1ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn/*
2ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * Copyright (C) 2010 The Android Open Source Project
3ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn *
4ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * you may not use this file except in compliance with the License.
6ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * You may obtain a copy of the License at
7ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn *
8ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn *
10ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * Unless required by applicable law or agreed to in writing, software
11ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * See the License for the specific language governing permissions and
14ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn * limitations under the License.
15ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn */
16ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
17ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornpackage com.android.settings.fuelgauge;
18ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
19ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.Context;
2039b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.content.Intent;
21ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.res.ColorStateList;
22ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.res.TypedArray;
2339b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.graphics.Bitmap;
24ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.graphics.Canvas;
2539b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.graphics.DashPathEffect;
26ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.graphics.Paint;
274f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackbornimport android.graphics.Path;
28ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.graphics.Typeface;
29ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.os.BatteryStats;
304f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackbornimport android.os.BatteryStats.HistoryItem;
3139b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.os.SystemClock;
32cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackbornimport android.telephony.ServiceState;
33ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.text.TextPaint;
3439b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.text.format.DateFormat;
3539b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.text.format.Formatter;
36ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.util.AttributeSet;
3739b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.util.Log;
3839b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.util.TimeUtils;
394f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackbornimport android.util.TypedValue;
40ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.view.View;
4139b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.settings.R;
4239b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.settings.Utils;
4327985e1f922eeb75da3214a7f88c63ac34dc4badJason Monkimport com.android.settingslib.BatteryInfo;
445a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport libcore.icu.LocaleData;
455a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
465a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport java.util.ArrayList;
475a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport java.util.Calendar;
48a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglioimport java.util.Locale;
49ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
50ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornpublic class BatteryHistoryChart extends View {
515a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    static final boolean DEBUG = false;
525a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    static final String TAG = "BatteryHistoryChart";
535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
5419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    static final int CHART_DATA_X_MASK = 0x0000ffff;
5519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    static final int CHART_DATA_BIN_MASK = 0xffff0000;
5619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    static final int CHART_DATA_BIN_SHIFT = 16;
5719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
5819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    static class ChartData {
5919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        int[] mColors;
6019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        Paint[] mPaints;
6119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
6219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        int mNumTicks;
6319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        int[] mTicks;
6419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        int mLastBin;
6519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
6619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        void setColors(int[] colors) {
6719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            mColors = colors;
6819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            mPaints = new Paint[colors.length];
6919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            for (int i=0; i<colors.length; i++) {
7019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mPaints[i] = new Paint();
7119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mPaints[i].setColor(colors[i]);
7219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mPaints[i].setStyle(Paint.Style.FILL);
7319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            }
7419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        }
7519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
7619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        void init(int width) {
7719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            if (width > 0) {
78916adce02d5b37038cd78d11a8c884237684f9a8Dianne Hackborn                mTicks = new int[width*2];
7919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            } else {
8019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mTicks = null;
8119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            }
8219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            mNumTicks = 0;
8319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            mLastBin = 0;
8419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        }
8519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
8619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        void addTick(int x, int bin) {
87916adce02d5b37038cd78d11a8c884237684f9a8Dianne Hackborn            if (bin != mLastBin && mNumTicks < mTicks.length) {
881cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn                mTicks[mNumTicks] = (x&CHART_DATA_X_MASK) | (bin<<CHART_DATA_BIN_SHIFT);
8919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mNumTicks++;
9019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mLastBin = bin;
9119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            }
9219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        }
9319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
9419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        void finish(int width) {
9519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            if (mLastBin != 0) {
9619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                addTick(width, 0);
9719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            }
9819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        }
9919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
10019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        void draw(Canvas canvas, int top, int height) {
10119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            int lastBin=0, lastX=0;
10219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            int bottom = top + height;
10319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            for (int i=0; i<mNumTicks; i++) {
10419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                int tick = mTicks[i];
10519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                int x = tick&CHART_DATA_X_MASK;
10619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                int bin = (tick&CHART_DATA_BIN_MASK) >> CHART_DATA_BIN_SHIFT;
10719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                if (lastBin != 0) {
10819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    canvas.drawRect(lastX, top, x, bottom, mPaints[lastBin]);
10919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                }
11019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                lastBin = bin;
11119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                lastX = x;
11219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            }
11319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
11419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        }
11519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    }
11619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
1174f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    static final int SANS = 1;
1184f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    static final int SERIF = 2;
1194f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    static final int MONOSPACE = 3;
1204f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn
12119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    // First value if for phone off; first value is "scanning"; following values
122cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    // are battery stats signal strength buckets.
123cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    static final int NUM_PHONE_SIGNALS = 7;
124cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
1254f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    final Paint mBatteryBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1264f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    final Paint mBatteryGoodPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1274f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    final Paint mBatteryWarnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1284f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    final Paint mBatteryCriticalPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1295a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final Paint mTimeRemainPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
130cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    final Paint mChargingPaint = new Paint();
131cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    final Paint mScreenOnPaint = new Paint();
132cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    final Paint mGpsOnPaint = new Paint();
1332627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk    final Paint mFlashlightOnPaint = new Paint();
1342627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk    final Paint mCameraOnPaint = new Paint();
135be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    final Paint mWifiRunningPaint = new Paint();
13655985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn    final Paint mCpuRunningPaint = new Paint();
1375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final Paint mDateLinePaint = new Paint();
13819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    final ChartData mPhoneSignalChart = new ChartData();
139ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    final TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
1400be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    final TextPaint mHeaderTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
1415a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final Paint mDebugRectPaint = new Paint();
1420be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
14312fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn    final Path mBatLevelPath = new Path();
14412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn    final Path mBatGoodPath = new Path();
14512fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn    final Path mBatWarnPath = new Path();
14612fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn    final Path mBatCriticalPath = new Path();
1475a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final Path mTimeRemainPath = new Path();
14812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn    final Path mChargingPath = new Path();
14912fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn    final Path mScreenOnPath = new Path();
150cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    final Path mGpsOnPath = new Path();
1512627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk    final Path mFlashlightOnPath = new Path();
1522627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk    final Path mCameraOnPath = new Path();
153be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    final Path mWifiRunningPath = new Path();
15455985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn    final Path mCpuRunningPath = new Path();
1555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final Path mDateLinePath = new Path();
1563069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk
157ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    BatteryStats mStats;
1580be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    Intent mBatteryBroadcast;
159ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    long mStatsPeriod;
1605a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    String mMaxPercentLabelString;
1615a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    String mMinPercentLabelString;
162ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    String mDurationString;
1630be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    String mChargeDurationString;
1640be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    String mDrainString;
165cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    String mChargingLabel;
166cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    String mScreenOnLabel;
167cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    String mGpsOnLabel;
1682627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk    String mCameraOnLabel;
1692627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk    String mFlashlightOnLabel;
170be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    String mWifiRunningLabel;
17155985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn    String mCpuRunningLabel;
172cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    String mPhoneSignalLabel;
1737158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
1743069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk    BatteryInfo mInfo;
1753069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk
1767158e6299210d08f82c29135c001652508b79dfbDianne Hackborn    int mChartMinHeight;
1777158e6299210d08f82c29135c001652508b79dfbDianne Hackborn    int mHeaderHeight;
1787158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
1797158e6299210d08f82c29135c001652508b79dfbDianne Hackborn    int mBatteryWarnLevel;
1807158e6299210d08f82c29135c001652508b79dfbDianne Hackborn    int mBatteryCriticalLevel;
1817158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
182ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mTextAscent;
183ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mTextDescent;
1840be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    int mHeaderTextAscent;
1850be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    int mHeaderTextDescent;
1865a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mMaxPercentLabelStringWidth;
1875a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mMinPercentLabelStringWidth;
188ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mDurationStringWidth;
1890be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    int mChargeLabelStringWidth;
1900be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    int mChargeDurationStringWidth;
1910be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    int mDrainStringWidth;
192cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
193cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    boolean mLargeMode;
194cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
1955a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mLastWidth = -1;
1965a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mLastHeight = -1;
1975a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
198cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mLineWidth;
199cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mThinLineWidth;
200cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mChargingOffset;
201cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mScreenOnOffset;
202cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mGpsOnOffset;
2032627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk    int mFlashlightOnOffset;
2042627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk    int mCameraOnOffset;
205be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    int mWifiRunningOffset;
20655985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn    int mCpuRunningOffset;
207cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mPhoneSignalOffset;
208cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mLevelOffset;
209cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mLevelTop;
210cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mLevelBottom;
2115a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mLevelLeft;
2125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mLevelRight;
2133bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn
214ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mNumHist;
215ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    long mHistStart;
2165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    long mHistDataEnd;
217ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    long mHistEnd;
2185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    long mStartWallTime;
2195a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    long mEndDataWallTime;
2205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    long mEndWallTime;
221ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mBatLow;
222ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mBatHigh;
223be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    boolean mHaveWifi;
224be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    boolean mHaveGps;
225c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani    boolean mHavePhoneSignal;
2262627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk    boolean mHaveCamera;
2272627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk    boolean mHaveFlashlight;
2280be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2295a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final ArrayList<TimeLabel> mTimeLabels = new ArrayList<TimeLabel>();
2305a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final ArrayList<DateLabel> mDateLabels = new ArrayList<DateLabel>();
2315a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
2326fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    Bitmap mBitmap;
2336fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    Canvas mCanvas;
2346fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
2350be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    static class TextAttrs {
2360be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        ColorStateList textColor = null;
2370be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        int textSize = 15;
2380be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        int typefaceIndex = -1;
2390be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        int styleIndex = -1;
2400be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2410be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        void retrieve(Context context, TypedArray from, int index) {
2420be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            TypedArray appearance = null;
2430be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            int ap = from.getResourceId(index, -1);
2440be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            if (ap != -1) {
2450be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                appearance = context.obtainStyledAttributes(ap,
2460be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                                    com.android.internal.R.styleable.TextAppearance);
2470be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            }
2480be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            if (appearance != null) {
2490be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                int n = appearance.getIndexCount();
2500be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                for (int i = 0; i < n; i++) {
2510be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    int attr = appearance.getIndex(i);
2520be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2530be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    switch (attr) {
2540be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    case com.android.internal.R.styleable.TextAppearance_textColor:
2550be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        textColor = appearance.getColorStateList(attr);
2560be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        break;
2570be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2580be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    case com.android.internal.R.styleable.TextAppearance_textSize:
2590be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        textSize = appearance.getDimensionPixelSize(attr, textSize);
2600be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        break;
2610be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2620be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    case com.android.internal.R.styleable.TextAppearance_typeface:
2630be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        typefaceIndex = appearance.getInt(attr, -1);
2640be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        break;
2650be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2660be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    case com.android.internal.R.styleable.TextAppearance_textStyle:
2670be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        styleIndex = appearance.getInt(attr, -1);
2680be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        break;
2690be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    }
2700be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                }
2710be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2720be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                appearance.recycle();
2730be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            }
2740be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        }
2750be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2760be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        void apply(Context context, TextPaint paint) {
2770be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            paint.density = context.getResources().getDisplayMetrics().density;
2780be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            paint.setCompatibilityScaling(
2790be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    context.getResources().getCompatibilityInfo().applicationScale);
2800be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2810be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            paint.setColor(textColor.getDefaultColor());
2820be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            paint.setTextSize(textSize);
2830be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2840be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            Typeface tf = null;
2850be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            switch (typefaceIndex) {
2860be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                case SANS:
2870be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    tf = Typeface.SANS_SERIF;
2880be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    break;
2890be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2900be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                case SERIF:
2910be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    tf = Typeface.SERIF;
2920be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    break;
2930be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2940be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                case MONOSPACE:
2950be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    tf = Typeface.MONOSPACE;
2960be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    break;
2970be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            }
2980be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2990be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            setTypeface(paint, tf, styleIndex);
3000be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        }
3010be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
3020be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        public void setTypeface(TextPaint paint, Typeface tf, int style) {
3030be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            if (style > 0) {
3040be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                if (tf == null) {
3050be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    tf = Typeface.defaultFromStyle(style);
3060be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                } else {
3070be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    tf = Typeface.create(tf, style);
3080be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                }
3090be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
3100be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setTypeface(tf);
3110be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                // now compute what (if any) algorithmic styling is needed
3120be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                int typefaceStyle = tf != null ? tf.getStyle() : 0;
3130be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                int need = style & ~typefaceStyle;
3140be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setFakeBoldText((need & Typeface.BOLD) != 0);
3150be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0);
3160be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            } else {
3170be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setFakeBoldText(false);
3180be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setTextSkewX(0);
3190be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setTypeface(tf);
3200be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            }
3210be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        }
3220be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    }
3230be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
3245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    static class TimeLabel {
3255a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final int x;
3265a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final String label;
3275a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final int width;
3285a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
329a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio        TimeLabel(TextPaint paint, int x, Calendar cal, boolean use24hr) {
3305a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            this.x = x;
331a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio            final String bestFormat = DateFormat.getBestDateTimePattern(
332a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio                    Locale.getDefault(), use24hr ? "km" : "ha");
333a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio            label = DateFormat.format(bestFormat, cal).toString();
3345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            width = (int)paint.measureText(label);
3355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
3365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
3375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
3385a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    static class DateLabel {
3395a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final int x;
3405a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final String label;
3415a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final int width;
3425a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
343a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio        DateLabel(TextPaint paint, int x, Calendar cal, boolean dayFirst) {
3445a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            this.x = x;
345a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio            final String bestFormat = DateFormat.getBestDateTimePattern(
346a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio                    Locale.getDefault(), dayFirst ? "dM" : "Md");
347a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio            label = DateFormat.format(bestFormat, cal).toString();
3485a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            width = (int)paint.measureText(label);
3495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
3505a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
3515a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
352ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    public BatteryHistoryChart(Context context, AttributeSet attrs) {
353ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        super(context, attrs);
3547158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
3556fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        if (DEBUG) Log.d(TAG, "New BatteryHistoryChart!");
3566fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
3577158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryWarnLevel = mContext.getResources().getInteger(
3587158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                com.android.internal.R.integer.config_lowBatteryWarningLevel);
3597158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryCriticalLevel = mContext.getResources().getInteger(
3607158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                com.android.internal.R.integer.config_criticalBatteryWarningLevel);
3617158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
3625a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mThinLineWidth = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
3635a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                2, getResources().getDisplayMetrics());
3645a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
3657158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryBackgroundPaint.setColor(0xFF009688);
3664f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        mBatteryBackgroundPaint.setStyle(Paint.Style.FILL);
3677158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryGoodPaint.setARGB(128, 0, 128, 0);
36812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatteryGoodPaint.setStyle(Paint.Style.STROKE);
3697158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryWarnPaint.setARGB(128, 128, 128, 0);
37012fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatteryWarnPaint.setStyle(Paint.Style.STROKE);
3717158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryCriticalPaint.setARGB(192, 128, 0, 0);
37212fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatteryCriticalPaint.setStyle(Paint.Style.STROKE);
3737158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mTimeRemainPaint.setColor(0xFFCED7BB);
3745a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mTimeRemainPaint.setStyle(Paint.Style.FILL);
37512fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mChargingPaint.setStyle(Paint.Style.STROKE);
37612fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mScreenOnPaint.setStyle(Paint.Style.STROKE);
377cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mGpsOnPaint.setStyle(Paint.Style.STROKE);
3782627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mCameraOnPaint.setStyle(Paint.Style.STROKE);
3792627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mFlashlightOnPaint.setStyle(Paint.Style.STROKE);
380be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        mWifiRunningPaint.setStyle(Paint.Style.STROKE);
38155985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        mCpuRunningPaint.setStyle(Paint.Style.STROKE);
38268f005fbd48f18cdab0168ba92b8fd40776edc1eDianne Hackborn        mPhoneSignalChart.setColors(com.android.settings.Utils.BADNESS_COLORS);
3835a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDebugRectPaint.setARGB(255, 255, 0, 0);
3845a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDebugRectPaint.setStyle(Paint.Style.STROKE);
3853bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn        mScreenOnPaint.setColor(0xFF009688);
3863bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn        mGpsOnPaint.setColor(0xFF009688);
3872627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mCameraOnPaint.setColor(0xFF009688);
3882627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mFlashlightOnPaint.setColor(0xFF009688);
3893bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn        mWifiRunningPaint.setColor(0xFF009688);
3903bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn        mCpuRunningPaint.setColor(0xFF009688);
3913bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn        mChargingPaint.setColor(0xFF009688);
3925a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
393ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        TypedArray a =
394ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            context.obtainStyledAttributes(
395ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                attrs, R.styleable.BatteryHistoryChart, 0, 0);
396ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
3970be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final TextAttrs mainTextAttrs = new TextAttrs();
3980be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final TextAttrs headTextAttrs = new TextAttrs();
3990be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mainTextAttrs.retrieve(context, a, R.styleable.BatteryHistoryChart_android_textAppearance);
4000be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        headTextAttrs.retrieve(context, a, R.styleable.BatteryHistoryChart_headerAppearance);
401ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
402ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        int shadowcolor = 0;
403ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        float dx=0, dy=0, r=0;
404ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
405ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        int n = a.getIndexCount();
406ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        for (int i = 0; i < n; i++) {
407ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            int attr = a.getIndex(i);
408ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
409ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            switch (attr) {
410ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_shadowColor:
411ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    shadowcolor = a.getInt(attr, 0);
412ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
413ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
414ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_shadowDx:
415ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    dx = a.getFloat(attr, 0);
416ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
417ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
418ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_shadowDy:
419ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    dy = a.getFloat(attr, 0);
420ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
421ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
422ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_shadowRadius:
423ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    r = a.getFloat(attr, 0);
424ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
425ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
426ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_textColor:
4270be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    mainTextAttrs.textColor = a.getColorStateList(attr);
4280be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    headTextAttrs.textColor = a.getColorStateList(attr);
429ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
430ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
431ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_textSize:
4320be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    mainTextAttrs.textSize = a.getDimensionPixelSize(attr, mainTextAttrs.textSize);
4330be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    headTextAttrs.textSize = a.getDimensionPixelSize(attr, headTextAttrs.textSize);
434ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
435ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
436ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_typeface:
4370be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    mainTextAttrs.typefaceIndex = a.getInt(attr, mainTextAttrs.typefaceIndex);
4380be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    headTextAttrs.typefaceIndex = a.getInt(attr, headTextAttrs.typefaceIndex);
439ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
440ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
441ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_textStyle:
4420be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    mainTextAttrs.styleIndex = a.getInt(attr, mainTextAttrs.styleIndex);
4430be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    headTextAttrs.styleIndex = a.getInt(attr, headTextAttrs.styleIndex);
444ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
4457158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
4467158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                case R.styleable.BatteryHistoryChart_barPrimaryColor:
4477158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    mBatteryBackgroundPaint.setColor(a.getInt(attr, 0));
4483bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn                    mScreenOnPaint.setColor(a.getInt(attr, 0));
4493bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn                    mGpsOnPaint.setColor(a.getInt(attr, 0));
4502627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                    mCameraOnPaint.setColor(a.getInt(attr, 0));
4512627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                    mFlashlightOnPaint.setColor(a.getInt(attr, 0));
4523bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn                    mWifiRunningPaint.setColor(a.getInt(attr, 0));
4533bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn                    mCpuRunningPaint.setColor(a.getInt(attr, 0));
4543bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn                    mChargingPaint.setColor(a.getInt(attr, 0));
4557158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    break;
4567158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
4577158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                case R.styleable.BatteryHistoryChart_barPredictionColor:
4587158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    mTimeRemainPaint.setColor(a.getInt(attr, 0));
4597158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    break;
4607158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
4617158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                case R.styleable.BatteryHistoryChart_chartMinHeight:
4627158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    mChartMinHeight = a.getDimensionPixelSize(attr, 0);
4637158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    break;
464ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            }
465ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
466ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
467d2be882d8f2e5acd8a5806c649ba4640249cf4baDianne Hackborn        a.recycle();
468d2be882d8f2e5acd8a5806c649ba4640249cf4baDianne Hackborn
4690be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mainTextAttrs.apply(context, mTextPaint);
4700be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        headTextAttrs.apply(context, mHeaderTextPaint);
4710be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
4725a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDateLinePaint.set(mTextPaint);
4735a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDateLinePaint.setStyle(Paint.Style.STROKE);
4745a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        int hairlineWidth = mThinLineWidth/2;
4755a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (hairlineWidth < 1) {
4765a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            hairlineWidth = 1;
4775a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
4785a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDateLinePaint.setStrokeWidth(hairlineWidth);
4795a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDateLinePaint.setPathEffect(new DashPathEffect(new float[] {
4805a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mThinLineWidth * 2, mThinLineWidth * 2 }, 0));
4815a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
482ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (shadowcolor != 0) {
483ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            mTextPaint.setShadowLayer(r, dx, dy, shadowcolor);
4840be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            mHeaderTextPaint.setShadowLayer(r, dx, dy, shadowcolor);
485ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
486ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
4875a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
4880be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    void setStats(BatteryStats stats, Intent broadcast) {
489ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mStats = stats;
4900be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mBatteryBroadcast = broadcast;
4910be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
4926fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        if (DEBUG) Log.d(TAG, "Setting stats...");
4936fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
4940be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
4950be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
4960be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        long uSecTime = mStats.computeBatteryRealtime(elapsedRealtimeUs,
4974f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn                BatteryStats.STATS_SINCE_CHARGED);
498ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mStatsPeriod = uSecTime;
499cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mChargingLabel = getContext().getString(R.string.battery_stats_charging_label);
500cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mScreenOnLabel = getContext().getString(R.string.battery_stats_screen_on_label);
501cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mGpsOnLabel = getContext().getString(R.string.battery_stats_gps_on_label);
5022627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mCameraOnLabel = getContext().getString(R.string.battery_stats_camera_on_label);
5032627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mFlashlightOnLabel = getContext().getString(R.string.battery_stats_flashlight_on_label);
504be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        mWifiRunningLabel = getContext().getString(R.string.battery_stats_wifi_running_label);
50555985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        mCpuRunningLabel = getContext().getString(R.string.battery_stats_wake_lock_label);
506cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mPhoneSignalLabel = getContext().getString(R.string.battery_stats_phone_signal_label);
5075a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
5087253df35a09d8d61ececedbb66179171802e42a7Elliott Hughes        mMaxPercentLabelString = Utils.formatPercentage(100);
5097253df35a09d8d61ececedbb66179171802e42a7Elliott Hughes        mMinPercentLabelString = Utils.formatPercentage(0);
51027985e1f922eeb75da3214a7f88c63ac34dc4badJason Monk        mInfo = BatteryInfo.getBatteryInfo(getContext(), mBatteryBroadcast, mStats,
51127985e1f922eeb75da3214a7f88c63ac34dc4badJason Monk                elapsedRealtimeUs);
5125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDrainString = "";
5135a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mChargeDurationString = "";
5143069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        setContentDescription(mInfo.mChargeLabelString);
5155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
516ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        int pos = 0;
5174f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        int lastInteresting = 0;
5184f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        byte lastLevel = -1;
519ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mBatLow = 0;
520ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mBatHigh = 100;
5215a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mStartWallTime = 0;
5225a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mEndDataWallTime = 0;
5235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mEndWallTime = 0;
5245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mHistStart = 0;
5255a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mHistEnd = 0;
5265a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        long lastWallTime = 0;
5275a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        long lastRealtime = 0;
528be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        int aggrStates = 0;
52996debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn        int aggrStates2 = 0;
53019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        boolean first = true;
53119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        if (stats.startIteratingHistoryLocked()) {
53219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            final HistoryItem rec = new HistoryItem();
53319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            while (stats.getNextHistoryLocked(rec)) {
53419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                pos++;
5355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (first) {
5365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    first = false;
5375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    mHistStart = rec.time;
5385a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                }
5395a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
5405a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        || rec.cmd == HistoryItem.CMD_RESET) {
5412b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    // If there is a ridiculously large jump in time, then we won't be
5422b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    // able to create a good chart with that data, so just ignore the
5432b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    // times we got before and pretend like our data extends back from
5442b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    // the time we have now.
54594aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                    // Also, if we are getting a time change and we are less than 5 minutes
54694aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                    // since the start of the history real time, then also use this new
54794aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                    // time to compute the base time, since whatever time we had before is
54894aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                    // pretty much just noise.
54994aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                    if (rec.currentTime > (lastWallTime+(180*24*60*60*1000L))
55094aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                            || rec.time < (mHistStart+(5*60*1000L))) {
5512b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        mStartWallTime = 0;
5522b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    }
5535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    lastWallTime = rec.currentTime;
5545a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    lastRealtime = rec.time;
5555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (mStartWallTime == 0) {
5562b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        mStartWallTime = lastWallTime - (lastRealtime-mHistStart);
55719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    }
5585a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                }
5595a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (rec.isDeltaData()) {
56019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    if (rec.batteryLevel != lastLevel || pos == 1) {
56119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                        lastLevel = rec.batteryLevel;
56219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    }
563b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn                    lastInteresting = pos;
5645a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    mHistDataEnd = rec.time;
56519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    aggrStates |= rec.states;
56696debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                    aggrStates2 |= rec.states2;
567b9b7e5c863c9dda33cacc9978ee8c98b6b395d60Dianne Hackborn                }
568ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            }
569ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
5703069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        mHistEnd = mHistDataEnd + (mInfo.remainingTimeUs/1000);
5715a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mEndDataWallTime = lastWallTime + mHistDataEnd - lastRealtime;
5723069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        mEndWallTime = mEndDataWallTime + (mInfo.remainingTimeUs/1000);
5734f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        mNumHist = lastInteresting;
574be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        mHaveGps = (aggrStates&HistoryItem.STATE_GPS_ON_FLAG) != 0;
5752627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mHaveFlashlight = (aggrStates2&HistoryItem.STATE2_FLASHLIGHT_FLAG) != 0;
5762627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mHaveCamera = (aggrStates2&HistoryItem.STATE2_CAMERA_FLAG) != 0;
57796debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn        mHaveWifi = (aggrStates2&HistoryItem.STATE2_WIFI_RUNNING_FLAG) != 0
57896debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                || (aggrStates&(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG
57996debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        |HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG
58096debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        |HistoryItem.STATE_WIFI_SCAN_FLAG)) != 0;
5818af88fb8387259e51615709b2d1ea0260f7057fdRobert Greenwalt        if (!com.android.settings.Utils.isWifiOnly(getContext())) {
582c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            mHavePhoneSignal = true;
583c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        }
584ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (mHistEnd <= mHistStart) mHistEnd = mHistStart+1;
585ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
586ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
587ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    @Override
588ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
5895a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mMaxPercentLabelStringWidth = (int)mTextPaint.measureText(mMaxPercentLabelString);
5905a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mMinPercentLabelStringWidth = (int)mTextPaint.measureText(mMinPercentLabelString);
5910be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mDrainStringWidth = (int)mHeaderTextPaint.measureText(mDrainString);
5923069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        mChargeLabelStringWidth = (int)mHeaderTextPaint.measureText(mInfo.mChargeLabelString);
5930be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mChargeDurationStringWidth = (int)mHeaderTextPaint.measureText(mChargeDurationString);
594ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mTextAscent = (int)mTextPaint.ascent();
595ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mTextDescent = (int)mTextPaint.descent();
5960be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mHeaderTextAscent = (int)mHeaderTextPaint.ascent();
5970be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mHeaderTextDescent = (int)mHeaderTextPaint.descent();
5987158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        int headerTextHeight = mHeaderTextDescent - mHeaderTextAscent;
5997158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mHeaderHeight = headerTextHeight*2 - mTextAscent;
6007158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
6017158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                getDefaultSize(mChartMinHeight+mHeaderHeight, heightMeasureSpec));
602ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
603ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
60412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn    void finishPaths(int w, int h, int levelh, int startX, int y, Path curLevelPath,
605cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            int lastX, boolean lastCharging, boolean lastScreenOn, boolean lastGpsOn,
6062627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            boolean lastFlashlightOn, boolean lastCameraOn, boolean lastWifiRunning,
6072627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            boolean lastCpuRunning, Path lastPath) {
60812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        if (curLevelPath != null) {
609c01b0c83fca571229621d16b757a46dc0fae7dfeDianne Hackborn            if (lastX >= 0 && lastX < w) {
61012fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                if (lastPath != null) {
61112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                    lastPath.lineTo(w, y);
61212fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                }
61312fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                curLevelPath.lineTo(w, y);
61412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            }
615cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            curLevelPath.lineTo(w, mLevelTop+levelh);
616cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            curLevelPath.lineTo(startX, mLevelTop+levelh);
61712fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            curLevelPath.close();
61812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
61912fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn
620cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (lastCharging) {
62112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            mChargingPath.lineTo(w, h-mChargingOffset);
62212fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
623cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (lastScreenOn) {
62412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            mScreenOnPath.lineTo(w, h-mScreenOnOffset);
62512fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
626cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (lastGpsOn) {
627cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            mGpsOnPath.lineTo(w, h-mGpsOnOffset);
628cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
6292627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        if (lastFlashlightOn) {
6302627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            mFlashlightOnPath.lineTo(w, h-mFlashlightOnOffset);
6312627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        }
6322627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        if (lastCameraOn) {
6332627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            mCameraOnPath.lineTo(w, h-mCameraOnOffset);
6342627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        }
635be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        if (lastWifiRunning) {
636be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            mWifiRunningPath.lineTo(w, h-mWifiRunningOffset);
637be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        }
63855985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        if (lastCpuRunning) {
63955985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn            mCpuRunningPath.lineTo(w, h - mCpuRunningOffset);
640be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        }
641c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        if (mHavePhoneSignal) {
642c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            mPhoneSignalChart.finish(w);
643c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        }
64412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn    }
6455a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
6465a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    private boolean is24Hour() {
6475a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        return DateFormat.is24HourFormat(getContext());
6485a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
6495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
6505a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    private boolean isDayFirst() {
651ad53f0b936067dd9b3161b47abbfe5af6e87c4a1Narayan Kamath        final String value = LocaleData.get(getResources().getConfiguration().locale)
652ad53f0b936067dd9b3161b47abbfe5af6e87c4a1Narayan Kamath                .getDateFormat(java.text.DateFormat.SHORT);
6535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        return value.indexOf('M') > value.indexOf('d');
6545a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
6555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
656ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    @Override
657ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
658ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        super.onSizeChanged(w, h, oldw, oldh);
6595a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
6605a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "onSizeChanged: " + oldw + "x" + oldh + " to " + w + "x" + h);
6615a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
6625a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (mLastWidth == w && mLastHeight == h) {
6635a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            return;
6645a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
6655a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
666a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        if (mLastWidth == 0 || mLastHeight == 0) {
667a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn            return;
668a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        }
669a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn
6706fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        if (DEBUG) Log.d(TAG, "Rebuilding chart for: " + w + "x" + h);
6716fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
672a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        mLastWidth = w;
673a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        mLastHeight = h;
6746fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        mBitmap = null;
6756fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        mCanvas = null;
676a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn
677cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        int textHeight = mTextDescent - mTextAscent;
6787158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        if (h > ((textHeight*10)+mChartMinHeight)) {
679cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            mLargeMode = true;
680b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn            if (h > (textHeight*15)) {
681b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn                // Plenty of room for the chart.
682b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn                mLineWidth = textHeight/2;
683b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn            } else {
684b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn                // Compress lines to make more room for chart.
685b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn                mLineWidth = textHeight/3;
686b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn            }
687cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        } else {
688cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            mLargeMode = false;
689cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            mLineWidth = mThinLineWidth;
690cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
691cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (mLineWidth <= 0) mLineWidth = 1;
6925a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
6937158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mLevelTop = mHeaderHeight;
6945a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mLevelLeft = mMaxPercentLabelStringWidth + mThinLineWidth*3;
6955a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mLevelRight = w;
6965a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        int levelWidth = mLevelRight-mLevelLeft;
6975a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
698cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mTextPaint.setStrokeWidth(mThinLineWidth);
699cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mBatteryGoodPaint.setStrokeWidth(mThinLineWidth);
700cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mBatteryWarnPaint.setStrokeWidth(mThinLineWidth);
701cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mBatteryCriticalPaint.setStrokeWidth(mThinLineWidth);
702cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mChargingPaint.setStrokeWidth(mLineWidth);
703cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mScreenOnPaint.setStrokeWidth(mLineWidth);
704cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mGpsOnPaint.setStrokeWidth(mLineWidth);
7052627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mCameraOnPaint.setStrokeWidth(mLineWidth);
7062627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mFlashlightOnPaint.setStrokeWidth(mLineWidth);
707be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        mWifiRunningPaint.setStrokeWidth(mLineWidth);
70855985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        mCpuRunningPaint.setStrokeWidth(mLineWidth);
7095a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDebugRectPaint.setStrokeWidth(1);
7105a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
7115a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        int fullBarOffset = textHeight + mLineWidth;
712cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
713cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (mLargeMode) {
714be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            mChargingOffset = mLineWidth;
7155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mScreenOnOffset = mChargingOffset + fullBarOffset;
7165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mCpuRunningOffset = mScreenOnOffset + fullBarOffset;
7175a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mWifiRunningOffset = mCpuRunningOffset + fullBarOffset;
7185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mGpsOnOffset = mWifiRunningOffset + (mHaveWifi ? fullBarOffset : 0);
7192627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            mFlashlightOnOffset = mGpsOnOffset + (mHaveGps ? fullBarOffset : 0);
7202627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            mCameraOnOffset = mFlashlightOnOffset + (mHaveFlashlight ? fullBarOffset : 0);
7212627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            mPhoneSignalOffset = mCameraOnOffset + (mHaveCamera ? fullBarOffset : 0);
7225a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mLevelOffset = mPhoneSignalOffset + (mHavePhoneSignal ? fullBarOffset : 0)
7235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    + mLineWidth*2 + mLineWidth/2;
724c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            if (mHavePhoneSignal) {
725c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani                mPhoneSignalChart.init(w);
726c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            }
727cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        } else {
7282627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            mScreenOnOffset = mGpsOnOffset = mCameraOnOffset = mFlashlightOnOffset =
7292627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                    mWifiRunningOffset = mCpuRunningOffset = mChargingOffset =
7302627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                    mPhoneSignalOffset = 0;
7315a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mLevelOffset = fullBarOffset + mThinLineWidth*4;
732c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            if (mHavePhoneSignal) {
733c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani                mPhoneSignalChart.init(0);
734c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            }
735cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
736cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
7374f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        mBatLevelPath.reset();
73812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatGoodPath.reset();
73912fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatWarnPath.reset();
7405a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mTimeRemainPath.reset();
74112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatCriticalPath.reset();
74212fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mScreenOnPath.reset();
743cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mGpsOnPath.reset();
7442627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mFlashlightOnPath.reset();
7452627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        mCameraOnPath.reset();
746be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        mWifiRunningPath.reset();
74755985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        mCpuRunningPath.reset();
74812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mChargingPath.reset();
7495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
750a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        mTimeLabels.clear();
751a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        mDateLabels.clear();
752a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn
7535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final long walltimeStart = mStartWallTime;
754c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn        final long walltimeChange = mEndWallTime > walltimeStart
755c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                ? (mEndWallTime-walltimeStart) : 1;
7562b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn        long curWalltime = mStartWallTime;
7575a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        long lastRealtime = 0;
7585a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
759ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final int batLow = mBatLow;
760ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final int batChange = mBatHigh-mBatLow;
7615a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
762cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        final int levelh = h - mLevelOffset - mLevelTop;
763cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mLevelBottom = mLevelTop + levelh;
7645a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
7655a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        int x = mLevelLeft, y = 0, startX = mLevelLeft, lastX = -1, lastY = -1;
76612fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        int i = 0;
76712fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        Path curLevelPath = null;
76812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        Path lastLinePath = null;
769cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        boolean lastCharging = false, lastScreenOn = false, lastGpsOn = false;
7702627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        boolean lastFlashlightOn = false, lastCameraOn = false;
77196debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn        boolean lastWifiRunning = false, lastWifiSupplRunning = false, lastCpuRunning = false;
77296debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn        int lastWifiSupplState = BatteryStats.WIFI_SUPPL_STATE_INVALID;
773ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final int N = mNumHist;
7742b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn        if (mEndDataWallTime > mStartWallTime && mStats.startIteratingHistoryLocked()) {
77519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            final HistoryItem rec = new HistoryItem();
77619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            while (mStats.getNextHistoryLocked(rec) && i < N) {
7772b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                if (rec.isDeltaData()) {
7785a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    curWalltime += rec.time-lastRealtime;
7795a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    lastRealtime = rec.time;
7805a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    x = mLevelLeft + (int)(((curWalltime-walltimeStart)*levelWidth)/walltimeChange);
7811cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn                    if (x < 0) {
7821cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn                        x = 0;
7831cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn                    }
7845a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (false) {
7855a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        StringBuilder sb = new StringBuilder(128);
7865a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        sb.append("walloff=");
7875a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        TimeUtils.formatDuration(curWalltime - walltimeStart, sb);
7885a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        sb.append(" wallchange=");
7895a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        TimeUtils.formatDuration(walltimeChange, sb);
7905a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        sb.append(" x=");
7915a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        sb.append(x);
7925a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        Log.d("foo", sb.toString());
7935a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
79419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    y = mLevelTop + levelh - ((rec.batteryLevel-batLow)*(levelh-1))/batChange;
79519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
79619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    if (lastX != x) {
79719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                        // We have moved by at least a pixel.
79819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                        if (lastY != y) {
79919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            // Don't plot changes within a pixel.
80019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            Path path;
80119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            byte value = rec.batteryLevel;
8027158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                            if (value <= mBatteryCriticalLevel) path = mBatCriticalPath;
8037158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                            else if (value <= mBatteryWarnLevel) path = mBatWarnPath;
8047158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                            else path = null; //mBatGoodPath;
80519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
80619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            if (path != lastLinePath) {
80719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                if (lastLinePath != null) {
80819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                    lastLinePath.lineTo(x, y);
80919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                }
8107158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                                if (path != null) {
8117158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                                    path.moveTo(x, y);
8127158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                                }
81319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                lastLinePath = path;
8147158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                            } else if (path != null) {
81519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                path.lineTo(x, y);
81619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            }
81719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
81819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            if (curLevelPath == null) {
81919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                curLevelPath = mBatLevelPath;
82019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                curLevelPath.moveTo(x, y);
82119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                startX = x;
82219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            } else {
82319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                curLevelPath.lineTo(x, y);
82412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                            }
82519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            lastX = x;
82619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            lastY = y;
82712fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                        }
82856247a63fc621815ecff82a278ad8553174922a0Todd Poynor                    }
82919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
8305a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (mLargeMode) {
8315a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        final boolean charging =
8325a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            (rec.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) != 0;
8335a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (charging != lastCharging) {
8345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (charging) {
8355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mChargingPath.moveTo(x, h-mChargingOffset);
8365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
8375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mChargingPath.lineTo(x, h-mChargingOffset);
8385a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
8395a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            lastCharging = charging;
84012fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                        }
841cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
8425a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        final boolean screenOn =
8435a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            (rec.states&HistoryItem.STATE_SCREEN_ON_FLAG) != 0;
8445a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (screenOn != lastScreenOn) {
8455a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (screenOn) {
8465a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mScreenOnPath.moveTo(x, h-mScreenOnOffset);
8475a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
8485a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mScreenOnPath.lineTo(x, h-mScreenOnOffset);
8495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
8505a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            lastScreenOn = screenOn;
85112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                        }
852cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
8535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        final boolean gpsOn =
8545a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            (rec.states&HistoryItem.STATE_GPS_ON_FLAG) != 0;
8555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (gpsOn != lastGpsOn) {
8565a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (gpsOn) {
8575a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mGpsOnPath.moveTo(x, h-mGpsOnOffset);
8585a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
8595a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mGpsOnPath.lineTo(x, h-mGpsOnOffset);
8605a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
8615a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            lastGpsOn = gpsOn;
862cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn                        }
863cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
8642627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                        final boolean flashlightOn =
8652627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            (rec.states2&HistoryItem.STATE2_FLASHLIGHT_FLAG) != 0;
8662627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                        if (flashlightOn != lastFlashlightOn) {
8672627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            if (flashlightOn) {
8682627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                                mFlashlightOnPath.moveTo(x, h-mFlashlightOnOffset);
8692627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            } else {
8702627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                                mFlashlightOnPath.lineTo(x, h-mFlashlightOnOffset);
8712627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            }
8722627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            lastFlashlightOn = flashlightOn;
8732627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                        }
8742627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk
8752627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                        final boolean cameraOn =
8762627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            (rec.states2&HistoryItem.STATE2_CAMERA_FLAG) != 0;
8772627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                        if (cameraOn != lastCameraOn) {
8782627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            if (cameraOn) {
8792627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                                mCameraOnPath.moveTo(x, h-mCameraOnOffset);
8802627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            } else {
8812627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                                mCameraOnPath.lineTo(x, h-mCameraOnOffset);
8822627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            }
8832627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            lastCameraOn = cameraOn;
8842627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                        }
8852627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk
88696debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        final int wifiSupplState =
88796debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            ((rec.states2&HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
88896debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                    >> HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
88996debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        boolean wifiRunning;
89096debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        if (lastWifiSupplState != wifiSupplState) {
89196debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            lastWifiSupplState = wifiSupplState;
89296debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            switch (wifiSupplState) {
89396debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_DISCONNECTED:
89496debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_DORMANT:
89596debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_INACTIVE:
89696debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_INTERFACE_DISABLED:
89796debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_INVALID:
89896debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_UNINITIALIZED:
89996debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                    wifiRunning = lastWifiSupplRunning = false;
90096debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                    break;
90196debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                default:
90296debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                    wifiRunning = lastWifiSupplRunning = true;
90396debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                    break;
90496debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            }
90596debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        } else {
90696debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            wifiRunning = lastWifiSupplRunning;
90796debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        }
90896debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        if ((rec.states&(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG
90996debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                |HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG
91096debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                |HistoryItem.STATE_WIFI_SCAN_FLAG)) != 0) {
91196debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            wifiRunning = true;
91296debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        }
9135a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (wifiRunning != lastWifiRunning) {
9145a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (wifiRunning) {
9155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mWifiRunningPath.moveTo(x, h-mWifiRunningOffset);
9165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
9175a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mWifiRunningPath.lineTo(x, h-mWifiRunningOffset);
9185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
9195a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            lastWifiRunning = wifiRunning;
920cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn                        }
921cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
9225a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        final boolean cpuRunning =
9235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            (rec.states&HistoryItem.STATE_CPU_RUNNING_FLAG) != 0;
9245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (cpuRunning != lastCpuRunning) {
9255a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (cpuRunning) {
9265a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mCpuRunningPath.moveTo(x, h - mCpuRunningOffset);
9275a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
9285a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mCpuRunningPath.lineTo(x, h - mCpuRunningOffset);
9295a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
9305a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            lastCpuRunning = cpuRunning;
931be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                        }
932be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn
9335a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (mLargeMode && mHavePhoneSignal) {
9345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            int bin;
9355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (((rec.states&HistoryItem.STATE_PHONE_STATE_MASK)
9365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                    >> HistoryItem.STATE_PHONE_STATE_SHIFT)
9375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                    == ServiceState.STATE_POWER_OFF) {
9385a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                bin = 0;
9395a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else if ((rec.states&HistoryItem.STATE_PHONE_SCANNING_FLAG) != 0) {
9405a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                bin = 1;
9415a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
94296debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                bin = (rec.states&HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
94396debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                        >> HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT;
9445a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                bin += 2;
9455a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
9465a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            mPhoneSignalChart.addTick(x, bin);
947be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                        }
948be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                    }
949be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn
9502b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                } else {
9512b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    long lastWalltime = curWalltime;
9522b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
9532b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            || rec.cmd == HistoryItem.CMD_RESET) {
9542b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        if (rec.currentTime >= mStartWallTime) {
9552b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            curWalltime = rec.currentTime;
9562b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        } else {
9572b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            curWalltime = mStartWallTime + (rec.time-mHistStart);
9582b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        }
9592b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        lastRealtime = rec.time;
9602b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    }
9612b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn
9622b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    if (rec.cmd != HistoryItem.CMD_OVERFLOW
9632b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            && (rec.cmd != HistoryItem.CMD_CURRENT_TIME
9642b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                                    || Math.abs(lastWalltime-curWalltime) > (60*60*1000))) {
9652b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        if (curLevelPath != null) {
9662b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            finishPaths(x+1, h, levelh, startX, lastY, curLevelPath, lastX,
9672627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                                    lastCharging, lastScreenOn, lastGpsOn, lastFlashlightOn,
9682627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                                    lastCameraOn, lastWifiRunning, lastCpuRunning, lastLinePath);
9692b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            lastX = lastY = -1;
9702b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            curLevelPath = null;
9712b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            lastLinePath = null;
9722627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                            lastCharging = lastScreenOn = lastGpsOn = lastFlashlightOn =
9732627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                                    lastCameraOn = lastCpuRunning = false;
9742b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        }
9754f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn                    }
9764f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn                }
97712fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn
97819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                i++;
979ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            }
9802b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn            mStats.finishIteratingHistoryLocked();
981ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
9825a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
983c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn        if (lastY < 0 || lastX < 0) {
984c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            // Didn't get any data...
985c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            x = lastX = mLevelLeft;
9863069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk            y = lastY = mLevelTop + levelh - ((mInfo.mBatteryLevel-batLow)*(levelh-1))/batChange;
987c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            Path path;
9883069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk            byte value = (byte)mInfo.mBatteryLevel;
989c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            if (value <= mBatteryCriticalLevel) path = mBatCriticalPath;
990c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            else if (value <= mBatteryWarnLevel) path = mBatWarnPath;
991c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            else path = null; //mBatGoodPath;
992c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            if (path != null) {
993c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                path.moveTo(x, y);
994c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                lastLinePath = path;
995c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            }
996c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            mBatLevelPath.moveTo(x, y);
997c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            curLevelPath = mBatLevelPath;
998c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            x = w;
999c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn        } else {
1000c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            // Figure out where the actual data ends on the screen.
1001c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            x = mLevelLeft + (int)(((mEndDataWallTime-walltimeStart)*levelWidth)/walltimeChange);
10021cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn            if (x < 0) {
10031cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn                x = 0;
10041cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn            }
1005c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn        }
10065a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
10075a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        finishPaths(x, h, levelh, startX, lastY, curLevelPath, lastX,
10082627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                lastCharging, lastScreenOn, lastGpsOn, lastFlashlightOn, lastCameraOn,
10092627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                lastWifiRunning, lastCpuRunning, lastLinePath);
10105a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
10115a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (x < w) {
10125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            // If we reserved room for the remaining time, create a final path to draw
10135a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            // that part of the UI.
10145a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mTimeRemainPath.moveTo(x, lastY);
10155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int fullY = mLevelTop + levelh - ((100-batLow)*(levelh-1))/batChange;
10165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int emptyY = mLevelTop + levelh - ((0-batLow)*(levelh-1))/batChange;
10173069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk            if (mInfo.mDischarging) {
10185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mTimeRemainPath.lineTo(mLevelRight, emptyY);
10195a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            } else {
10205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mTimeRemainPath.lineTo(mLevelRight, fullY);
10215a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mTimeRemainPath.lineTo(mLevelRight, emptyY);
10225a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
10235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mTimeRemainPath.lineTo(x, emptyY);
10245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mTimeRemainPath.close();
10255a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
10265a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
1027c891ce6565fbeba8414c470b109088ac959f7143Dianne Hackborn        if (mStartWallTime > 0 && mEndWallTime > mStartWallTime) {
10287158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            // Create the time labels at the bottom.
10297158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            boolean is24hr = is24Hour();
10307158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            Calendar calStart = Calendar.getInstance();
10317158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calStart.setTimeInMillis(mStartWallTime);
10327158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calStart.set(Calendar.MILLISECOND, 0);
10337158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calStart.set(Calendar.SECOND, 0);
10347158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calStart.set(Calendar.MINUTE, 0);
10357158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            long startRoundTime = calStart.getTimeInMillis();
10365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (startRoundTime < mStartWallTime) {
10377158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calStart.set(Calendar.HOUR_OF_DAY, calStart.get(Calendar.HOUR_OF_DAY)+1);
10385a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                startRoundTime = calStart.getTimeInMillis();
10395a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
10407158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            Calendar calEnd = Calendar.getInstance();
10417158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calEnd.setTimeInMillis(mEndWallTime);
10427158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calEnd.set(Calendar.MILLISECOND, 0);
10437158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calEnd.set(Calendar.SECOND, 0);
10447158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calEnd.set(Calendar.MINUTE, 0);
10457158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            long endRoundTime = calEnd.getTimeInMillis();
10465a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (startRoundTime < endRoundTime) {
10477158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                addTimeLabel(calStart, mLevelLeft, mLevelRight, is24hr);
10487158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                Calendar calMid = Calendar.getInstance();
10497158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calMid.setTimeInMillis(mStartWallTime+((mEndWallTime-mStartWallTime)/2));
10507158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calMid.set(Calendar.MILLISECOND, 0);
10517158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calMid.set(Calendar.SECOND, 0);
10527158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calMid.set(Calendar.MINUTE, 0);
10537158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                long calMidMillis = calMid.getTimeInMillis();
10547158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                if (calMidMillis > startRoundTime && calMidMillis < endRoundTime) {
10557158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    addTimeLabel(calMid, mLevelLeft, mLevelRight, is24hr);
10567158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                }
10577158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                addTimeLabel(calEnd, mLevelLeft, mLevelRight, is24hr);
10587158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            }
10597158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
10607158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            // Create the date labels if the chart includes multiple days
10617158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            if (calStart.get(Calendar.DAY_OF_YEAR) != calEnd.get(Calendar.DAY_OF_YEAR) ||
10627158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    calStart.get(Calendar.YEAR) != calEnd.get(Calendar.YEAR)) {
10637158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                boolean isDayFirst = isDayFirst();
10647158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calStart.set(Calendar.HOUR_OF_DAY, 0);
10657158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                startRoundTime = calStart.getTimeInMillis();
10667158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                if (startRoundTime < mStartWallTime) {
10677158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    calStart.set(Calendar.DAY_OF_YEAR, calStart.get(Calendar.DAY_OF_YEAR) + 1);
10687158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    startRoundTime = calStart.getTimeInMillis();
10697158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                }
10707158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calEnd.set(Calendar.HOUR_OF_DAY, 0);
10717158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                endRoundTime = calEnd.getTimeInMillis();
10727158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                if (startRoundTime < endRoundTime) {
10737158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    addDateLabel(calStart, mLevelLeft, mLevelRight, isDayFirst);
10746fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    Calendar calMid = Calendar.getInstance();
107599b78b3eebd4fa75c3d8a4a4e500a91faf5a4c12Philip P. Moltmann
107699b78b3eebd4fa75c3d8a4a4e500a91faf5a4c12Philip P. Moltmann                    // The middle between two beginnings of days can be anywhere between -1 to 13
107799b78b3eebd4fa75c3d8a4a4e500a91faf5a4c12Philip P. Moltmann                    // after the beginning of the "median" day.
107899b78b3eebd4fa75c3d8a4a4e500a91faf5a4c12Philip P. Moltmann                    calMid.setTimeInMillis(startRoundTime + ((endRoundTime - startRoundTime) / 2)
107999b78b3eebd4fa75c3d8a4a4e500a91faf5a4c12Philip P. Moltmann                                           + 2 * 60 * 60 * 1000);
10806fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    calMid.set(Calendar.HOUR_OF_DAY, 0);
108199b78b3eebd4fa75c3d8a4a4e500a91faf5a4c12Philip P. Moltmann                    calMid.set(Calendar.MINUTE, 0);
10826fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    long calMidMillis = calMid.getTimeInMillis();
10836fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    if (calMidMillis > startRoundTime && calMidMillis < endRoundTime) {
10846fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                        addDateLabel(calMid, mLevelLeft, mLevelRight, isDayFirst);
10856fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    }
10867158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                }
10877158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                addDateLabel(calEnd, mLevelLeft, mLevelRight, isDayFirst);
10885a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
10897158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        }
10907158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
10917158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        if (mTimeLabels.size() < 2) {
10927158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            // If there are fewer than 2 time labels, then they are useless.  Just
10937158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            // show an axis label giving the entire duration.
10947158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            mDurationString = Formatter.formatShortElapsedTime(getContext(),
10957158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    mEndWallTime - mStartWallTime);
10967158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            mDurationStringWidth = (int)mTextPaint.measureText(mDurationString);
10977158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        } else {
10987158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            mDurationString = null;
10997158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            mDurationStringWidth = 0;
11005a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
11014f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    }
11025a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11035a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    void addTimeLabel(Calendar cal, int levelLeft, int levelRight, boolean is24hr) {
11045a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final long walltimeStart = mStartWallTime;
11055a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final long walltimeChange = mEndWallTime-walltimeStart;
1106a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio        mTimeLabels.add(new TimeLabel(mTextPaint,
11075a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                levelLeft + (int)(((cal.getTimeInMillis()-walltimeStart)*(levelRight-levelLeft))
11085a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        / walltimeChange),
11095a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                cal, is24hr));
11105a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
11115a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    void addDateLabel(Calendar cal, int levelLeft, int levelRight, boolean isDayFirst) {
11135a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final long walltimeStart = mStartWallTime;
11145a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final long walltimeChange = mEndWallTime-walltimeStart;
1115a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio        mDateLabels.add(new DateLabel(mTextPaint,
11165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                levelLeft + (int)(((cal.getTimeInMillis()-walltimeStart)*(levelRight-levelLeft))
11175a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        / walltimeChange),
11185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                cal, isDayFirst));
11195a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
11205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11214f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    @Override
11224f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    protected void onDraw(Canvas canvas) {
11234f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        super.onDraw(canvas);
112474809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani
11254f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        final int width = getWidth();
11264f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        final int height = getHeight();
11275a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11286fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        //buildBitmap(width, height);
11296fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
11305a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "onDraw: " + width + "x" + height);
11316fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        //canvas.drawBitmap(mBitmap, 0, 0, null);
11326fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        drawChart(canvas, width, height);
11336fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    }
11346fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
11356fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    void buildBitmap(int width, int height) {
11366fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        if (mBitmap != null && width == mBitmap.getWidth() && height == mBitmap.getHeight()) {
11376fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn            return;
11386fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        }
11396fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
11406fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        if (DEBUG) Log.d(TAG, "buildBitmap: " + width + "x" + height);
11416fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
11426fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        mBitmap = Bitmap.createBitmap(getResources().getDisplayMetrics(), width, height,
11436fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                Bitmap.Config.ARGB_8888);
11446fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        mCanvas = new Canvas(mBitmap);
11456fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        drawChart(mCanvas, width, height);
11466fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    }
11475a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11486fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    void drawChart(Canvas canvas, int width, int height) {
114974809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani        final boolean layoutRtl = isLayoutRtl();
115074809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani        final int textStartX = layoutRtl ? width : 0;
11510be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final int textEndX = layoutRtl ? 0 : width;
11520be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final Paint.Align textAlignLeft = layoutRtl ? Paint.Align.RIGHT : Paint.Align.LEFT;
11530be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final Paint.Align textAlignRight = layoutRtl ? Paint.Align.LEFT : Paint.Align.RIGHT;
115474809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani
11555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) {
11565a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            canvas.drawRect(1, 1, width, height, mDebugRectPaint);
11575a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
11585a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11595a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "Drawing level path.");
11604f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        canvas.drawPath(mBatLevelPath, mBatteryBackgroundPaint);
11615a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (!mTimeRemainPath.isEmpty()) {
11625a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing time remain path.");
11635a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            canvas.drawPath(mTimeRemainPath, mTimeRemainPaint);
11645a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
11657158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        if (mTimeLabels.size() > 1) {
11665a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int y = mLevelBottom - mTextAscent + (mThinLineWidth*4);
11675a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int ytick = mLevelBottom+mThinLineWidth+(mThinLineWidth/2);
11685a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mTextPaint.setTextAlign(Paint.Align.LEFT);
11695a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int lastX = 0;
11705a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            for (int i=0; i<mTimeLabels.size(); i++) {
11715a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                TimeLabel label = mTimeLabels.get(i);
11725a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (i == 0) {
11735a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    int x = label.x - label.width/2;
11745a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (x < 0) {
11755a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        x = 0;
11765a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
11775a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (DEBUG) Log.d(TAG, "Drawing left label: " + label.label + " @ " + x);
11785a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawText(label.label, x, y, mTextPaint);
11795a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawLine(label.x, ytick, label.x, ytick+mThinLineWidth, mTextPaint);
11805a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    lastX = x + label.width;
11815a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                } else if (i < (mTimeLabels.size()-1)) {
11825a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    int x = label.x - label.width/2;
11835a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (x < (lastX+mTextAscent)) {
11845a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        continue;
11855a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
11865a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    TimeLabel nextLabel = mTimeLabels.get(i+1);
11875a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (x > (width-nextLabel.width-mTextAscent)) {
11885a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        continue;
11895a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
11905a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (DEBUG) Log.d(TAG, "Drawing middle label: " + label.label + " @ " + x);
11915a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawText(label.label, x, y, mTextPaint);
11925a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawLine(label.x, ytick, label.x, ytick + mThinLineWidth, mTextPaint);
11935a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    lastX = x + label.width;
11945a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                } else {
11955a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    int x = label.x - label.width/2;
11965a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if ((x+label.width) >= width) {
11975a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        x = width-1-label.width;
11985a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
11995a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (DEBUG) Log.d(TAG, "Drawing right label: " + label.label + " @ " + x);
12005a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawText(label.label, x, y, mTextPaint);
12015a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawLine(label.x, ytick, label.x, ytick+mThinLineWidth, mTextPaint);
12025a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                }
12035a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
12047158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        } else if (mDurationString != null) {
12057158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            int y = mLevelBottom - mTextAscent + (mThinLineWidth*4);
12067158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            mTextPaint.setTextAlign(Paint.Align.LEFT);
12077158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            canvas.drawText(mDurationString,
12087158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    mLevelLeft + (mLevelRight-mLevelLeft)/2 - mDurationStringWidth/2,
12097158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    y, mTextPaint);
12105a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
12115a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
12125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        int headerTop = -mHeaderTextAscent + (mHeaderTextDescent-mHeaderTextAscent)/3;
12130be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mHeaderTextPaint.setTextAlign(textAlignLeft);
12143069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        if (DEBUG) Log.d(TAG, "Drawing charge label string: " + mInfo.mChargeLabelString);
12153069581512bcb9687cb8d79675f6c4950c9ac087Jason Monk        canvas.drawText(mInfo.mChargeLabelString, textStartX, headerTop, mHeaderTextPaint);
12167158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        int stringHalfWidth = mChargeDurationStringWidth / 2;
12177158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        if (layoutRtl) stringHalfWidth = -stringHalfWidth;
12180be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        int headerCenter = ((width-mChargeDurationStringWidth-mDrainStringWidth)/2)
12190be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                + (layoutRtl ? mDrainStringWidth : mChargeLabelStringWidth);
12205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "Drawing charge duration string: " + mChargeDurationString);
12217158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        canvas.drawText(mChargeDurationString, headerCenter - stringHalfWidth, headerTop,
12220be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                mHeaderTextPaint);
12230be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mHeaderTextPaint.setTextAlign(textAlignRight);
12245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "Drawing drain string: " + mDrainString);
12250be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        canvas.drawText(mDrainString, textEndX, headerTop, mHeaderTextPaint);
12260be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
122712fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        if (!mBatGoodPath.isEmpty()) {
12285a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing good battery path");
122912fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            canvas.drawPath(mBatGoodPath, mBatteryGoodPaint);
123012fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
123112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        if (!mBatWarnPath.isEmpty()) {
12325a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing warn battery path");
123312fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            canvas.drawPath(mBatWarnPath, mBatteryWarnPaint);
123412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
123512fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        if (!mBatCriticalPath.isEmpty()) {
12365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing critical battery path");
123712fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            canvas.drawPath(mBatCriticalPath, mBatteryCriticalPaint);
123812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
1239c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        if (mHavePhoneSignal) {
12405a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing phone signal path");
1241b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn            int top = height-mPhoneSignalOffset - (mLineWidth/2);
1242c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            mPhoneSignalChart.draw(canvas, top, mLineWidth);
1243c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        }
124412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        if (!mScreenOnPath.isEmpty()) {
12455a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing screen on path");
124612fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            canvas.drawPath(mScreenOnPath, mScreenOnPaint);
12474f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        }
1248cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (!mChargingPath.isEmpty()) {
12495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing charging path");
1250cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            canvas.drawPath(mChargingPath, mChargingPaint);
1251cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
1252be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        if (mHaveGps) {
1253be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            if (!mGpsOnPath.isEmpty()) {
12545a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (DEBUG) Log.d(TAG, "Drawing gps path");
1255be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                canvas.drawPath(mGpsOnPath, mGpsOnPaint);
1256be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            }
1257be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        }
12582627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        if (mHaveFlashlight) {
12592627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            if (!mFlashlightOnPath.isEmpty()) {
12602627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                if (DEBUG) Log.d(TAG, "Drawing flashlight path");
12612627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                canvas.drawPath(mFlashlightOnPath, mFlashlightOnPaint);
12622627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            }
12632627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        }
12642627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        if (mHaveCamera) {
12652627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            if (!mCameraOnPath.isEmpty()) {
12662627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                if (DEBUG) Log.d(TAG, "Drawing camera path");
12672627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                canvas.drawPath(mCameraOnPath, mCameraOnPaint);
12682627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            }
12692627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk        }
1270be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        if (mHaveWifi) {
1271be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            if (!mWifiRunningPath.isEmpty()) {
12725a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (DEBUG) Log.d(TAG, "Drawing wifi path");
1273be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                canvas.drawPath(mWifiRunningPath, mWifiRunningPaint);
1274be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            }
1275be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        }
127655985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        if (!mCpuRunningPath.isEmpty()) {
12775a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing running path");
127855985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn            canvas.drawPath(mCpuRunningPath, mCpuRunningPaint);
1279cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
1280cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
1281cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (mLargeMode) {
12825a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing large mode labels");
1283a312f7f8044a07a2a41de477cc30bb34fc1df55fJohn Spurlock            Paint.Align align = mTextPaint.getTextAlign();
1284a312f7f8044a07a2a41de477cc30bb34fc1df55fJohn Spurlock            mTextPaint.setTextAlign(textAlignLeft);  // large-mode labels always aligned to start
1285c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            if (mHavePhoneSignal) {
128674809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani                canvas.drawText(mPhoneSignalLabel, textStartX,
1287c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani                        height - mPhoneSignalOffset - mTextDescent, mTextPaint);
1288c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            }
1289be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            if (mHaveGps) {
129074809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani                canvas.drawText(mGpsOnLabel, textStartX,
1291be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                        height - mGpsOnOffset - mTextDescent, mTextPaint);
1292be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            }
12932627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            if (mHaveFlashlight) {
12942627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                canvas.drawText(mFlashlightOnLabel, textStartX,
12952627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                        height - mFlashlightOnOffset - mTextDescent, mTextPaint);
12962627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            }
12972627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            if (mHaveCamera) {
12982627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                canvas.drawText(mCameraOnLabel, textStartX,
12992627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk                        height - mCameraOnOffset - mTextDescent, mTextPaint);
13002627190bac86184ce7bfb64f3bb44b98b8c03ff6Ruben Brunk            }
1301be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            if (mHaveWifi) {
130274809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani                canvas.drawText(mWifiRunningLabel, textStartX,
1303be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                        height - mWifiRunningOffset - mTextDescent, mTextPaint);
1304be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            }
130555985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn            canvas.drawText(mCpuRunningLabel, textStartX,
130655985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn                    height - mCpuRunningOffset - mTextDescent, mTextPaint);
130774809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani            canvas.drawText(mChargingLabel, textStartX,
1308cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn                    height - mChargingOffset - mTextDescent, mTextPaint);
130974809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani            canvas.drawText(mScreenOnLabel, textStartX,
1310cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn                    height - mScreenOnOffset - mTextDescent, mTextPaint);
1311a312f7f8044a07a2a41de477cc30bb34fc1df55fJohn Spurlock            mTextPaint.setTextAlign(align);
13125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
13135a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
13145a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        canvas.drawLine(mLevelLeft-mThinLineWidth, mLevelTop, mLevelLeft-mThinLineWidth,
13155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mLevelBottom+(mThinLineWidth/2), mTextPaint);
13165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (mLargeMode) {
1317cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            for (int i=0; i<10; i++) {
13185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                int y = mLevelTop + mThinLineWidth/2 + ((mLevelBottom-mLevelTop)*i)/10;
13195a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                canvas.drawLine(mLevelLeft-mThinLineWidth*2-mThinLineWidth/2, y,
13205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        mLevelLeft-mThinLineWidth-mThinLineWidth/2, y, mTextPaint);
13215a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
13225a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
13235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "Drawing max percent, origw=" + mMaxPercentLabelStringWidth
13245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                + ", noww=" + (int)mTextPaint.measureText(mMaxPercentLabelString));
13255a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        canvas.drawText(mMaxPercentLabelString, 0, mLevelTop, mTextPaint);
13265a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        canvas.drawText(mMinPercentLabelString,
13275a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mMaxPercentLabelStringWidth-mMinPercentLabelStringWidth,
13285a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mLevelBottom - mThinLineWidth, mTextPaint);
13297158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        canvas.drawLine(mLevelLeft/2, mLevelBottom+mThinLineWidth, width,
13305a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mLevelBottom+mThinLineWidth, mTextPaint);
13315a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
13325a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (mDateLabels.size() > 0) {
13335a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int ytop = mLevelTop + mTextAscent;
13345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int ybottom = mLevelBottom;
13355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int lastLeft = mLevelRight;
13365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mTextPaint.setTextAlign(Paint.Align.LEFT);
13375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            for (int i=mDateLabels.size()-1; i>=0; i--) {
13385a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                DateLabel label = mDateLabels.get(i);
13395a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                int left = label.x - mThinLineWidth;
13405a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                int x = label.x + mThinLineWidth*2;
13415a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if ((x+label.width) >= lastLeft) {
13425a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    x = label.x - mThinLineWidth*2 - label.width;
13435a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    left = x - mThinLineWidth;
13445a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (left >= lastLeft) {
13455a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        // okay we give up.
13465a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        continue;
13475a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
13485a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                }
13495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (left < mLevelLeft) {
13505a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    // Won't fit on left, give up.
13515a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    continue;
13525a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                }
13535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mDateLinePath.reset();
13545a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mDateLinePath.moveTo(label.x, ytop);
13555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mDateLinePath.lineTo(label.x, ybottom);
13565a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                canvas.drawPath(mDateLinePath, mDateLinePaint);
13575a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                canvas.drawText(label.label, x, ytop - mTextAscent, mTextPaint);
1358cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            }
1359cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
1360ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
1361ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn}
1362