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
190be7598cb8c8cf6808b336204632615c5f26298fDianne Hackbornimport android.content.Intent;
206fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackbornimport android.graphics.Bitmap;
215a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport android.graphics.DashPathEffect;
220be7598cb8c8cf6808b336204632615c5f26298fDianne Hackbornimport android.os.BatteryManager;
235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport android.provider.Settings;
245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport android.text.format.DateFormat;
25525f2bdfd2b5293ba4338a9664da9a21d468ba0aDianne Hackbornimport android.text.format.Formatter;
265a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport android.util.Log;
275a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport android.util.TimeUtils;
28ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport com.android.settings.R;
297253df35a09d8d61ececedbb66179171802e42a7Elliott Hughesimport com.android.settings.Utils;
30ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
31ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.Context;
32ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.res.ColorStateList;
33ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.content.res.TypedArray;
34ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.graphics.Canvas;
35ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.graphics.Paint;
364f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackbornimport android.graphics.Path;
37ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.graphics.Typeface;
38ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.os.BatteryStats;
39ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.os.SystemClock;
404f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackbornimport android.os.BatteryStats.HistoryItem;
41cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackbornimport android.telephony.ServiceState;
42ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.text.TextPaint;
43ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.util.AttributeSet;
444f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackbornimport android.util.TypedValue;
45ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornimport android.view.View;
465a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport libcore.icu.LocaleData;
475a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
485a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport java.util.ArrayList;
495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackbornimport java.util.Calendar;
50a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglioimport java.util.Locale;
51ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
52ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackbornpublic class BatteryHistoryChart extends View {
535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    static final boolean DEBUG = false;
545a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    static final String TAG = "BatteryHistoryChart";
555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
5619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    static final int CHART_DATA_X_MASK = 0x0000ffff;
5719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    static final int CHART_DATA_BIN_MASK = 0xffff0000;
5819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    static final int CHART_DATA_BIN_SHIFT = 16;
5919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
6019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    static class ChartData {
6119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        int[] mColors;
6219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        Paint[] mPaints;
6319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
6419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        int mNumTicks;
6519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        int[] mTicks;
6619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        int mLastBin;
6719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
6819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        void setColors(int[] colors) {
6919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            mColors = colors;
7019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            mPaints = new Paint[colors.length];
7119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            for (int i=0; i<colors.length; i++) {
7219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mPaints[i] = new Paint();
7319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mPaints[i].setColor(colors[i]);
7419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mPaints[i].setStyle(Paint.Style.FILL);
7519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            }
7619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        }
7719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
7819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        void init(int width) {
7919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            if (width > 0) {
80916adce02d5b37038cd78d11a8c884237684f9a8Dianne Hackborn                mTicks = new int[width*2];
8119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            } else {
8219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mTicks = null;
8319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            }
8419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            mNumTicks = 0;
8519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            mLastBin = 0;
8619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        }
8719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
8819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        void addTick(int x, int bin) {
89916adce02d5b37038cd78d11a8c884237684f9a8Dianne Hackborn            if (bin != mLastBin && mNumTicks < mTicks.length) {
901cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn                mTicks[mNumTicks] = (x&CHART_DATA_X_MASK) | (bin<<CHART_DATA_BIN_SHIFT);
9119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mNumTicks++;
9219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                mLastBin = bin;
9319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            }
9419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        }
9519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
9619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        void finish(int width) {
9719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            if (mLastBin != 0) {
9819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                addTick(width, 0);
9919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            }
10019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        }
10119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
10219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        void draw(Canvas canvas, int top, int height) {
10319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            int lastBin=0, lastX=0;
10419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            int bottom = top + height;
10519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            for (int i=0; i<mNumTicks; i++) {
10619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                int tick = mTicks[i];
10719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                int x = tick&CHART_DATA_X_MASK;
10819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                int bin = (tick&CHART_DATA_BIN_MASK) >> CHART_DATA_BIN_SHIFT;
10919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                if (lastBin != 0) {
11019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    canvas.drawRect(lastX, top, x, bottom, mPaints[lastBin]);
11119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                }
11219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                lastBin = bin;
11319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                lastX = x;
11419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            }
11519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
11619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        }
11719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    }
11819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
1194f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    static final int SANS = 1;
1204f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    static final int SERIF = 2;
1214f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    static final int MONOSPACE = 3;
1224f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn
12319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn    // First value if for phone off; first value is "scanning"; following values
124cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    // are battery stats signal strength buckets.
125cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    static final int NUM_PHONE_SIGNALS = 7;
126cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
1274f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    final Paint mBatteryBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1284f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    final Paint mBatteryGoodPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1294f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    final Paint mBatteryWarnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1304f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    final Paint mBatteryCriticalPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1315a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final Paint mTimeRemainPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
132cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    final Paint mChargingPaint = new Paint();
133cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    final Paint mScreenOnPaint = new Paint();
134cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    final Paint mGpsOnPaint = 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();
151be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    final Path mWifiRunningPath = new Path();
15255985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn    final Path mCpuRunningPath = new Path();
1535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final Path mDateLinePath = new Path();
15412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn
155ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    BatteryStats mStats;
1560be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    Intent mBatteryBroadcast;
157ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    long mStatsPeriod;
158c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn    int mBatteryLevel;
1595a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    String mMaxPercentLabelString;
1605a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    String mMinPercentLabelString;
161ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    String mDurationString;
1620be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    String mChargeLabelString;
1630be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    String mChargeDurationString;
1640be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    String mDrainString;
165cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    String mChargingLabel;
166cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    String mScreenOnLabel;
167cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    String mGpsOnLabel;
168be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    String mWifiRunningLabel;
16955985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn    String mCpuRunningLabel;
170cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    String mPhoneSignalLabel;
1717158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
1727158e6299210d08f82c29135c001652508b79dfbDianne Hackborn    int mChartMinHeight;
1737158e6299210d08f82c29135c001652508b79dfbDianne Hackborn    int mHeaderHeight;
1747158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
1757158e6299210d08f82c29135c001652508b79dfbDianne Hackborn    int mBatteryWarnLevel;
1767158e6299210d08f82c29135c001652508b79dfbDianne Hackborn    int mBatteryCriticalLevel;
1777158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
178ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mTextAscent;
179ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mTextDescent;
1800be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    int mHeaderTextAscent;
1810be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    int mHeaderTextDescent;
1825a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mMaxPercentLabelStringWidth;
1835a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mMinPercentLabelStringWidth;
184ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mDurationStringWidth;
1850be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    int mChargeLabelStringWidth;
1860be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    int mChargeDurationStringWidth;
1870be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    int mDrainStringWidth;
188cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
189cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    boolean mLargeMode;
190cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
1915a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mLastWidth = -1;
1925a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mLastHeight = -1;
1935a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
194cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mLineWidth;
195cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mThinLineWidth;
196cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mChargingOffset;
197cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mScreenOnOffset;
198cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mGpsOnOffset;
199be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    int mWifiRunningOffset;
20055985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn    int mCpuRunningOffset;
201cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mPhoneSignalOffset;
202cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mLevelOffset;
203cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mLevelTop;
204cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn    int mLevelBottom;
2055a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mLevelLeft;
2065a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    int mLevelRight;
2073bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn
208ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mNumHist;
209ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    long mHistStart;
2105a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    long mHistDataEnd;
211ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    long mHistEnd;
2125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    long mStartWallTime;
2135a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    long mEndDataWallTime;
2145a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    long mEndWallTime;
2155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    boolean mDischarging;
216ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mBatLow;
217ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    int mBatHigh;
218be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    boolean mHaveWifi;
219be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn    boolean mHaveGps;
220c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani    boolean mHavePhoneSignal;
2210be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2225a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final ArrayList<TimeLabel> mTimeLabels = new ArrayList<TimeLabel>();
2235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    final ArrayList<DateLabel> mDateLabels = new ArrayList<DateLabel>();
2245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
2256fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    Bitmap mBitmap;
2266fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    Canvas mCanvas;
2276fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
2280be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    static class TextAttrs {
2290be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        ColorStateList textColor = null;
2300be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        int textSize = 15;
2310be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        int typefaceIndex = -1;
2320be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        int styleIndex = -1;
2330be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2340be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        void retrieve(Context context, TypedArray from, int index) {
2350be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            TypedArray appearance = null;
2360be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            int ap = from.getResourceId(index, -1);
2370be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            if (ap != -1) {
2380be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                appearance = context.obtainStyledAttributes(ap,
2390be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                                    com.android.internal.R.styleable.TextAppearance);
2400be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            }
2410be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            if (appearance != null) {
2420be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                int n = appearance.getIndexCount();
2430be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                for (int i = 0; i < n; i++) {
2440be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    int attr = appearance.getIndex(i);
2450be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2460be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    switch (attr) {
2470be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    case com.android.internal.R.styleable.TextAppearance_textColor:
2480be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        textColor = appearance.getColorStateList(attr);
2490be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        break;
2500be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2510be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    case com.android.internal.R.styleable.TextAppearance_textSize:
2520be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        textSize = appearance.getDimensionPixelSize(attr, textSize);
2530be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        break;
2540be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2550be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    case com.android.internal.R.styleable.TextAppearance_typeface:
2560be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        typefaceIndex = appearance.getInt(attr, -1);
2570be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        break;
2580be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2590be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    case com.android.internal.R.styleable.TextAppearance_textStyle:
2600be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        styleIndex = appearance.getInt(attr, -1);
2610be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                        break;
2620be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    }
2630be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                }
2640be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2650be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                appearance.recycle();
2660be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            }
2670be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        }
2680be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2690be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        void apply(Context context, TextPaint paint) {
2700be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            paint.density = context.getResources().getDisplayMetrics().density;
2710be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            paint.setCompatibilityScaling(
2720be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    context.getResources().getCompatibilityInfo().applicationScale);
2730be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2740be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            paint.setColor(textColor.getDefaultColor());
2750be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            paint.setTextSize(textSize);
2760be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2770be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            Typeface tf = null;
2780be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            switch (typefaceIndex) {
2790be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                case SANS:
2800be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    tf = Typeface.SANS_SERIF;
2810be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    break;
2820be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2830be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                case SERIF:
2840be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    tf = Typeface.SERIF;
2850be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    break;
2860be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2870be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                case MONOSPACE:
2880be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    tf = Typeface.MONOSPACE;
2890be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    break;
2900be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            }
2910be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2920be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            setTypeface(paint, tf, styleIndex);
2930be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        }
2940be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
2950be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        public void setTypeface(TextPaint paint, Typeface tf, int style) {
2960be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            if (style > 0) {
2970be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                if (tf == null) {
2980be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    tf = Typeface.defaultFromStyle(style);
2990be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                } else {
3000be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    tf = Typeface.create(tf, style);
3010be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                }
3020be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
3030be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setTypeface(tf);
3040be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                // now compute what (if any) algorithmic styling is needed
3050be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                int typefaceStyle = tf != null ? tf.getStyle() : 0;
3060be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                int need = style & ~typefaceStyle;
3070be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setFakeBoldText((need & Typeface.BOLD) != 0);
3080be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0);
3090be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            } else {
3100be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setFakeBoldText(false);
3110be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setTextSkewX(0);
3120be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                paint.setTypeface(tf);
3130be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            }
3140be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        }
3150be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    }
3160be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
3175a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    static class TimeLabel {
3185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final int x;
3195a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final String label;
3205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final int width;
3215a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
322a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio        TimeLabel(TextPaint paint, int x, Calendar cal, boolean use24hr) {
3235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            this.x = x;
324a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio            final String bestFormat = DateFormat.getBestDateTimePattern(
325a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio                    Locale.getDefault(), use24hr ? "km" : "ha");
326a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio            label = DateFormat.format(bestFormat, cal).toString();
3275a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            width = (int)paint.measureText(label);
3285a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
3295a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
3305a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
3315a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    static class DateLabel {
3325a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final int x;
3335a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final String label;
3345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final int width;
3355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
336a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio        DateLabel(TextPaint paint, int x, Calendar cal, boolean dayFirst) {
3375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            this.x = x;
338a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio            final String bestFormat = DateFormat.getBestDateTimePattern(
339a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio                    Locale.getDefault(), dayFirst ? "dM" : "Md");
340a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio            label = DateFormat.format(bestFormat, cal).toString();
3415a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            width = (int)paint.measureText(label);
3425a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
3435a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
3445a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
345ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    public BatteryHistoryChart(Context context, AttributeSet attrs) {
346ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        super(context, attrs);
3477158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
3486fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        if (DEBUG) Log.d(TAG, "New BatteryHistoryChart!");
3496fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
3507158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryWarnLevel = mContext.getResources().getInteger(
3517158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                com.android.internal.R.integer.config_lowBatteryWarningLevel);
3527158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryCriticalLevel = mContext.getResources().getInteger(
3537158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                com.android.internal.R.integer.config_criticalBatteryWarningLevel);
3547158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
3555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mThinLineWidth = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
3565a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                2, getResources().getDisplayMetrics());
3575a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
3587158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryBackgroundPaint.setColor(0xFF009688);
3594f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        mBatteryBackgroundPaint.setStyle(Paint.Style.FILL);
3607158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryGoodPaint.setARGB(128, 0, 128, 0);
36112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatteryGoodPaint.setStyle(Paint.Style.STROKE);
3627158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryWarnPaint.setARGB(128, 128, 128, 0);
36312fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatteryWarnPaint.setStyle(Paint.Style.STROKE);
3647158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mBatteryCriticalPaint.setARGB(192, 128, 0, 0);
36512fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatteryCriticalPaint.setStyle(Paint.Style.STROKE);
3667158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mTimeRemainPaint.setColor(0xFFCED7BB);
3675a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mTimeRemainPaint.setStyle(Paint.Style.FILL);
36812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mChargingPaint.setStyle(Paint.Style.STROKE);
36912fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mScreenOnPaint.setStyle(Paint.Style.STROKE);
370cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mGpsOnPaint.setStyle(Paint.Style.STROKE);
371be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        mWifiRunningPaint.setStyle(Paint.Style.STROKE);
37255985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        mCpuRunningPaint.setStyle(Paint.Style.STROKE);
37368f005fbd48f18cdab0168ba92b8fd40776edc1eDianne Hackborn        mPhoneSignalChart.setColors(com.android.settings.Utils.BADNESS_COLORS);
3745a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDebugRectPaint.setARGB(255, 255, 0, 0);
3755a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDebugRectPaint.setStyle(Paint.Style.STROKE);
3763bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn        mScreenOnPaint.setColor(0xFF009688);
3773bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn        mGpsOnPaint.setColor(0xFF009688);
3783bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn        mWifiRunningPaint.setColor(0xFF009688);
3793bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn        mCpuRunningPaint.setColor(0xFF009688);
3803bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn        mChargingPaint.setColor(0xFF009688);
3815a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
382ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        TypedArray a =
383ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            context.obtainStyledAttributes(
384ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                attrs, R.styleable.BatteryHistoryChart, 0, 0);
385ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
3860be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final TextAttrs mainTextAttrs = new TextAttrs();
3870be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final TextAttrs headTextAttrs = new TextAttrs();
3880be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mainTextAttrs.retrieve(context, a, R.styleable.BatteryHistoryChart_android_textAppearance);
3890be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        headTextAttrs.retrieve(context, a, R.styleable.BatteryHistoryChart_headerAppearance);
390ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
391ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        int shadowcolor = 0;
392ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        float dx=0, dy=0, r=0;
393ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
394ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        int n = a.getIndexCount();
395ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        for (int i = 0; i < n; i++) {
396ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            int attr = a.getIndex(i);
397ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
398ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            switch (attr) {
399ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_shadowColor:
400ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    shadowcolor = a.getInt(attr, 0);
401ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
402ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
403ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_shadowDx:
404ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    dx = a.getFloat(attr, 0);
405ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
406ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
407ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_shadowDy:
408ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    dy = a.getFloat(attr, 0);
409ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
410ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
411ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_shadowRadius:
412ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    r = a.getFloat(attr, 0);
413ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
414ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
415ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_textColor:
4160be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    mainTextAttrs.textColor = a.getColorStateList(attr);
4170be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    headTextAttrs.textColor = a.getColorStateList(attr);
418ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
419ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
420ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_textSize:
4210be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    mainTextAttrs.textSize = a.getDimensionPixelSize(attr, mainTextAttrs.textSize);
4220be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    headTextAttrs.textSize = a.getDimensionPixelSize(attr, headTextAttrs.textSize);
423ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
424ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
425ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_typeface:
4260be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    mainTextAttrs.typefaceIndex = a.getInt(attr, mainTextAttrs.typefaceIndex);
4270be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    headTextAttrs.typefaceIndex = a.getInt(attr, headTextAttrs.typefaceIndex);
428ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
429ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
430ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                case R.styleable.BatteryHistoryChart_android_textStyle:
4310be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    mainTextAttrs.styleIndex = a.getInt(attr, mainTextAttrs.styleIndex);
4320be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                    headTextAttrs.styleIndex = a.getInt(attr, headTextAttrs.styleIndex);
433ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn                    break;
4347158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
4357158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                case R.styleable.BatteryHistoryChart_barPrimaryColor:
4367158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    mBatteryBackgroundPaint.setColor(a.getInt(attr, 0));
4373bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn                    mScreenOnPaint.setColor(a.getInt(attr, 0));
4383bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn                    mGpsOnPaint.setColor(a.getInt(attr, 0));
4393bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn                    mWifiRunningPaint.setColor(a.getInt(attr, 0));
4403bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn                    mCpuRunningPaint.setColor(a.getInt(attr, 0));
4413bd46a70c1e63c16542fcec1b87b99693cbbbf1eDianne Hackborn                    mChargingPaint.setColor(a.getInt(attr, 0));
4427158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    break;
4437158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
4447158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                case R.styleable.BatteryHistoryChart_barPredictionColor:
4457158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    mTimeRemainPaint.setColor(a.getInt(attr, 0));
4467158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    break;
4477158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
4487158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                case R.styleable.BatteryHistoryChart_chartMinHeight:
4497158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    mChartMinHeight = a.getDimensionPixelSize(attr, 0);
4507158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    break;
451ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            }
452ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
453ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
454d2be882d8f2e5acd8a5806c649ba4640249cf4baDianne Hackborn        a.recycle();
455d2be882d8f2e5acd8a5806c649ba4640249cf4baDianne Hackborn
4560be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mainTextAttrs.apply(context, mTextPaint);
4570be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        headTextAttrs.apply(context, mHeaderTextPaint);
4580be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
4595a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDateLinePaint.set(mTextPaint);
4605a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDateLinePaint.setStyle(Paint.Style.STROKE);
4615a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        int hairlineWidth = mThinLineWidth/2;
4625a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (hairlineWidth < 1) {
4635a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            hairlineWidth = 1;
4645a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
4655a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDateLinePaint.setStrokeWidth(hairlineWidth);
4665a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDateLinePaint.setPathEffect(new DashPathEffect(new float[] {
4675a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mThinLineWidth * 2, mThinLineWidth * 2 }, 0));
4685a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
469ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (shadowcolor != 0) {
470ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            mTextPaint.setShadowLayer(r, dx, dy, shadowcolor);
4710be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn            mHeaderTextPaint.setShadowLayer(r, dx, dy, shadowcolor);
472ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
473ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
4745a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
4750be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn    void setStats(BatteryStats stats, Intent broadcast) {
476ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mStats = stats;
4770be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mBatteryBroadcast = broadcast;
4780be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
4796fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        if (DEBUG) Log.d(TAG, "Setting stats...");
4806fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
4810be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
4820be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
4830be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        long uSecTime = mStats.computeBatteryRealtime(elapsedRealtimeUs,
4844f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn                BatteryStats.STATS_SINCE_CHARGED);
485ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mStatsPeriod = uSecTime;
486cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mChargingLabel = getContext().getString(R.string.battery_stats_charging_label);
487cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mScreenOnLabel = getContext().getString(R.string.battery_stats_screen_on_label);
488cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mGpsOnLabel = getContext().getString(R.string.battery_stats_gps_on_label);
489be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        mWifiRunningLabel = getContext().getString(R.string.battery_stats_wifi_running_label);
49055985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        mCpuRunningLabel = getContext().getString(R.string.battery_stats_wake_lock_label);
491cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mPhoneSignalLabel = getContext().getString(R.string.battery_stats_phone_signal_label);
4925a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
4937253df35a09d8d61ececedbb66179171802e42a7Elliott Hughes        mMaxPercentLabelString = Utils.formatPercentage(100);
4947253df35a09d8d61ececedbb66179171802e42a7Elliott Hughes        mMinPercentLabelString = Utils.formatPercentage(0);
4955a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
496c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn        mBatteryLevel = com.android.settings.Utils.getBatteryLevel(mBatteryBroadcast);
4975a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        long remainingTimeUs = 0;
4985a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDischarging = true;
499b11c97379918fce423bfb0b96a8319a8e698845dDianne Hackborn        if (mBatteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) == 0) {
5005a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            final long drainTime = mStats.computeBatteryTimeRemaining(elapsedRealtimeUs);
5015a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (drainTime > 0) {
5025a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                remainingTimeUs = drainTime;
5035a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                String timeString = Formatter.formatShortElapsedTime(getContext(),
5045a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        drainTime / 1000);
5055a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mChargeLabelString = getContext().getResources().getString(
506c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                        R.string.power_discharging_duration, mBatteryLevel, timeString);
5075a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            } else {
5087253df35a09d8d61ececedbb66179171802e42a7Elliott Hughes                mChargeLabelString = Utils.formatPercentage(mBatteryLevel);
5095a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
5105a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        } else {
5115a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            final long chargeTime = mStats.computeChargeTimeRemaining(elapsedRealtimeUs);
5125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            final String statusLabel = com.android.settings.Utils.getBatteryStatus(getResources(),
5135a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    mBatteryBroadcast);
514b11c97379918fce423bfb0b96a8319a8e698845dDianne Hackborn            final int status = mBatteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
515b11c97379918fce423bfb0b96a8319a8e698845dDianne Hackborn                    BatteryManager.BATTERY_STATUS_UNKNOWN);
5165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
5175a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mDischarging = false;
5185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                remainingTimeUs = chargeTime;
5195a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                String timeString = Formatter.formatShortElapsedTime(getContext(),
5205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        chargeTime / 1000);
5217158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                int plugType = mBatteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
5227158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                int resId;
5237158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                if (plugType == BatteryManager.BATTERY_PLUGGED_AC) {
5247158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    resId = R.string.power_charging_duration_ac;
5257158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                } else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) {
5267158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    resId = R.string.power_charging_duration_usb;
5277158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                } else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
5287158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    resId = R.string.power_charging_duration_wireless;
5297158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                } else {
5307158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    resId = R.string.power_charging_duration;
5317158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                }
5325a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mChargeLabelString = getContext().getResources().getString(
533c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                        resId, mBatteryLevel, timeString);
5345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            } else {
5355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mChargeLabelString = getContext().getResources().getString(
536c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                        R.string.power_charging, mBatteryLevel, statusLabel);
5375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
5385a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
5395a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDrainString = "";
5405a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mChargeDurationString = "";
5411cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn        setContentDescription(mChargeLabelString);
5425a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
543ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        int pos = 0;
5444f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        int lastInteresting = 0;
5454f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        byte lastLevel = -1;
546ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mBatLow = 0;
547ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mBatHigh = 100;
5485a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mStartWallTime = 0;
5495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mEndDataWallTime = 0;
5505a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mEndWallTime = 0;
5515a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mHistStart = 0;
5525a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mHistEnd = 0;
5535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        long lastWallTime = 0;
5545a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        long lastRealtime = 0;
555be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        int aggrStates = 0;
55696debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn        int aggrStates2 = 0;
55719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        boolean first = true;
55819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn        if (stats.startIteratingHistoryLocked()) {
55919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            final HistoryItem rec = new HistoryItem();
56019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            while (stats.getNextHistoryLocked(rec)) {
56119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                pos++;
5625a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (first) {
5635a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    first = false;
5645a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    mHistStart = rec.time;
5655a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                }
5665a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
5675a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        || rec.cmd == HistoryItem.CMD_RESET) {
5682b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    // If there is a ridiculously large jump in time, then we won't be
5692b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    // able to create a good chart with that data, so just ignore the
5702b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    // times we got before and pretend like our data extends back from
5712b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    // the time we have now.
57294aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                    // Also, if we are getting a time change and we are less than 5 minutes
57394aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                    // since the start of the history real time, then also use this new
57494aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                    // time to compute the base time, since whatever time we had before is
57594aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                    // pretty much just noise.
57694aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                    if (rec.currentTime > (lastWallTime+(180*24*60*60*1000L))
57794aae9afd18c17848aed68addd19d93c937c7555Dianne Hackborn                            || rec.time < (mHistStart+(5*60*1000L))) {
5782b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        mStartWallTime = 0;
5792b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    }
5805a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    lastWallTime = rec.currentTime;
5815a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    lastRealtime = rec.time;
5825a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (mStartWallTime == 0) {
5832b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        mStartWallTime = lastWallTime - (lastRealtime-mHistStart);
58419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    }
5855a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                }
5865a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (rec.isDeltaData()) {
58719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    if (rec.batteryLevel != lastLevel || pos == 1) {
58819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                        lastLevel = rec.batteryLevel;
58919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    }
590b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn                    lastInteresting = pos;
5915a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    mHistDataEnd = rec.time;
59219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    aggrStates |= rec.states;
59396debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                    aggrStates2 |= rec.states2;
594b9b7e5c863c9dda33cacc9978ee8c98b6b395d60Dianne Hackborn                }
595ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            }
596ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
5975a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mHistEnd = mHistDataEnd + (remainingTimeUs/1000);
5985a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mEndDataWallTime = lastWallTime + mHistDataEnd - lastRealtime;
5995a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mEndWallTime = mEndDataWallTime + (remainingTimeUs/1000);
6004f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        mNumHist = lastInteresting;
601be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        mHaveGps = (aggrStates&HistoryItem.STATE_GPS_ON_FLAG) != 0;
60296debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn        mHaveWifi = (aggrStates2&HistoryItem.STATE2_WIFI_RUNNING_FLAG) != 0
60396debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                || (aggrStates&(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG
60496debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        |HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG
60596debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        |HistoryItem.STATE_WIFI_SCAN_FLAG)) != 0;
6068af88fb8387259e51615709b2d1ea0260f7057fdRobert Greenwalt        if (!com.android.settings.Utils.isWifiOnly(getContext())) {
607c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            mHavePhoneSignal = true;
608c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        }
609ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        if (mHistEnd <= mHistStart) mHistEnd = mHistStart+1;
610ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
611ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
612ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    @Override
613ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
6145a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mMaxPercentLabelStringWidth = (int)mTextPaint.measureText(mMaxPercentLabelString);
6155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mMinPercentLabelStringWidth = (int)mTextPaint.measureText(mMinPercentLabelString);
6160be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mDrainStringWidth = (int)mHeaderTextPaint.measureText(mDrainString);
6170be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mChargeLabelStringWidth = (int)mHeaderTextPaint.measureText(mChargeLabelString);
6180be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mChargeDurationStringWidth = (int)mHeaderTextPaint.measureText(mChargeDurationString);
619ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mTextAscent = (int)mTextPaint.ascent();
620ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        mTextDescent = (int)mTextPaint.descent();
6210be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mHeaderTextAscent = (int)mHeaderTextPaint.ascent();
6220be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mHeaderTextDescent = (int)mHeaderTextPaint.descent();
6237158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        int headerTextHeight = mHeaderTextDescent - mHeaderTextAscent;
6247158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mHeaderHeight = headerTextHeight*2 - mTextAscent;
6257158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
6267158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                getDefaultSize(mChartMinHeight+mHeaderHeight, heightMeasureSpec));
627ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
628ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn
62912fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn    void finishPaths(int w, int h, int levelh, int startX, int y, Path curLevelPath,
630cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            int lastX, boolean lastCharging, boolean lastScreenOn, boolean lastGpsOn,
63155985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn            boolean lastWifiRunning, boolean lastCpuRunning, Path lastPath) {
63212fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        if (curLevelPath != null) {
633c01b0c83fca571229621d16b757a46dc0fae7dfeDianne Hackborn            if (lastX >= 0 && lastX < w) {
63412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                if (lastPath != null) {
63512fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                    lastPath.lineTo(w, y);
63612fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                }
63712fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                curLevelPath.lineTo(w, y);
63812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            }
639cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            curLevelPath.lineTo(w, mLevelTop+levelh);
640cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            curLevelPath.lineTo(startX, mLevelTop+levelh);
64112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            curLevelPath.close();
64212fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
64312fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn
644cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (lastCharging) {
64512fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            mChargingPath.lineTo(w, h-mChargingOffset);
64612fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
647cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (lastScreenOn) {
64812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            mScreenOnPath.lineTo(w, h-mScreenOnOffset);
64912fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
650cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (lastGpsOn) {
651cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            mGpsOnPath.lineTo(w, h-mGpsOnOffset);
652cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
653be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        if (lastWifiRunning) {
654be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            mWifiRunningPath.lineTo(w, h-mWifiRunningOffset);
655be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        }
65655985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        if (lastCpuRunning) {
65755985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn            mCpuRunningPath.lineTo(w, h - mCpuRunningOffset);
658be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        }
659c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        if (mHavePhoneSignal) {
660c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            mPhoneSignalChart.finish(w);
661c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        }
66212fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn    }
6635a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
6645a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    private boolean is24Hour() {
6655a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        return DateFormat.is24HourFormat(getContext());
6665a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
6675a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
6685a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    private boolean isDayFirst() {
6695a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        String value = Settings.System.getString(mContext.getContentResolver(),
6705a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                Settings.System.DATE_FORMAT);
6715a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (value == null) {
6725a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            LocaleData d = LocaleData.get(mContext.getResources().getConfiguration().locale);
6735a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            value = d.shortDateFormat4;
6745a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
6755a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        return value.indexOf('M') > value.indexOf('d');
6765a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
6775a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
6785a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    /*
6795a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    private void buildTime() {
6805a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(context);
6815a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final Calendar now = Calendar.getInstance();
6825a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDummyDate.setTimeZone(now.getTimeZone());
6835a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        // We use December 31st because it's unambiguous when demonstrating the date format.
6845a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        // We use 13:00 so we can demonstrate the 12/24 hour options.
6855a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDummyDate.set(now.get(Calendar.YEAR), 11, 31, 13, 0, 0);
6865a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        Date dummyDate = mDummyDate.getTime();
6875a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mTimePref.setSummary(DateFormat.getTimeFormat(getActivity()).format(now.getTime()));
6885a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mTimeZone.setSummary(getTimeZoneText(now.getTimeZone(), true));
6895a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDatePref.setSummary(shortDateFormat.format(now.getTime()));
6905a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDateFormat.setSummary(shortDateFormat.format(dummyDate));
6915a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mTime24Pref.setSummary(DateFormat.getTimeFormat(getActivity()).format(dummyDate));
6925a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
6935a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
6945a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    */
6955a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
696ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    @Override
697ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
698ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        super.onSizeChanged(w, h, oldw, oldh);
6995a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
7005a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "onSizeChanged: " + oldw + "x" + oldh + " to " + w + "x" + h);
7015a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
7025a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (mLastWidth == w && mLastHeight == h) {
7035a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            return;
7045a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
7055a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
706a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        if (mLastWidth == 0 || mLastHeight == 0) {
707a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn            return;
708a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        }
709a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn
7106fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        if (DEBUG) Log.d(TAG, "Rebuilding chart for: " + w + "x" + h);
7116fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
712a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        mLastWidth = w;
713a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        mLastHeight = h;
7146fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        mBitmap = null;
7156fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        mCanvas = null;
716a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn
717cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        int textHeight = mTextDescent - mTextAscent;
7187158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        if (h > ((textHeight*10)+mChartMinHeight)) {
719cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            mLargeMode = true;
720b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn            if (h > (textHeight*15)) {
721b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn                // Plenty of room for the chart.
722b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn                mLineWidth = textHeight/2;
723b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn            } else {
724b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn                // Compress lines to make more room for chart.
725b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn                mLineWidth = textHeight/3;
726b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn            }
727cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        } else {
728cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            mLargeMode = false;
729cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            mLineWidth = mThinLineWidth;
730cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
731cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (mLineWidth <= 0) mLineWidth = 1;
7325a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
7337158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        mLevelTop = mHeaderHeight;
7345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mLevelLeft = mMaxPercentLabelStringWidth + mThinLineWidth*3;
7355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mLevelRight = w;
7365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        int levelWidth = mLevelRight-mLevelLeft;
7375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
738cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mTextPaint.setStrokeWidth(mThinLineWidth);
739cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mBatteryGoodPaint.setStrokeWidth(mThinLineWidth);
740cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mBatteryWarnPaint.setStrokeWidth(mThinLineWidth);
741cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mBatteryCriticalPaint.setStrokeWidth(mThinLineWidth);
742cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mChargingPaint.setStrokeWidth(mLineWidth);
743cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mScreenOnPaint.setStrokeWidth(mLineWidth);
744cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mGpsOnPaint.setStrokeWidth(mLineWidth);
745be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        mWifiRunningPaint.setStrokeWidth(mLineWidth);
74655985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        mCpuRunningPaint.setStrokeWidth(mLineWidth);
7475a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mDebugRectPaint.setStrokeWidth(1);
7485a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
7495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        int fullBarOffset = textHeight + mLineWidth;
750cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
751cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (mLargeMode) {
752be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            mChargingOffset = mLineWidth;
7535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mScreenOnOffset = mChargingOffset + fullBarOffset;
7545a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mCpuRunningOffset = mScreenOnOffset + fullBarOffset;
7555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mWifiRunningOffset = mCpuRunningOffset + fullBarOffset;
7565a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mGpsOnOffset = mWifiRunningOffset + (mHaveWifi ? fullBarOffset : 0);
7575a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mPhoneSignalOffset = mGpsOnOffset + (mHaveGps ? fullBarOffset : 0);
7585a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mLevelOffset = mPhoneSignalOffset + (mHavePhoneSignal ? fullBarOffset : 0)
7595a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    + mLineWidth*2 + mLineWidth/2;
760c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            if (mHavePhoneSignal) {
761c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani                mPhoneSignalChart.init(w);
762c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            }
763cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        } else {
764be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            mScreenOnOffset = mGpsOnOffset = mWifiRunningOffset
7655a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    = mCpuRunningOffset = mChargingOffset = mPhoneSignalOffset = 0;
7665a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mLevelOffset = fullBarOffset + mThinLineWidth*4;
767c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            if (mHavePhoneSignal) {
768c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani                mPhoneSignalChart.init(0);
769c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            }
770cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
771cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
7724f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        mBatLevelPath.reset();
77312fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatGoodPath.reset();
77412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatWarnPath.reset();
7755a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        mTimeRemainPath.reset();
77612fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mBatCriticalPath.reset();
77712fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mScreenOnPath.reset();
778cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mGpsOnPath.reset();
779be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        mWifiRunningPath.reset();
78055985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        mCpuRunningPath.reset();
78112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        mChargingPath.reset();
7825a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
783a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        mTimeLabels.clear();
784a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn        mDateLabels.clear();
785a32d81797f0e8164f922d9626ed6258c93b72772Dianne Hackborn
7865a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final long walltimeStart = mStartWallTime;
787c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn        final long walltimeChange = mEndWallTime > walltimeStart
788c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                ? (mEndWallTime-walltimeStart) : 1;
7892b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn        long curWalltime = mStartWallTime;
7905a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        long lastRealtime = 0;
7915a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
792ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final int batLow = mBatLow;
793ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final int batChange = mBatHigh-mBatLow;
7945a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
795cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        final int levelh = h - mLevelOffset - mLevelTop;
796cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        mLevelBottom = mLevelTop + levelh;
7975a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
7985a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        int x = mLevelLeft, y = 0, startX = mLevelLeft, lastX = -1, lastY = -1;
79912fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        int i = 0;
80012fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        Path curLevelPath = null;
80112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        Path lastLinePath = null;
802cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        boolean lastCharging = false, lastScreenOn = false, lastGpsOn = false;
80396debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn        boolean lastWifiRunning = false, lastWifiSupplRunning = false, lastCpuRunning = false;
80496debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn        int lastWifiSupplState = BatteryStats.WIFI_SUPPL_STATE_INVALID;
805ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        final int N = mNumHist;
8062b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn        if (mEndDataWallTime > mStartWallTime && mStats.startIteratingHistoryLocked()) {
80719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            final HistoryItem rec = new HistoryItem();
80819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn            while (mStats.getNextHistoryLocked(rec) && i < N) {
8092b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                if (rec.isDeltaData()) {
8105a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    curWalltime += rec.time-lastRealtime;
8115a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    lastRealtime = rec.time;
8125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    x = mLevelLeft + (int)(((curWalltime-walltimeStart)*levelWidth)/walltimeChange);
8131cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn                    if (x < 0) {
8141cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn                        x = 0;
8151cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn                    }
8165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (false) {
8175a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        StringBuilder sb = new StringBuilder(128);
8185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        sb.append("walloff=");
8195a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        TimeUtils.formatDuration(curWalltime - walltimeStart, sb);
8205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        sb.append(" wallchange=");
8215a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        TimeUtils.formatDuration(walltimeChange, sb);
8225a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        sb.append(" x=");
8235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        sb.append(x);
8245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        Log.d("foo", sb.toString());
8255a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
82619df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    y = mLevelTop + levelh - ((rec.batteryLevel-batLow)*(levelh-1))/batChange;
82719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
82819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                    if (lastX != x) {
82919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                        // We have moved by at least a pixel.
83019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                        if (lastY != y) {
83119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            // Don't plot changes within a pixel.
83219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            Path path;
83319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            byte value = rec.batteryLevel;
8347158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                            if (value <= mBatteryCriticalLevel) path = mBatCriticalPath;
8357158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                            else if (value <= mBatteryWarnLevel) path = mBatWarnPath;
8367158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                            else path = null; //mBatGoodPath;
83719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
83819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            if (path != lastLinePath) {
83919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                if (lastLinePath != null) {
84019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                    lastLinePath.lineTo(x, y);
84119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                }
8427158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                                if (path != null) {
8437158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                                    path.moveTo(x, y);
8447158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                                }
84519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                lastLinePath = path;
8467158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                            } else if (path != null) {
84719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                path.lineTo(x, y);
84819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            }
84919df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
85019df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            if (curLevelPath == null) {
85119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                curLevelPath = mBatLevelPath;
85219df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                curLevelPath.moveTo(x, y);
85319df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                startX = x;
85419df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            } else {
85519df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                                curLevelPath.lineTo(x, y);
85612fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                            }
85719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            lastX = x;
85819df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                            lastY = y;
85912fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                        }
86056247a63fc621815ecff82a278ad8553174922a0Todd Poynor                    }
86119df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn
8625a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (mLargeMode) {
8635a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        final boolean charging =
8645a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            (rec.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) != 0;
8655a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (charging != lastCharging) {
8665a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (charging) {
8675a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mChargingPath.moveTo(x, h-mChargingOffset);
8685a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
8695a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mChargingPath.lineTo(x, h-mChargingOffset);
8705a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
8715a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            lastCharging = charging;
87212fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                        }
873cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
8745a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        final boolean screenOn =
8755a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            (rec.states&HistoryItem.STATE_SCREEN_ON_FLAG) != 0;
8765a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (screenOn != lastScreenOn) {
8775a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (screenOn) {
8785a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mScreenOnPath.moveTo(x, h-mScreenOnOffset);
8795a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
8805a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mScreenOnPath.lineTo(x, h-mScreenOnOffset);
8815a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
8825a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            lastScreenOn = screenOn;
88312fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn                        }
884cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
8855a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        final boolean gpsOn =
8865a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            (rec.states&HistoryItem.STATE_GPS_ON_FLAG) != 0;
8875a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (gpsOn != lastGpsOn) {
8885a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (gpsOn) {
8895a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mGpsOnPath.moveTo(x, h-mGpsOnOffset);
8905a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
8915a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mGpsOnPath.lineTo(x, h-mGpsOnOffset);
8925a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
8935a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            lastGpsOn = gpsOn;
894cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn                        }
895cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
89696debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        final int wifiSupplState =
89796debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            ((rec.states2&HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
89896debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                    >> HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
89996debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        boolean wifiRunning;
90096debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        if (lastWifiSupplState != wifiSupplState) {
90196debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            lastWifiSupplState = wifiSupplState;
90296debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            switch (wifiSupplState) {
90396debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_DISCONNECTED:
90496debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_DORMANT:
90596debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_INACTIVE:
90696debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_INTERFACE_DISABLED:
90796debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_INVALID:
90896debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                case BatteryStats.WIFI_SUPPL_STATE_UNINITIALIZED:
90996debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                    wifiRunning = lastWifiSupplRunning = false;
91096debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                    break;
91196debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                default:
91296debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                    wifiRunning = lastWifiSupplRunning = true;
91396debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                    break;
91496debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            }
91596debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        } else {
91696debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            wifiRunning = lastWifiSupplRunning;
91796debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        }
91896debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        if ((rec.states&(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG
91996debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                |HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG
92096debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                |HistoryItem.STATE_WIFI_SCAN_FLAG)) != 0) {
92196debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                            wifiRunning = true;
92296debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                        }
9235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (wifiRunning != lastWifiRunning) {
9245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (wifiRunning) {
9255a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mWifiRunningPath.moveTo(x, h-mWifiRunningOffset);
9265a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
9275a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mWifiRunningPath.lineTo(x, h-mWifiRunningOffset);
9285a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
9295a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            lastWifiRunning = wifiRunning;
930cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn                        }
931cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
9325a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        final boolean cpuRunning =
9335a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            (rec.states&HistoryItem.STATE_CPU_RUNNING_FLAG) != 0;
9345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (cpuRunning != lastCpuRunning) {
9355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (cpuRunning) {
9365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mCpuRunningPath.moveTo(x, h - mCpuRunningOffset);
9375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
9385a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                mCpuRunningPath.lineTo(x, h - mCpuRunningOffset);
9395a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
9405a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            lastCpuRunning = cpuRunning;
941be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                        }
942be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn
9435a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        if (mLargeMode && mHavePhoneSignal) {
9445a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            int bin;
9455a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            if (((rec.states&HistoryItem.STATE_PHONE_STATE_MASK)
9465a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                    >> HistoryItem.STATE_PHONE_STATE_SHIFT)
9475a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                    == ServiceState.STATE_POWER_OFF) {
9485a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                bin = 0;
9495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else if ((rec.states&HistoryItem.STATE_PHONE_SCANNING_FLAG) != 0) {
9505a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                bin = 1;
9515a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            } else {
95296debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                bin = (rec.states&HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
95396debb5c96e8b75945ea2c2e1171cf29fe2c2887Dianne Hackborn                                        >> HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT;
9545a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                                bin += 2;
9555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            }
9565a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                            mPhoneSignalChart.addTick(x, bin);
957be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                        }
958be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                    }
959be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn
9602b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                } else {
9612b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    long lastWalltime = curWalltime;
9622b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
9632b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            || rec.cmd == HistoryItem.CMD_RESET) {
9642b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        if (rec.currentTime >= mStartWallTime) {
9652b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            curWalltime = rec.currentTime;
9662b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        } else {
9672b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            curWalltime = mStartWallTime + (rec.time-mHistStart);
9682b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        }
9692b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        lastRealtime = rec.time;
9702b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    }
9712b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn
9722b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                    if (rec.cmd != HistoryItem.CMD_OVERFLOW
9732b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            && (rec.cmd != HistoryItem.CMD_CURRENT_TIME
9742b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                                    || Math.abs(lastWalltime-curWalltime) > (60*60*1000))) {
9752b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        if (curLevelPath != null) {
9762b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            finishPaths(x+1, h, levelh, startX, lastY, curLevelPath, lastX,
9772b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                                    lastCharging, lastScreenOn, lastGpsOn, lastWifiRunning,
9782b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                                    lastCpuRunning, lastLinePath);
9792b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            lastX = lastY = -1;
9802b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            curLevelPath = null;
9812b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            lastLinePath = null;
9822b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                            lastCharging = lastScreenOn = lastGpsOn = lastCpuRunning = false;
9832b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn                        }
9844f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn                    }
9854f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn                }
98612fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn
98719df79af269c4a2354b0989cebfcfe949aea42c4Dianne Hackborn                i++;
988ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn            }
9892b54a9fa571a429e188b5e37d4732debd3e90ac0Dianne Hackborn            mStats.finishIteratingHistoryLocked();
990ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn        }
9915a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
992c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn        if (lastY < 0 || lastX < 0) {
993c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            // Didn't get any data...
994c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            x = lastX = mLevelLeft;
995c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            y = lastY = mLevelTop + levelh - ((mBatteryLevel-batLow)*(levelh-1))/batChange;
996c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            Path path;
997c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            byte value = (byte)mBatteryLevel;
998c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            if (value <= mBatteryCriticalLevel) path = mBatCriticalPath;
999c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            else if (value <= mBatteryWarnLevel) path = mBatWarnPath;
1000c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            else path = null; //mBatGoodPath;
1001c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            if (path != null) {
1002c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                path.moveTo(x, y);
1003c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn                lastLinePath = path;
1004c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            }
1005c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            mBatLevelPath.moveTo(x, y);
1006c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            curLevelPath = mBatLevelPath;
1007c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            x = w;
1008c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn        } else {
1009c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            // Figure out where the actual data ends on the screen.
1010c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn            x = mLevelLeft + (int)(((mEndDataWallTime-walltimeStart)*levelWidth)/walltimeChange);
10111cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn            if (x < 0) {
10121cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn                x = 0;
10131cf2077c3762349f4838ab041e6a06363ebd0b26Dianne Hackborn            }
1014c19eb361a407058b76cbbc866106db9fc81d9596Dianne Hackborn        }
10155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
10165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        finishPaths(x, h, levelh, startX, lastY, curLevelPath, lastX,
1017be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                lastCharging, lastScreenOn, lastGpsOn, lastWifiRunning,
101855985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn                lastCpuRunning, lastLinePath);
10195a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
10205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (x < w) {
10215a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            // If we reserved room for the remaining time, create a final path to draw
10225a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            // that part of the UI.
10235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mTimeRemainPath.moveTo(x, lastY);
10245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int fullY = mLevelTop + levelh - ((100-batLow)*(levelh-1))/batChange;
10255a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int emptyY = mLevelTop + levelh - ((0-batLow)*(levelh-1))/batChange;
10265a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (mDischarging) {
10275a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mTimeRemainPath.lineTo(mLevelRight, emptyY);
10285a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            } else {
10295a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mTimeRemainPath.lineTo(mLevelRight, fullY);
10305a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mTimeRemainPath.lineTo(mLevelRight, emptyY);
10315a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
10325a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mTimeRemainPath.lineTo(x, emptyY);
10335a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mTimeRemainPath.close();
10345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
10355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
1036c891ce6565fbeba8414c470b109088ac959f7143Dianne Hackborn        if (mStartWallTime > 0 && mEndWallTime > mStartWallTime) {
10377158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            // Create the time labels at the bottom.
10387158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            boolean is24hr = is24Hour();
10397158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            Calendar calStart = Calendar.getInstance();
10407158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calStart.setTimeInMillis(mStartWallTime);
10417158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calStart.set(Calendar.MILLISECOND, 0);
10427158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calStart.set(Calendar.SECOND, 0);
10437158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calStart.set(Calendar.MINUTE, 0);
10447158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            long startRoundTime = calStart.getTimeInMillis();
10455a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (startRoundTime < mStartWallTime) {
10467158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calStart.set(Calendar.HOUR_OF_DAY, calStart.get(Calendar.HOUR_OF_DAY)+1);
10475a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                startRoundTime = calStart.getTimeInMillis();
10485a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
10497158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            Calendar calEnd = Calendar.getInstance();
10507158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calEnd.setTimeInMillis(mEndWallTime);
10517158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calEnd.set(Calendar.MILLISECOND, 0);
10527158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calEnd.set(Calendar.SECOND, 0);
10537158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            calEnd.set(Calendar.MINUTE, 0);
10547158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            long endRoundTime = calEnd.getTimeInMillis();
10555a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (startRoundTime < endRoundTime) {
10567158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                addTimeLabel(calStart, mLevelLeft, mLevelRight, is24hr);
10577158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                Calendar calMid = Calendar.getInstance();
10587158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calMid.setTimeInMillis(mStartWallTime+((mEndWallTime-mStartWallTime)/2));
10597158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calMid.set(Calendar.MILLISECOND, 0);
10607158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calMid.set(Calendar.SECOND, 0);
10617158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calMid.set(Calendar.MINUTE, 0);
10627158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                long calMidMillis = calMid.getTimeInMillis();
10637158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                if (calMidMillis > startRoundTime && calMidMillis < endRoundTime) {
10647158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    addTimeLabel(calMid, mLevelLeft, mLevelRight, is24hr);
10657158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                }
10667158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                addTimeLabel(calEnd, mLevelLeft, mLevelRight, is24hr);
10677158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            }
10687158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
10697158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            // Create the date labels if the chart includes multiple days
10707158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            if (calStart.get(Calendar.DAY_OF_YEAR) != calEnd.get(Calendar.DAY_OF_YEAR) ||
10717158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    calStart.get(Calendar.YEAR) != calEnd.get(Calendar.YEAR)) {
10727158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                boolean isDayFirst = isDayFirst();
10737158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calStart.set(Calendar.HOUR_OF_DAY, 0);
10747158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                startRoundTime = calStart.getTimeInMillis();
10757158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                if (startRoundTime < mStartWallTime) {
10767158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    calStart.set(Calendar.DAY_OF_YEAR, calStart.get(Calendar.DAY_OF_YEAR) + 1);
10777158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    startRoundTime = calStart.getTimeInMillis();
10787158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                }
10797158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                calEnd.set(Calendar.HOUR_OF_DAY, 0);
10807158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                endRoundTime = calEnd.getTimeInMillis();
10817158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                if (startRoundTime < endRoundTime) {
10827158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    addDateLabel(calStart, mLevelLeft, mLevelRight, isDayFirst);
10836fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    Calendar calMid = Calendar.getInstance();
10846fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    calMid.setTimeInMillis(startRoundTime + ((endRoundTime - startRoundTime) / 2));
10856fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    calMid.set(Calendar.HOUR_OF_DAY, 0);
10866fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    long calMidMillis = calMid.getTimeInMillis();
10876fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    if (calMidMillis > startRoundTime && calMidMillis < endRoundTime) {
10886fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                        addDateLabel(calMid, mLevelLeft, mLevelRight, isDayFirst);
10896fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                    }
10907158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                }
10917158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                addDateLabel(calEnd, mLevelLeft, mLevelRight, isDayFirst);
10925a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
10937158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        }
10947158e6299210d08f82c29135c001652508b79dfbDianne Hackborn
10957158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        if (mTimeLabels.size() < 2) {
10967158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            // If there are fewer than 2 time labels, then they are useless.  Just
10977158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            // show an axis label giving the entire duration.
10987158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            mDurationString = Formatter.formatShortElapsedTime(getContext(),
10997158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    mEndWallTime - mStartWallTime);
11007158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            mDurationStringWidth = (int)mTextPaint.measureText(mDurationString);
11017158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        } else {
11027158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            mDurationString = null;
11037158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            mDurationStringWidth = 0;
11045a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
11054f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    }
11065a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11075a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    void addTimeLabel(Calendar cal, int levelLeft, int levelRight, boolean is24hr) {
11085a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final long walltimeStart = mStartWallTime;
11095a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final long walltimeChange = mEndWallTime-walltimeStart;
1110a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio        mTimeLabels.add(new TimeLabel(mTextPaint,
11115a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                levelLeft + (int)(((cal.getTimeInMillis()-walltimeStart)*(levelRight-levelLeft))
11125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        / walltimeChange),
11135a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                cal, is24hr));
11145a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
11155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    void addDateLabel(Calendar cal, int levelLeft, int levelRight, boolean isDayFirst) {
11175a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final long walltimeStart = mStartWallTime;
11185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        final long walltimeChange = mEndWallTime-walltimeStart;
1119a7a62c5b66189f114a8ad41c53bbe0bb00ae1e90Fabrice Di Meglio        mDateLabels.add(new DateLabel(mTextPaint,
11205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                levelLeft + (int)(((cal.getTimeInMillis()-walltimeStart)*(levelRight-levelLeft))
11215a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        / walltimeChange),
11225a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                cal, isDayFirst));
11235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn    }
11245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11254f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    @Override
11264f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn    protected void onDraw(Canvas canvas) {
11274f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        super.onDraw(canvas);
112874809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani
11294f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        final int width = getWidth();
11304f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        final int height = getHeight();
11315a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11326fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        //buildBitmap(width, height);
11336fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
11345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "onDraw: " + width + "x" + height);
11356fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        //canvas.drawBitmap(mBitmap, 0, 0, null);
11366fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        drawChart(canvas, width, height);
11376fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    }
11386fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
11396fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    void buildBitmap(int width, int height) {
11406fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        if (mBitmap != null && width == mBitmap.getWidth() && height == mBitmap.getHeight()) {
11416fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn            return;
11426fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        }
11436fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
11446fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        if (DEBUG) Log.d(TAG, "buildBitmap: " + width + "x" + height);
11456fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn
11466fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        mBitmap = Bitmap.createBitmap(getResources().getDisplayMetrics(), width, height,
11476fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn                Bitmap.Config.ARGB_8888);
11486fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        mCanvas = new Canvas(mBitmap);
11496fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn        drawChart(mCanvas, width, height);
11506fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    }
11515a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11526fd48e224f89e4d4e154dcf2e494c201293cc167Dianne Hackborn    void drawChart(Canvas canvas, int width, int height) {
115374809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani        final boolean layoutRtl = isLayoutRtl();
115474809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani        final int textStartX = layoutRtl ? width : 0;
11550be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final int textEndX = layoutRtl ? 0 : width;
11560be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final Paint.Align textAlignLeft = layoutRtl ? Paint.Align.RIGHT : Paint.Align.LEFT;
11570be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        final Paint.Align textAlignRight = layoutRtl ? Paint.Align.LEFT : Paint.Align.RIGHT;
115874809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani
11595a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) {
11605a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            canvas.drawRect(1, 1, width, height, mDebugRectPaint);
11615a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
11625a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
11635a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "Drawing level path.");
11644f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        canvas.drawPath(mBatLevelPath, mBatteryBackgroundPaint);
11655a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (!mTimeRemainPath.isEmpty()) {
11665a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing time remain path.");
11675a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            canvas.drawPath(mTimeRemainPath, mTimeRemainPaint);
11685a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
11697158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        if (mTimeLabels.size() > 1) {
11705a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int y = mLevelBottom - mTextAscent + (mThinLineWidth*4);
11715a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int ytick = mLevelBottom+mThinLineWidth+(mThinLineWidth/2);
11725a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mTextPaint.setTextAlign(Paint.Align.LEFT);
11735a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int lastX = 0;
11745a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            for (int i=0; i<mTimeLabels.size(); i++) {
11755a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                TimeLabel label = mTimeLabels.get(i);
11765a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (i == 0) {
11775a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    int x = label.x - label.width/2;
11785a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (x < 0) {
11795a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        x = 0;
11805a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
11815a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (DEBUG) Log.d(TAG, "Drawing left label: " + label.label + " @ " + x);
11825a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawText(label.label, x, y, mTextPaint);
11835a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawLine(label.x, ytick, label.x, ytick+mThinLineWidth, mTextPaint);
11845a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    lastX = x + label.width;
11855a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                } else if (i < (mTimeLabels.size()-1)) {
11865a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    int x = label.x - label.width/2;
11875a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (x < (lastX+mTextAscent)) {
11885a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        continue;
11895a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
11905a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    TimeLabel nextLabel = mTimeLabels.get(i+1);
11915a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (x > (width-nextLabel.width-mTextAscent)) {
11925a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        continue;
11935a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
11945a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (DEBUG) Log.d(TAG, "Drawing middle label: " + label.label + " @ " + x);
11955a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawText(label.label, x, y, mTextPaint);
11965a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawLine(label.x, ytick, label.x, ytick + mThinLineWidth, mTextPaint);
11975a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    lastX = x + label.width;
11985a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                } else {
11995a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    int x = label.x - label.width/2;
12005a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if ((x+label.width) >= width) {
12015a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        x = width-1-label.width;
12025a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
12035a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (DEBUG) Log.d(TAG, "Drawing right label: " + label.label + " @ " + x);
12045a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawText(label.label, x, y, mTextPaint);
12055a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    canvas.drawLine(label.x, ytick, label.x, ytick+mThinLineWidth, mTextPaint);
12065a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                }
12075a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
12087158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        } else if (mDurationString != null) {
12097158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            int y = mLevelBottom - mTextAscent + (mThinLineWidth*4);
12107158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            mTextPaint.setTextAlign(Paint.Align.LEFT);
12117158e6299210d08f82c29135c001652508b79dfbDianne Hackborn            canvas.drawText(mDurationString,
12127158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    mLevelLeft + (mLevelRight-mLevelLeft)/2 - mDurationStringWidth/2,
12137158e6299210d08f82c29135c001652508b79dfbDianne Hackborn                    y, mTextPaint);
12145a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
12155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
12165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        int headerTop = -mHeaderTextAscent + (mHeaderTextDescent-mHeaderTextAscent)/3;
12170be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mHeaderTextPaint.setTextAlign(textAlignLeft);
12185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "Drawing charge label string: " + mChargeLabelString);
12190be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        canvas.drawText(mChargeLabelString, textStartX, headerTop, mHeaderTextPaint);
12207158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        int stringHalfWidth = mChargeDurationStringWidth / 2;
12217158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        if (layoutRtl) stringHalfWidth = -stringHalfWidth;
12220be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        int headerCenter = ((width-mChargeDurationStringWidth-mDrainStringWidth)/2)
12230be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                + (layoutRtl ? mDrainStringWidth : mChargeLabelStringWidth);
12245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "Drawing charge duration string: " + mChargeDurationString);
12257158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        canvas.drawText(mChargeDurationString, headerCenter - stringHalfWidth, headerTop,
12260be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn                mHeaderTextPaint);
12270be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        mHeaderTextPaint.setTextAlign(textAlignRight);
12285a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "Drawing drain string: " + mDrainString);
12290be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn        canvas.drawText(mDrainString, textEndX, headerTop, mHeaderTextPaint);
12300be7598cb8c8cf6808b336204632615c5f26298fDianne Hackborn
123112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        if (!mBatGoodPath.isEmpty()) {
12325a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing good battery path");
123312fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            canvas.drawPath(mBatGoodPath, mBatteryGoodPaint);
123412fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
123512fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        if (!mBatWarnPath.isEmpty()) {
12365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing warn battery path");
123712fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            canvas.drawPath(mBatWarnPath, mBatteryWarnPaint);
123812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
123912fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        if (!mBatCriticalPath.isEmpty()) {
12405a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing critical battery path");
124112fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            canvas.drawPath(mBatCriticalPath, mBatteryCriticalPaint);
124212fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        }
1243c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        if (mHavePhoneSignal) {
12445a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing phone signal path");
1245b28c0c95c21bb60b8259b0cafb16754e590b4a9bDianne Hackborn            int top = height-mPhoneSignalOffset - (mLineWidth/2);
1246c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            mPhoneSignalChart.draw(canvas, top, mLineWidth);
1247c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        }
124812fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn        if (!mScreenOnPath.isEmpty()) {
12495a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing screen on path");
125012fd447d6f46b0c06072b0e9735589bf14cc53f6Dianne Hackborn            canvas.drawPath(mScreenOnPath, mScreenOnPaint);
12514f0e5350fccd78bf881b938aaf0f484d135829a0Dianne Hackborn        }
1252cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (!mChargingPath.isEmpty()) {
12535a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing charging path");
1254cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            canvas.drawPath(mChargingPath, mChargingPaint);
1255cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
1256be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        if (mHaveGps) {
1257be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            if (!mGpsOnPath.isEmpty()) {
12585a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (DEBUG) Log.d(TAG, "Drawing gps path");
1259be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                canvas.drawPath(mGpsOnPath, mGpsOnPaint);
1260be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            }
1261be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        }
1262be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        if (mHaveWifi) {
1263be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            if (!mWifiRunningPath.isEmpty()) {
12645a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (DEBUG) Log.d(TAG, "Drawing wifi path");
1265be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                canvas.drawPath(mWifiRunningPath, mWifiRunningPaint);
1266be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            }
1267be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn        }
126855985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn        if (!mCpuRunningPath.isEmpty()) {
12695a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing running path");
127055985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn            canvas.drawPath(mCpuRunningPath, mCpuRunningPaint);
1271cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
1272cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn
1273cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        if (mLargeMode) {
12745a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            if (DEBUG) Log.d(TAG, "Drawing large mode labels");
1275a312f7f8044a07a2a41de477cc30bb34fc1df55fJohn Spurlock            Paint.Align align = mTextPaint.getTextAlign();
1276a312f7f8044a07a2a41de477cc30bb34fc1df55fJohn Spurlock            mTextPaint.setTextAlign(textAlignLeft);  // large-mode labels always aligned to start
1277c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            if (mHavePhoneSignal) {
127874809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani                canvas.drawText(mPhoneSignalLabel, textStartX,
1279c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani                        height - mPhoneSignalOffset - mTextDescent, mTextPaint);
1280c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            }
1281be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            if (mHaveGps) {
128274809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani                canvas.drawText(mGpsOnLabel, textStartX,
1283be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                        height - mGpsOnOffset - mTextDescent, mTextPaint);
1284be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            }
1285be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            if (mHaveWifi) {
128674809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani                canvas.drawText(mWifiRunningLabel, textStartX,
1287be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn                        height - mWifiRunningOffset - mTextDescent, mTextPaint);
1288be5994d20152c7194aac79eb8152240655fd3373Dianne Hackborn            }
128955985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn            canvas.drawText(mCpuRunningLabel, textStartX,
129055985d2ceca9cecfbc07bb331bf48fe28849b818Dianne Hackborn                    height - mCpuRunningOffset - mTextDescent, mTextPaint);
129174809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani            canvas.drawText(mChargingLabel, textStartX,
1292cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn                    height - mChargingOffset - mTextDescent, mTextPaint);
129374809c2679d9c046f73acb4473434f9f5ad4b1c1Amith Yamasani            canvas.drawText(mScreenOnLabel, textStartX,
1294cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn                    height - mScreenOnOffset - mTextDescent, mTextPaint);
1295a312f7f8044a07a2a41de477cc30bb34fc1df55fJohn Spurlock            mTextPaint.setTextAlign(align);
12965a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
12975a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
12985a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        canvas.drawLine(mLevelLeft-mThinLineWidth, mLevelTop, mLevelLeft-mThinLineWidth,
12995a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mLevelBottom+(mThinLineWidth/2), mTextPaint);
13005a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (mLargeMode) {
1301cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            for (int i=0; i<10; i++) {
13025a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                int y = mLevelTop + mThinLineWidth/2 + ((mLevelBottom-mLevelTop)*i)/10;
13035a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                canvas.drawLine(mLevelLeft-mThinLineWidth*2-mThinLineWidth/2, y,
13045a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        mLevelLeft-mThinLineWidth-mThinLineWidth/2, y, mTextPaint);
13055a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            }
13065a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        }
13075a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (DEBUG) Log.d(TAG, "Drawing max percent, origw=" + mMaxPercentLabelStringWidth
13085a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                + ", noww=" + (int)mTextPaint.measureText(mMaxPercentLabelString));
13095a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        canvas.drawText(mMaxPercentLabelString, 0, mLevelTop, mTextPaint);
13105a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        canvas.drawText(mMinPercentLabelString,
13115a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mMaxPercentLabelStringWidth-mMinPercentLabelStringWidth,
13125a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mLevelBottom - mThinLineWidth, mTextPaint);
13137158e6299210d08f82c29135c001652508b79dfbDianne Hackborn        canvas.drawLine(mLevelLeft/2, mLevelBottom+mThinLineWidth, width,
13145a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mLevelBottom+mThinLineWidth, mTextPaint);
13155a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn
13165a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn        if (mDateLabels.size() > 0) {
13175a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int ytop = mLevelTop + mTextAscent;
13185a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int ybottom = mLevelBottom;
13195a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            int lastLeft = mLevelRight;
13205a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            mTextPaint.setTextAlign(Paint.Align.LEFT);
13215a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn            for (int i=mDateLabels.size()-1; i>=0; i--) {
13225a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                DateLabel label = mDateLabels.get(i);
13235a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                int left = label.x - mThinLineWidth;
13245a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                int x = label.x + mThinLineWidth*2;
13255a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if ((x+label.width) >= lastLeft) {
13265a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    x = label.x - mThinLineWidth*2 - label.width;
13275a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    left = x - mThinLineWidth;
13285a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    if (left >= lastLeft) {
13295a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        // okay we give up.
13305a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                        continue;
13315a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    }
13325a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                }
13335a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                if (left < mLevelLeft) {
13345a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    // Won't fit on left, give up.
13355a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                    continue;
13365a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                }
13375a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mDateLinePath.reset();
13385a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mDateLinePath.moveTo(label.x, ytop);
13395a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                mDateLinePath.lineTo(label.x, ybottom);
13405a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                canvas.drawPath(mDateLinePath, mDateLinePaint);
13415a9ace3a7abe5de8d6f3307dad830ac9b1d5ae04Dianne Hackborn                canvas.drawText(label.label, x, ytop - mTextAscent, mTextPaint);
1342cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn            }
1343cbaf6ceb8e6b2d36a40589de6380ff93e75335dfDianne Hackborn        }
1344ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn    }
1345ea38e678537cf740b5f30c1d69c7a332e98cdd2cDianne Hackborn}
1346