void setStats(BatteryStats stats) {
    mStats = stats;

    long uSecTime =
        mStats.computeBatteryRealtime(
            SystemClock.elapsedRealtime() * 1000, BatteryStats.STATS_SINCE_CHARGED);
    mStatsPeriod = uSecTime;
    String durationString = Utils.formatElapsedTime(getContext(), mStatsPeriod / 1000);
    mDurationString = getContext().getString(R.string.battery_stats_on_battery, durationString);
    mChargingLabel = getContext().getString(R.string.battery_stats_charging_label);
    mScreenOnLabel = getContext().getString(R.string.battery_stats_screen_on_label);
    mGpsOnLabel = getContext().getString(R.string.battery_stats_gps_on_label);
    mWifiRunningLabel = getContext().getString(R.string.battery_stats_wifi_running_label);
    mWakeLockLabel = getContext().getString(R.string.battery_stats_wake_lock_label);
    mPhoneSignalLabel = getContext().getString(R.string.battery_stats_phone_signal_label);

    int pos = 0;
    int lastInteresting = 0;
    byte lastLevel = -1;
    mBatLow = 0;
    mBatHigh = 100;
    int aggrStates = 0;
    boolean first = true;
    if (stats.startIteratingHistoryLocked()) {
      final HistoryItem rec = new HistoryItem();
      while (stats.getNextHistoryLocked(rec)) {
        pos++;
        if (rec.cmd == HistoryItem.CMD_UPDATE) {
          if (first) {
            first = false;
            mHistStart = rec.time;
          }
          if (rec.batteryLevel != lastLevel || pos == 1) {
            lastLevel = rec.batteryLevel;
            lastInteresting = pos;
            mHistEnd = rec.time;
          }
          aggrStates |= rec.states;
        }
      }
    }
    mNumHist = lastInteresting;
    mHaveGps = (aggrStates & HistoryItem.STATE_GPS_ON_FLAG) != 0;
    mHaveWifi = (aggrStates & HistoryItem.STATE_WIFI_RUNNING_FLAG) != 0;

    if (mHistEnd <= mHistStart) mHistEnd = mHistStart + 1;
    mTotalDurationString = Utils.formatElapsedTime(getContext(), mHistEnd - mHistStart);
  }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    int textHeight = mTextDescent - mTextAscent;
    mThinLineWidth =
        (int)
            TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics());
    if (h > (textHeight * 6)) {
      mLargeMode = true;
      mLineWidth = textHeight / 2;
      mLevelTop = textHeight + mLineWidth;
      mScreenOnPaint.setARGB(255, 32, 64, 255);
      mGpsOnPaint.setARGB(255, 32, 64, 255);
      mWifiRunningPaint.setARGB(255, 32, 64, 255);
      mWakeLockPaint.setARGB(255, 32, 64, 255);
    } else {
      mLargeMode = false;
      mLineWidth = mThinLineWidth;
      mLevelTop = 0;
      mScreenOnPaint.setARGB(255, 0, 0, 255);
      mGpsOnPaint.setARGB(255, 0, 0, 255);
      mWifiRunningPaint.setARGB(255, 0, 0, 255);
      mWakeLockPaint.setARGB(255, 0, 0, 255);
    }
    if (mLineWidth <= 0) mLineWidth = 1;
    mTextPaint.setStrokeWidth(mThinLineWidth);
    mBatteryGoodPaint.setStrokeWidth(mThinLineWidth);
    mBatteryWarnPaint.setStrokeWidth(mThinLineWidth);
    mBatteryCriticalPaint.setStrokeWidth(mThinLineWidth);
    mChargingPaint.setStrokeWidth(mLineWidth);
    mScreenOnPaint.setStrokeWidth(mLineWidth);
    mGpsOnPaint.setStrokeWidth(mLineWidth);
    mWifiRunningPaint.setStrokeWidth(mLineWidth);
    mWakeLockPaint.setStrokeWidth(mLineWidth);

    if (mLargeMode) {
      int barOffset = textHeight + mLineWidth;
      mChargingOffset = mLineWidth;
      mScreenOnOffset = mChargingOffset + barOffset;
      mWakeLockOffset = mScreenOnOffset + barOffset;
      mWifiRunningOffset = mWakeLockOffset + barOffset;
      mGpsOnOffset = mWifiRunningOffset + (mHaveWifi ? barOffset : 0);
      mPhoneSignalOffset = mGpsOnOffset + (mHaveGps ? barOffset : 0);
      mLevelOffset = mPhoneSignalOffset + barOffset + mLineWidth;
      mPhoneSignalChart.init(w);
    } else {
      mScreenOnOffset = mGpsOnOffset = mWifiRunningOffset = mWakeLockOffset = mLineWidth;
      mChargingOffset = mLineWidth * 2;
      mPhoneSignalOffset = 0;
      mLevelOffset = mLineWidth * 3;
      mPhoneSignalChart.init(0);
    }

    mBatLevelPath.reset();
    mBatGoodPath.reset();
    mBatWarnPath.reset();
    mBatCriticalPath.reset();
    mScreenOnPath.reset();
    mGpsOnPath.reset();
    mWifiRunningPath.reset();
    mWakeLockPath.reset();
    mChargingPath.reset();

    final long timeStart = mHistStart;
    final long timeChange = mHistEnd - mHistStart;

    final int batLow = mBatLow;
    final int batChange = mBatHigh - mBatLow;

    final int levelh = h - mLevelOffset - mLevelTop;
    mLevelBottom = mLevelTop + levelh;

    int x = 0, y = 0, startX = 0, lastX = -1, lastY = -1;
    int i = 0;
    Path curLevelPath = null;
    Path lastLinePath = null;
    boolean lastCharging = false, lastScreenOn = false, lastGpsOn = false;
    boolean lastWifiRunning = false, lastWakeLock = false;
    final int N = mNumHist;
    if (mStats.startIteratingHistoryLocked()) {
      final HistoryItem rec = new HistoryItem();
      while (mStats.getNextHistoryLocked(rec) && i < N) {
        if (rec.cmd == BatteryStats.HistoryItem.CMD_UPDATE) {
          x = (int) (((rec.time - timeStart) * w) / timeChange);
          y = mLevelTop + levelh - ((rec.batteryLevel - batLow) * (levelh - 1)) / batChange;

          if (lastX != x) {
            // We have moved by at least a pixel.
            if (lastY != y) {
              // Don't plot changes within a pixel.
              Path path;
              byte value = rec.batteryLevel;
              if (value <= BATTERY_CRITICAL) path = mBatCriticalPath;
              else if (value <= BATTERY_WARN) path = mBatWarnPath;
              else path = mBatGoodPath;

              if (path != lastLinePath) {
                if (lastLinePath != null) {
                  lastLinePath.lineTo(x, y);
                }
                path.moveTo(x, y);
                lastLinePath = path;
              } else {
                path.lineTo(x, y);
              }

              if (curLevelPath == null) {
                curLevelPath = mBatLevelPath;
                curLevelPath.moveTo(x, y);
                startX = x;
              } else {
                curLevelPath.lineTo(x, y);
              }
              lastX = x;
              lastY = y;
            }

            final boolean charging = (rec.states & HistoryItem.STATE_BATTERY_PLUGGED_FLAG) != 0;
            if (charging != lastCharging) {
              if (charging) {
                mChargingPath.moveTo(x, h - mChargingOffset);
              } else {
                mChargingPath.lineTo(x, h - mChargingOffset);
              }
              lastCharging = charging;
            }

            final boolean screenOn = (rec.states & HistoryItem.STATE_SCREEN_ON_FLAG) != 0;
            if (screenOn != lastScreenOn) {
              if (screenOn) {
                mScreenOnPath.moveTo(x, h - mScreenOnOffset);
              } else {
                mScreenOnPath.lineTo(x, h - mScreenOnOffset);
              }
              lastScreenOn = screenOn;
            }

            final boolean gpsOn = (rec.states & HistoryItem.STATE_GPS_ON_FLAG) != 0;
            if (gpsOn != lastGpsOn) {
              if (gpsOn) {
                mGpsOnPath.moveTo(x, h - mGpsOnOffset);
              } else {
                mGpsOnPath.lineTo(x, h - mGpsOnOffset);
              }
              lastGpsOn = gpsOn;
            }

            final boolean wifiRunning = (rec.states & HistoryItem.STATE_WIFI_RUNNING_FLAG) != 0;
            if (wifiRunning != lastWifiRunning) {
              if (wifiRunning) {
                mWifiRunningPath.moveTo(x, h - mWifiRunningOffset);
              } else {
                mWifiRunningPath.lineTo(x, h - mWifiRunningOffset);
              }
              lastWifiRunning = wifiRunning;
            }

            final boolean wakeLock = (rec.states & HistoryItem.STATE_WAKE_LOCK_FLAG) != 0;
            if (wakeLock != lastWakeLock) {
              if (wakeLock) {
                mWakeLockPath.moveTo(x, h - mWakeLockOffset);
              } else {
                mWakeLockPath.lineTo(x, h - mWakeLockOffset);
              }
              lastWakeLock = wakeLock;
            }

            if (mLargeMode) {
              int bin;
              if (((rec.states & HistoryItem.STATE_PHONE_STATE_MASK)
                      >> HistoryItem.STATE_PHONE_STATE_SHIFT)
                  == ServiceState.STATE_POWER_OFF) {
                bin = 0;
              } else if ((rec.states & HistoryItem.STATE_PHONE_SCANNING_FLAG) != 0) {
                bin = 1;
              } else {
                bin =
                    (rec.states & HistoryItem.STATE_SIGNAL_STRENGTH_MASK)
                        >> HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT;
                bin += 2;
              }
              mPhoneSignalChart.addTick(x, bin);
            }
          }

        } else if (rec.cmd != BatteryStats.HistoryItem.CMD_OVERFLOW) {
          if (curLevelPath != null) {
            finishPaths(
                x + 1,
                h,
                levelh,
                startX,
                lastY,
                curLevelPath,
                lastX,
                lastCharging,
                lastScreenOn,
                lastGpsOn,
                lastWifiRunning,
                lastWakeLock,
                lastLinePath);
            lastX = lastY = -1;
            curLevelPath = null;
            lastLinePath = null;
            lastCharging = lastScreenOn = lastGpsOn = lastWakeLock = false;
          }
        }

        i++;
      }
    }

    finishPaths(
        w,
        h,
        levelh,
        startX,
        lastY,
        curLevelPath,
        lastX,
        lastCharging,
        lastScreenOn,
        lastGpsOn,
        lastWifiRunning,
        lastWakeLock,
        lastLinePath);
  }