BatteryStatsImpl.java revision 1e4b9f3936d6f357e89360293e05a0e16d5fa440
1/* 2 * Copyright (C) 2006-2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.os; 18 19import com.android.internal.util.JournaledFile; 20 21import android.bluetooth.BluetoothHeadset; 22import android.net.TrafficStats; 23import android.os.BatteryManager; 24import android.os.BatteryStats; 25import android.os.Parcel; 26import android.os.ParcelFormatException; 27import android.os.Parcelable; 28import android.os.Process; 29import android.os.SystemClock; 30import android.telephony.ServiceState; 31import android.telephony.SignalStrength; 32import android.telephony.TelephonyManager; 33import android.util.Log; 34import android.util.PrintWriterPrinter; 35import android.util.Printer; 36import android.util.Slog; 37import android.util.SparseArray; 38 39import java.io.BufferedReader; 40import java.io.File; 41import java.io.FileInputStream; 42import java.io.FileOutputStream; 43import java.io.FileReader; 44import java.io.IOException; 45import java.io.PrintWriter; 46import java.util.ArrayList; 47import java.util.HashMap; 48import java.util.Iterator; 49import java.util.Map; 50import java.util.concurrent.atomic.AtomicInteger; 51 52/** 53 * All information we are collecting about things that can happen that impact 54 * battery life. All times are represented in microseconds except where indicated 55 * otherwise. 56 */ 57public final class BatteryStatsImpl extends BatteryStats { 58 private static final String TAG = "BatteryStatsImpl"; 59 private static final boolean DEBUG = false; 60 private static final boolean DEBUG_HISTORY = false; 61 62 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data 63 private static final int MAGIC = 0xBA757475; // 'BATSTATS' 64 65 // Current on-disk Parcel version 66 private static final int VERSION = 48; 67 68 // Maximum number of items we will record in the history. 69 private static final int MAX_HISTORY_ITEMS = 1000; 70 71 // The maximum number of names wakelocks we will keep track of 72 // per uid; once the limit is reached, we batch the remaining wakelocks 73 // in to one common name. 74 private static final int MAX_WAKELOCKS_PER_UID = 20; 75 76 private static final String BATCHED_WAKELOCK_NAME = "*overflow*"; 77 78 private static int sNumSpeedSteps; 79 80 private final JournaledFile mFile; 81 82 /** 83 * The statistics we have collected organized by uids. 84 */ 85 final SparseArray<BatteryStatsImpl.Uid> mUidStats = 86 new SparseArray<BatteryStatsImpl.Uid>(); 87 88 // A set of pools of currently active timers. When a timer is queried, we will divide the 89 // elapsed time by the number of active timers to arrive at that timer's share of the time. 90 // In order to do this, we must refresh each timer whenever the number of active timers 91 // changes. 92 final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>(); 93 final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>(); 94 final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>(); 95 final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers 96 = new SparseArray<ArrayList<StopwatchTimer>>(); 97 98 // These are the objects that will want to do something when the device 99 // is unplugged from power. 100 final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>(); 101 102 boolean mShuttingDown; 103 104 long mHistoryBaseTime; 105 boolean mHaveBatteryLevel = false; 106 boolean mRecordingHistory = true; 107 int mNumHistoryItems; 108 HistoryItem mHistory; 109 HistoryItem mHistoryEnd; 110 HistoryItem mHistoryCache; 111 final HistoryItem mHistoryCur = new HistoryItem(); 112 113 int mStartCount; 114 115 long mBatteryUptime; 116 long mBatteryLastUptime; 117 long mBatteryRealtime; 118 long mBatteryLastRealtime; 119 120 long mUptime; 121 long mUptimeStart; 122 long mLastUptime; 123 long mRealtime; 124 long mRealtimeStart; 125 long mLastRealtime; 126 127 boolean mScreenOn; 128 StopwatchTimer mScreenOnTimer; 129 130 int mScreenBrightnessBin = -1; 131 final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS]; 132 133 Counter mInputEventCounter; 134 135 boolean mPhoneOn; 136 StopwatchTimer mPhoneOnTimer; 137 138 boolean mAudioOn; 139 StopwatchTimer mAudioOnTimer; 140 141 boolean mVideoOn; 142 StopwatchTimer mVideoOnTimer; 143 144 int mPhoneSignalStrengthBin = -1; 145 final StopwatchTimer[] mPhoneSignalStrengthsTimer = 146 new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS]; 147 148 StopwatchTimer mPhoneSignalScanningTimer; 149 150 int mPhoneDataConnectionType = -1; 151 final StopwatchTimer[] mPhoneDataConnectionsTimer = 152 new StopwatchTimer[NUM_DATA_CONNECTION_TYPES]; 153 154 boolean mWifiOn; 155 StopwatchTimer mWifiOnTimer; 156 int mWifiOnUid = -1; 157 158 boolean mWifiRunning; 159 StopwatchTimer mWifiRunningTimer; 160 161 boolean mBluetoothOn; 162 StopwatchTimer mBluetoothOnTimer; 163 164 /** Bluetooth headset object */ 165 BluetoothHeadset mBtHeadset; 166 167 /** 168 * These provide time bases that discount the time the device is plugged 169 * in to power. 170 */ 171 boolean mOnBattery; 172 boolean mOnBatteryInternal; 173 long mTrackBatteryPastUptime; 174 long mTrackBatteryUptimeStart; 175 long mTrackBatteryPastRealtime; 176 long mTrackBatteryRealtimeStart; 177 178 long mUnpluggedBatteryUptime; 179 long mUnpluggedBatteryRealtime; 180 181 /* 182 * These keep track of battery levels (1-100) at the last plug event and the last unplug event. 183 */ 184 int mDischargeStartLevel; 185 int mDischargeUnplugLevel; 186 int mDischargeCurrentLevel; 187 188 long mLastWriteTime = 0; // Milliseconds 189 190 // Mobile data transferred while on battery 191 private long[] mMobileDataTx = new long[4]; 192 private long[] mMobileDataRx = new long[4]; 193 private long[] mTotalDataTx = new long[4]; 194 private long[] mTotalDataRx = new long[4]; 195 196 private long mRadioDataUptime; 197 private long mRadioDataStart; 198 199 private int mBluetoothPingCount; 200 private int mBluetoothPingStart = -1; 201 202 private int mPhoneServiceState = -1; 203 204 /* 205 * Holds a SamplingTimer associated with each kernel wakelock name being tracked. 206 */ 207 private final HashMap<String, SamplingTimer> mKernelWakelockStats = 208 new HashMap<String, SamplingTimer>(); 209 210 public Map<String, ? extends SamplingTimer> getKernelWakelockStats() { 211 return mKernelWakelockStats; 212 } 213 214 private static int sKernelWakelockUpdateVersion = 0; 215 216 private static final int[] PROC_WAKELOCKS_FORMAT = new int[] { 217 Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name 218 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count 219 Process.PROC_TAB_TERM, 220 Process.PROC_TAB_TERM, 221 Process.PROC_TAB_TERM, 222 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime 223 }; 224 225 private final String[] mProcWakelocksName = new String[3]; 226 private final long[] mProcWakelocksData = new long[3]; 227 228 /* 229 * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added 230 * to mKernelWakelockStats. 231 */ 232 private final Map<String, KernelWakelockStats> mProcWakelockFileStats = 233 new HashMap<String, KernelWakelockStats>(); 234 235 private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>(); 236 237 // For debugging 238 public BatteryStatsImpl() { 239 mFile = null; 240 } 241 242 public static interface Unpluggable { 243 void unplug(long batteryUptime, long batteryRealtime); 244 void plug(long batteryUptime, long batteryRealtime); 245 } 246 247 /** 248 * State for keeping track of counting information. 249 */ 250 public static class Counter extends BatteryStats.Counter implements Unpluggable { 251 final AtomicInteger mCount = new AtomicInteger(); 252 final ArrayList<Unpluggable> mUnpluggables; 253 int mLoadedCount; 254 int mLastCount; 255 int mUnpluggedCount; 256 int mPluggedCount; 257 258 Counter(ArrayList<Unpluggable> unpluggables, Parcel in) { 259 mUnpluggables = unpluggables; 260 mPluggedCount = in.readInt(); 261 mCount.set(mPluggedCount); 262 mLoadedCount = in.readInt(); 263 mLastCount = in.readInt(); 264 mUnpluggedCount = in.readInt(); 265 unpluggables.add(this); 266 } 267 268 Counter(ArrayList<Unpluggable> unpluggables) { 269 mUnpluggables = unpluggables; 270 unpluggables.add(this); 271 } 272 273 public void writeToParcel(Parcel out) { 274 out.writeInt(mCount.get()); 275 out.writeInt(mLoadedCount); 276 out.writeInt(mLastCount); 277 out.writeInt(mUnpluggedCount); 278 } 279 280 public void unplug(long batteryUptime, long batteryRealtime) { 281 mUnpluggedCount = mPluggedCount; 282 mCount.set(mPluggedCount); 283 } 284 285 public void plug(long batteryUptime, long batteryRealtime) { 286 mPluggedCount = mCount.get(); 287 } 288 289 /** 290 * Writes a possibly null Counter to a Parcel. 291 * 292 * @param out the Parcel to be written to. 293 * @param counter a Counter, or null. 294 */ 295 public static void writeCounterToParcel(Parcel out, Counter counter) { 296 if (counter == null) { 297 out.writeInt(0); // indicates null 298 return; 299 } 300 out.writeInt(1); // indicates non-null 301 302 counter.writeToParcel(out); 303 } 304 305 @Override 306 public int getCountLocked(int which) { 307 int val; 308 if (which == STATS_LAST) { 309 val = mLastCount; 310 } else { 311 val = mCount.get(); 312 if (which == STATS_SINCE_UNPLUGGED) { 313 val -= mUnpluggedCount; 314 } else if (which != STATS_SINCE_CHARGED) { 315 val -= mLoadedCount; 316 } 317 } 318 319 return val; 320 } 321 322 public void logState(Printer pw, String prefix) { 323 pw.println(prefix + "mCount=" + mCount.get() 324 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 325 + " mUnpluggedCount=" + mUnpluggedCount 326 + " mPluggedCount=" + mPluggedCount); 327 } 328 329 void stepAtomic() { 330 mCount.incrementAndGet(); 331 } 332 333 /** 334 * Clear state of this counter. 335 */ 336 void reset(boolean detachIfReset) { 337 mCount.set(0); 338 mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0; 339 if (detachIfReset) { 340 detach(); 341 } 342 } 343 344 void detach() { 345 mUnpluggables.remove(this); 346 } 347 348 void writeSummaryFromParcelLocked(Parcel out) { 349 int count = mCount.get(); 350 out.writeInt(count); 351 out.writeInt(count - mLoadedCount); 352 } 353 354 void readSummaryFromParcelLocked(Parcel in) { 355 mLoadedCount = in.readInt(); 356 mCount.set(mLoadedCount); 357 mLastCount = in.readInt(); 358 mUnpluggedCount = mPluggedCount = mLoadedCount; 359 } 360 } 361 362 public static class SamplingCounter extends Counter { 363 364 SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) { 365 super(unpluggables, in); 366 } 367 368 SamplingCounter(ArrayList<Unpluggable> unpluggables) { 369 super(unpluggables); 370 } 371 372 public void addCountAtomic(long count) { 373 mCount.addAndGet((int)count); 374 } 375 } 376 377 /** 378 * State for keeping track of timing information. 379 */ 380 public static abstract class Timer extends BatteryStats.Timer implements Unpluggable { 381 final int mType; 382 final ArrayList<Unpluggable> mUnpluggables; 383 384 int mCount; 385 int mLoadedCount; 386 int mLastCount; 387 int mUnpluggedCount; 388 389 // Times are in microseconds for better accuracy when dividing by the 390 // lock count, and are in "battery realtime" units. 391 392 /** 393 * The total time we have accumulated since the start of the original 394 * boot, to the last time something interesting happened in the 395 * current run. 396 */ 397 long mTotalTime; 398 399 /** 400 * The total time we loaded for the previous runs. Subtract this from 401 * mTotalTime to find the time for the current run of the system. 402 */ 403 long mLoadedTime; 404 405 /** 406 * The run time of the last run of the system, as loaded from the 407 * saved data. 408 */ 409 long mLastTime; 410 411 /** 412 * The value of mTotalTime when unplug() was last called. Subtract 413 * this from mTotalTime to find the time since the last unplug from 414 * power. 415 */ 416 long mUnpluggedTime; 417 418 /** 419 * Constructs from a parcel. 420 * @param type 421 * @param unpluggables 422 * @param powerType 423 * @param in 424 */ 425 Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) { 426 mType = type; 427 mUnpluggables = unpluggables; 428 429 mCount = in.readInt(); 430 mLoadedCount = in.readInt(); 431 mLastCount = in.readInt(); 432 mUnpluggedCount = in.readInt(); 433 mTotalTime = in.readLong(); 434 mLoadedTime = in.readLong(); 435 mLastTime = in.readLong(); 436 mUnpluggedTime = in.readLong(); 437 unpluggables.add(this); 438 } 439 440 Timer(int type, ArrayList<Unpluggable> unpluggables) { 441 mType = type; 442 mUnpluggables = unpluggables; 443 unpluggables.add(this); 444 } 445 446 protected abstract long computeRunTimeLocked(long curBatteryRealtime); 447 448 protected abstract int computeCurrentCountLocked(); 449 450 /** 451 * Clear state of this timer. Returns true if the timer is inactive 452 * so can be completely dropped. 453 */ 454 boolean reset(boolean detachIfReset) { 455 mTotalTime = mLoadedTime = mLastTime = 0; 456 mCount = mLoadedCount = mLastCount = 0; 457 if (detachIfReset) { 458 detach(); 459 } 460 return true; 461 } 462 463 void detach() { 464 mUnpluggables.remove(this); 465 } 466 467 public void writeToParcel(Parcel out, long batteryRealtime) { 468 out.writeInt(mCount); 469 out.writeInt(mLoadedCount); 470 out.writeInt(mLastCount); 471 out.writeInt(mUnpluggedCount); 472 out.writeLong(computeRunTimeLocked(batteryRealtime)); 473 out.writeLong(mLoadedTime); 474 out.writeLong(mLastTime); 475 out.writeLong(mUnpluggedTime); 476 } 477 478 public void unplug(long batteryUptime, long batteryRealtime) { 479 if (DEBUG && mType < 0) { 480 Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime 481 + " old mUnpluggedTime=" + mUnpluggedTime 482 + " old mUnpluggedCount=" + mUnpluggedCount); 483 } 484 mUnpluggedTime = computeRunTimeLocked(batteryRealtime); 485 mUnpluggedCount = mCount; 486 if (DEBUG && mType < 0) { 487 Log.v(TAG, "unplug #" + mType 488 + ": new mUnpluggedTime=" + mUnpluggedTime 489 + " new mUnpluggedCount=" + mUnpluggedCount); 490 } 491 } 492 493 public void plug(long batteryUptime, long batteryRealtime) { 494 if (DEBUG && mType < 0) { 495 Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime 496 + " old mTotalTime=" + mTotalTime); 497 } 498 mTotalTime = computeRunTimeLocked(batteryRealtime); 499 mCount = computeCurrentCountLocked(); 500 if (DEBUG && mType < 0) { 501 Log.v(TAG, "plug #" + mType 502 + ": new mTotalTime=" + mTotalTime); 503 } 504 } 505 506 /** 507 * Writes a possibly null Timer to a Parcel. 508 * 509 * @param out the Parcel to be written to. 510 * @param timer a Timer, or null. 511 */ 512 public static void writeTimerToParcel(Parcel out, Timer timer, 513 long batteryRealtime) { 514 if (timer == null) { 515 out.writeInt(0); // indicates null 516 return; 517 } 518 out.writeInt(1); // indicates non-null 519 520 timer.writeToParcel(out, batteryRealtime); 521 } 522 523 @Override 524 public long getTotalTimeLocked(long batteryRealtime, int which) { 525 long val; 526 if (which == STATS_LAST) { 527 val = mLastTime; 528 } else { 529 val = computeRunTimeLocked(batteryRealtime); 530 if (which == STATS_SINCE_UNPLUGGED) { 531 val -= mUnpluggedTime; 532 } else if (which != STATS_SINCE_CHARGED) { 533 val -= mLoadedTime; 534 } 535 } 536 537 return val; 538 } 539 540 @Override 541 public int getCountLocked(int which) { 542 int val; 543 if (which == STATS_LAST) { 544 val = mLastCount; 545 } else { 546 val = computeCurrentCountLocked(); 547 if (which == STATS_SINCE_UNPLUGGED) { 548 val -= mUnpluggedCount; 549 } else if (which != STATS_SINCE_CHARGED) { 550 val -= mLoadedCount; 551 } 552 } 553 554 return val; 555 } 556 557 public void logState(Printer pw, String prefix) { 558 pw.println(prefix + " mCount=" + mCount 559 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 560 + " mUnpluggedCount=" + mUnpluggedCount); 561 pw.println(prefix + "mTotalTime=" + mTotalTime 562 + " mLoadedTime=" + mLoadedTime); 563 pw.println(prefix + "mLastTime=" + mLastTime 564 + " mUnpluggedTime=" + mUnpluggedTime); 565 } 566 567 568 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 569 long runTime = computeRunTimeLocked(batteryRealtime); 570 // Divide by 1000 for backwards compatibility 571 out.writeLong((runTime + 500) / 1000); 572 out.writeLong(((runTime - mLoadedTime) + 500) / 1000); 573 out.writeInt(mCount); 574 out.writeInt(mCount - mLoadedCount); 575 } 576 577 void readSummaryFromParcelLocked(Parcel in) { 578 // Multiply by 1000 for backwards compatibility 579 mTotalTime = mLoadedTime = in.readLong() * 1000; 580 mLastTime = in.readLong() * 1000; 581 mUnpluggedTime = mTotalTime; 582 mCount = mLoadedCount = in.readInt(); 583 mLastCount = in.readInt(); 584 mUnpluggedCount = mCount; 585 } 586 } 587 588 public static final class SamplingTimer extends Timer { 589 590 /** 591 * The most recent reported count from /proc/wakelocks. 592 */ 593 int mCurrentReportedCount; 594 595 /** 596 * The reported count from /proc/wakelocks when unplug() was last 597 * called. 598 */ 599 int mUnpluggedReportedCount; 600 601 /** 602 * The most recent reported total_time from /proc/wakelocks. 603 */ 604 long mCurrentReportedTotalTime; 605 606 607 /** 608 * The reported total_time from /proc/wakelocks when unplug() was last 609 * called. 610 */ 611 long mUnpluggedReportedTotalTime; 612 613 /** 614 * Whether we are currently in a discharge cycle. 615 */ 616 boolean mInDischarge; 617 618 /** 619 * Whether we are currently recording reported values. 620 */ 621 boolean mTrackingReportedValues; 622 623 /* 624 * A sequnce counter, incremented once for each update of the stats. 625 */ 626 int mUpdateVersion; 627 628 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) { 629 super(0, unpluggables, in); 630 mCurrentReportedCount = in.readInt(); 631 mUnpluggedReportedCount = in.readInt(); 632 mCurrentReportedTotalTime = in.readLong(); 633 mUnpluggedReportedTotalTime = in.readLong(); 634 mTrackingReportedValues = in.readInt() == 1; 635 mInDischarge = inDischarge; 636 } 637 638 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, 639 boolean trackReportedValues) { 640 super(0, unpluggables); 641 mTrackingReportedValues = trackReportedValues; 642 mInDischarge = inDischarge; 643 } 644 645 public void setStale() { 646 mTrackingReportedValues = false; 647 mUnpluggedReportedTotalTime = 0; 648 mUnpluggedReportedCount = 0; 649 } 650 651 public void setUpdateVersion(int version) { 652 mUpdateVersion = version; 653 } 654 655 public int getUpdateVersion() { 656 return mUpdateVersion; 657 } 658 659 public void updateCurrentReportedCount(int count) { 660 if (mInDischarge && mUnpluggedReportedCount == 0) { 661 // Updating the reported value for the first time. 662 mUnpluggedReportedCount = count; 663 // If we are receiving an update update mTrackingReportedValues; 664 mTrackingReportedValues = true; 665 } 666 mCurrentReportedCount = count; 667 } 668 669 public void updateCurrentReportedTotalTime(long totalTime) { 670 if (mInDischarge && mUnpluggedReportedTotalTime == 0) { 671 // Updating the reported value for the first time. 672 mUnpluggedReportedTotalTime = totalTime; 673 // If we are receiving an update update mTrackingReportedValues; 674 mTrackingReportedValues = true; 675 } 676 mCurrentReportedTotalTime = totalTime; 677 } 678 679 public void unplug(long batteryUptime, long batteryRealtime) { 680 super.unplug(batteryUptime, batteryRealtime); 681 if (mTrackingReportedValues) { 682 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime; 683 mUnpluggedReportedCount = mCurrentReportedCount; 684 } 685 mInDischarge = true; 686 } 687 688 public void plug(long batteryUptime, long batteryRealtime) { 689 super.plug(batteryUptime, batteryRealtime); 690 mInDischarge = false; 691 } 692 693 public void logState(Printer pw, String prefix) { 694 super.logState(pw, prefix); 695 pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount 696 + " mUnpluggedReportedCount=" + mUnpluggedReportedCount 697 + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime 698 + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime); 699 } 700 701 protected long computeRunTimeLocked(long curBatteryRealtime) { 702 return mTotalTime + (mInDischarge && mTrackingReportedValues 703 ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0); 704 } 705 706 protected int computeCurrentCountLocked() { 707 return mCount + (mInDischarge && mTrackingReportedValues 708 ? mCurrentReportedCount - mUnpluggedReportedCount : 0); 709 } 710 711 public void writeToParcel(Parcel out, long batteryRealtime) { 712 super.writeToParcel(out, batteryRealtime); 713 out.writeInt(mCurrentReportedCount); 714 out.writeInt(mUnpluggedReportedCount); 715 out.writeLong(mCurrentReportedTotalTime); 716 out.writeLong(mUnpluggedReportedTotalTime); 717 out.writeInt(mTrackingReportedValues ? 1 : 0); 718 } 719 720 boolean reset(boolean detachIfReset) { 721 super.reset(detachIfReset); 722 setStale(); 723 return true; 724 } 725 726 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 727 super.writeSummaryFromParcelLocked(out, batteryRealtime); 728 out.writeLong(mCurrentReportedTotalTime); 729 out.writeInt(mCurrentReportedCount); 730 out.writeInt(mTrackingReportedValues ? 1 : 0); 731 } 732 733 void readSummaryFromParcelLocked(Parcel in) { 734 super.readSummaryFromParcelLocked(in); 735 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong(); 736 mUnpluggedReportedCount = mCurrentReportedCount = in.readInt(); 737 mTrackingReportedValues = in.readInt() == 1; 738 } 739 } 740 741 /** 742 * State for keeping track of timing information. 743 */ 744 public static final class StopwatchTimer extends Timer { 745 final ArrayList<StopwatchTimer> mTimerPool; 746 int mNesting; 747 748 /** 749 * The last time at which we updated the timer. If mNesting is > 0, 750 * subtract this from the current battery time to find the amount of 751 * time we have been running since we last computed an update. 752 */ 753 long mUpdateTime; 754 755 /** 756 * The total time at which the timer was acquired, to determine if 757 * was actually held for an interesting duration. 758 */ 759 long mAcquireTime; 760 761 long mTimeout; 762 763 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, 764 ArrayList<Unpluggable> unpluggables, Parcel in) { 765 super(type, unpluggables, in); 766 mTimerPool = timerPool; 767 mUpdateTime = in.readLong(); 768 } 769 770 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, 771 ArrayList<Unpluggable> unpluggables) { 772 super(type, unpluggables); 773 mTimerPool = timerPool; 774 } 775 776 void setTimeout(long timeout) { 777 mTimeout = timeout; 778 } 779 780 public void writeToParcel(Parcel out, long batteryRealtime) { 781 super.writeToParcel(out, batteryRealtime); 782 out.writeLong(mUpdateTime); 783 } 784 785 public void plug(long batteryUptime, long batteryRealtime) { 786 if (mNesting > 0) { 787 if (DEBUG && mType < 0) { 788 Log.v(TAG, "old mUpdateTime=" + mUpdateTime); 789 } 790 super.plug(batteryUptime, batteryRealtime); 791 mUpdateTime = batteryRealtime; 792 if (DEBUG && mType < 0) { 793 Log.v(TAG, "new mUpdateTime=" + mUpdateTime); 794 } 795 } 796 } 797 798 public void logState(Printer pw, String prefix) { 799 super.logState(pw, prefix); 800 pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime 801 + " mAcquireTime=" + mAcquireTime); 802 } 803 804 void startRunningLocked(BatteryStatsImpl stats) { 805 if (mNesting++ == 0) { 806 mUpdateTime = stats.getBatteryRealtimeLocked( 807 SystemClock.elapsedRealtime() * 1000); 808 if (mTimerPool != null) { 809 // Accumulate time to all currently active timers before adding 810 // this new one to the pool. 811 refreshTimersLocked(stats, mTimerPool); 812 // Add this timer to the active pool 813 mTimerPool.add(this); 814 } 815 // Increment the count 816 mCount++; 817 mAcquireTime = mTotalTime; 818 if (DEBUG && mType < 0) { 819 Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime 820 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 821 + " mAcquireTime=" + mAcquireTime); 822 } 823 } 824 } 825 826 boolean isRunningLocked() { 827 return mNesting > 0; 828 } 829 830 void stopRunningLocked(BatteryStatsImpl stats) { 831 // Ignore attempt to stop a timer that isn't running 832 if (mNesting == 0) { 833 return; 834 } 835 if (--mNesting == 0) { 836 if (mTimerPool != null) { 837 // Accumulate time to all active counters, scaled by the total 838 // active in the pool, before taking this one out of the pool. 839 refreshTimersLocked(stats, mTimerPool); 840 // Remove this timer from the active pool 841 mTimerPool.remove(this); 842 } else { 843 final long realtime = SystemClock.elapsedRealtime() * 1000; 844 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 845 mNesting = 1; 846 mTotalTime = computeRunTimeLocked(batteryRealtime); 847 mNesting = 0; 848 } 849 850 if (DEBUG && mType < 0) { 851 Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime 852 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 853 + " mAcquireTime=" + mAcquireTime); 854 } 855 856 if (mTotalTime == mAcquireTime) { 857 // If there was no change in the time, then discard this 858 // count. A somewhat cheezy strategy, but hey. 859 mCount--; 860 } 861 } 862 } 863 864 // Update the total time for all other running Timers with the same type as this Timer 865 // due to a change in timer count 866 private static void refreshTimersLocked(final BatteryStatsImpl stats, 867 final ArrayList<StopwatchTimer> pool) { 868 final long realtime = SystemClock.elapsedRealtime() * 1000; 869 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 870 final int N = pool.size(); 871 for (int i=N-1; i>= 0; i--) { 872 final StopwatchTimer t = pool.get(i); 873 long heldTime = batteryRealtime - t.mUpdateTime; 874 if (heldTime > 0) { 875 t.mTotalTime += heldTime / N; 876 } 877 t.mUpdateTime = batteryRealtime; 878 } 879 } 880 881 @Override 882 protected long computeRunTimeLocked(long curBatteryRealtime) { 883 if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) { 884 curBatteryRealtime = mUpdateTime + mTimeout; 885 } 886 return mTotalTime + (mNesting > 0 887 ? (curBatteryRealtime - mUpdateTime) 888 / (mTimerPool != null ? mTimerPool.size() : 1) 889 : 0); 890 } 891 892 @Override 893 protected int computeCurrentCountLocked() { 894 return mCount; 895 } 896 897 boolean reset(boolean detachIfReset) { 898 boolean canDetach = mNesting <= 0; 899 super.reset(canDetach && detachIfReset); 900 return canDetach; 901 } 902 903 void detach() { 904 super.detach(); 905 if (mTimerPool != null) { 906 mTimerPool.remove(this); 907 } 908 } 909 910 void readSummaryFromParcelLocked(Parcel in) { 911 super.readSummaryFromParcelLocked(in); 912 mNesting = 0; 913 } 914 } 915 916 private final Map<String, KernelWakelockStats> readKernelWakelockStats() { 917 918 byte[] buffer = new byte[4096]; 919 int len; 920 921 try { 922 FileInputStream is = new FileInputStream("/proc/wakelocks"); 923 len = is.read(buffer); 924 is.close(); 925 926 if (len > 0) { 927 int i; 928 for (i=0; i<len; i++) { 929 if (buffer[i] == '\0') { 930 len = i; 931 break; 932 } 933 } 934 } 935 } catch (java.io.FileNotFoundException e) { 936 return null; 937 } catch (java.io.IOException e) { 938 return null; 939 } 940 941 return parseProcWakelocks(buffer, len); 942 } 943 944 private final Map<String, KernelWakelockStats> parseProcWakelocks( 945 byte[] wlBuffer, int len) { 946 String name; 947 int count; 948 long totalTime; 949 int startIndex, endIndex; 950 int numUpdatedWlNames = 0; 951 952 // Advance past the first line. 953 int i; 954 for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++); 955 startIndex = endIndex = i + 1; 956 957 synchronized(this) { 958 Map<String, KernelWakelockStats> m = mProcWakelockFileStats; 959 960 sKernelWakelockUpdateVersion++; 961 while (endIndex < len) { 962 for (endIndex=startIndex; 963 endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0'; 964 endIndex++); 965 // Don't go over the end of the buffer 966 if (endIndex < len) { 967 endIndex++; // endIndex is an exclusive upper bound. 968 } 969 970 String[] nameStringArray = mProcWakelocksName; 971 long[] wlData = mProcWakelocksData; 972 // Stomp out any bad characters since this is from a circular buffer 973 // A corruption is seen sometimes that results in the vm crashing 974 // This should prevent crashes and the line will probably fail to parse 975 for (int j = startIndex; j < endIndex; j++) { 976 if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?'; 977 } 978 boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex, 979 PROC_WAKELOCKS_FORMAT, nameStringArray, wlData, null); 980 981 name = nameStringArray[0]; 982 count = (int) wlData[1]; 983 // convert nanoseconds to microseconds with rounding. 984 totalTime = (wlData[2] + 500) / 1000; 985 986 if (parsed && name.length() > 0) { 987 if (!m.containsKey(name)) { 988 m.put(name, new KernelWakelockStats(count, totalTime, 989 sKernelWakelockUpdateVersion)); 990 numUpdatedWlNames++; 991 } else { 992 KernelWakelockStats kwlStats = m.get(name); 993 if (kwlStats.mVersion == sKernelWakelockUpdateVersion) { 994 kwlStats.mCount += count; 995 kwlStats.mTotalTime += totalTime; 996 } else { 997 kwlStats.mCount = count; 998 kwlStats.mTotalTime = totalTime; 999 kwlStats.mVersion = sKernelWakelockUpdateVersion; 1000 numUpdatedWlNames++; 1001 } 1002 } 1003 } 1004 startIndex = endIndex; 1005 } 1006 1007 if (m.size() != numUpdatedWlNames) { 1008 // Don't report old data. 1009 Iterator<KernelWakelockStats> itr = m.values().iterator(); 1010 while (itr.hasNext()) { 1011 if (itr.next().mVersion != sKernelWakelockUpdateVersion) { 1012 itr.remove(); 1013 } 1014 } 1015 } 1016 return m; 1017 } 1018 } 1019 1020 private class KernelWakelockStats { 1021 public int mCount; 1022 public long mTotalTime; 1023 public int mVersion; 1024 1025 KernelWakelockStats(int count, long totalTime, int version) { 1026 mCount = count; 1027 mTotalTime = totalTime; 1028 mVersion = version; 1029 } 1030 } 1031 1032 /* 1033 * Get the KernelWakelockTimer associated with name, and create a new one if one 1034 * doesn't already exist. 1035 */ 1036 public SamplingTimer getKernelWakelockTimerLocked(String name) { 1037 SamplingTimer kwlt = mKernelWakelockStats.get(name); 1038 if (kwlt == null) { 1039 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 1040 true /* track reported values */); 1041 mKernelWakelockStats.put(name, kwlt); 1042 } 1043 return kwlt; 1044 } 1045 1046 private void doDataPlug(long[] dataTransfer, long currentBytes) { 1047 dataTransfer[STATS_LAST] = dataTransfer[STATS_SINCE_UNPLUGGED]; 1048 dataTransfer[STATS_SINCE_UNPLUGGED] = -1; 1049 } 1050 1051 private void doDataUnplug(long[] dataTransfer, long currentBytes) { 1052 dataTransfer[STATS_SINCE_UNPLUGGED] = currentBytes; 1053 } 1054 1055 /** 1056 * Radio uptime in microseconds when transferring data. This value is very approximate. 1057 * @return 1058 */ 1059 private long getCurrentRadioDataUptime() { 1060 try { 1061 File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms"); 1062 if (!awakeTimeFile.exists()) return 0; 1063 BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile)); 1064 String line = br.readLine(); 1065 br.close(); 1066 return Long.parseLong(line) * 1000; 1067 } catch (NumberFormatException nfe) { 1068 // Nothing 1069 } catch (IOException ioe) { 1070 // Nothing 1071 } 1072 return 0; 1073 } 1074 1075 /** 1076 * @deprecated use getRadioDataUptime 1077 */ 1078 public long getRadioDataUptimeMs() { 1079 return getRadioDataUptime() / 1000; 1080 } 1081 1082 /** 1083 * Returns the duration that the cell radio was up for data transfers. 1084 */ 1085 public long getRadioDataUptime() { 1086 if (mRadioDataStart == -1) { 1087 return mRadioDataUptime; 1088 } else { 1089 return getCurrentRadioDataUptime() - mRadioDataStart; 1090 } 1091 } 1092 1093 private int getCurrentBluetoothPingCount() { 1094 if (mBtHeadset != null) { 1095 return mBtHeadset.getBatteryUsageHint(); 1096 } 1097 return -1; 1098 } 1099 1100 public int getBluetoothPingCount() { 1101 if (mBluetoothPingStart == -1) { 1102 return mBluetoothPingCount; 1103 } else if (mBtHeadset != null) { 1104 return getCurrentBluetoothPingCount() - mBluetoothPingStart; 1105 } 1106 return 0; 1107 } 1108 1109 public void setBtHeadset(BluetoothHeadset headset) { 1110 if (headset != null && mBtHeadset == null && isOnBattery() && mBluetoothPingStart == -1) { 1111 mBluetoothPingStart = getCurrentBluetoothPingCount(); 1112 } 1113 mBtHeadset = headset; 1114 } 1115 1116 void addHistoryRecordLocked(long curTime) { 1117 if (!mHaveBatteryLevel || !mRecordingHistory) { 1118 return; 1119 } 1120 if (mNumHistoryItems >= MAX_HISTORY_ITEMS) { 1121 // Once we've reached the maximum number of items, we only 1122 // record changes to the battery level. 1123 if (mHistoryEnd != null && mHistoryEnd.batteryLevel 1124 == mHistoryCur.batteryLevel) { 1125 return; 1126 } 1127 } 1128 addHistoryRecordLocked(curTime, HistoryItem.CMD_UPDATE); 1129 } 1130 1131 void addHistoryRecordLocked(long curTime, byte cmd) { 1132 HistoryItem rec = mHistoryCache; 1133 if (rec != null) { 1134 mHistoryCache = rec.next; 1135 } else { 1136 rec = new HistoryItem(); 1137 } 1138 rec.setTo(mHistoryBaseTime + curTime, cmd, mHistoryCur); 1139 1140 addHistoryRecordLocked(rec); 1141 } 1142 1143 void addHistoryRecordLocked(HistoryItem rec) { 1144 mNumHistoryItems++; 1145 rec.next = null; 1146 if (mHistoryEnd != null) { 1147 mHistoryEnd.next = rec; 1148 mHistoryEnd = rec; 1149 } else { 1150 mHistory = mHistoryEnd = rec; 1151 } 1152 } 1153 1154 void clearHistoryLocked() { 1155 if (mHistory != null) { 1156 mHistoryEnd.next = mHistoryCache; 1157 mHistoryCache = mHistory; 1158 mHistory = mHistoryEnd = null; 1159 } 1160 mNumHistoryItems = 0; 1161 mHistoryBaseTime = 0; 1162 } 1163 1164 public void doUnplugLocked(long batteryUptime, long batteryRealtime) { 1165 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 1166 Uid u = mUidStats.valueAt(iu); 1167 u.mStartedTcpBytesReceived = TrafficStats.getUidRxBytes(u.mUid); 1168 u.mStartedTcpBytesSent = TrafficStats.getUidTxBytes(u.mUid); 1169 u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived; 1170 u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent; 1171 } 1172 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 1173 mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime); 1174 } 1175 // Track total mobile data 1176 doDataUnplug(mMobileDataRx, TrafficStats.getMobileRxBytes()); 1177 doDataUnplug(mMobileDataTx, TrafficStats.getMobileTxBytes()); 1178 doDataUnplug(mTotalDataRx, TrafficStats.getTotalRxBytes()); 1179 doDataUnplug(mTotalDataTx, TrafficStats.getTotalTxBytes()); 1180 // Track radio awake time 1181 mRadioDataStart = getCurrentRadioDataUptime(); 1182 mRadioDataUptime = 0; 1183 // Track bt headset ping count 1184 mBluetoothPingStart = getCurrentBluetoothPingCount(); 1185 mBluetoothPingCount = 0; 1186 } 1187 1188 public void doPlugLocked(long batteryUptime, long batteryRealtime) { 1189 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 1190 Uid u = mUidStats.valueAt(iu); 1191 if (u.mStartedTcpBytesReceived >= 0) { 1192 u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived(); 1193 u.mStartedTcpBytesReceived = -1; 1194 } 1195 if (u.mStartedTcpBytesSent >= 0) { 1196 u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent(); 1197 u.mStartedTcpBytesSent = -1; 1198 } 1199 } 1200 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 1201 mUnpluggables.get(i).plug(batteryUptime, batteryRealtime); 1202 } 1203 doDataPlug(mMobileDataRx, TrafficStats.getMobileRxBytes()); 1204 doDataPlug(mMobileDataTx, TrafficStats.getMobileTxBytes()); 1205 doDataPlug(mTotalDataRx, TrafficStats.getTotalRxBytes()); 1206 doDataPlug(mTotalDataTx, TrafficStats.getTotalTxBytes()); 1207 // Track radio awake time 1208 mRadioDataUptime = getRadioDataUptime(); 1209 mRadioDataStart = -1; 1210 1211 // Track bt headset ping count 1212 mBluetoothPingCount = getBluetoothPingCount(); 1213 mBluetoothPingStart = -1; 1214 } 1215 1216 int mGpsNesting; 1217 1218 public void noteStartGpsLocked(int uid) { 1219 if (mGpsNesting == 0) { 1220 mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG; 1221 if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: " 1222 + Integer.toHexString(mHistoryCur.states)); 1223 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1224 } 1225 mGpsNesting++; 1226 getUidStatsLocked(uid).noteStartGps(); 1227 } 1228 1229 public void noteStopGpsLocked(int uid) { 1230 mGpsNesting--; 1231 if (mGpsNesting == 0) { 1232 mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG; 1233 if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: " 1234 + Integer.toHexString(mHistoryCur.states)); 1235 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1236 } 1237 getUidStatsLocked(uid).noteStopGps(); 1238 } 1239 1240 public void noteScreenOnLocked() { 1241 if (!mScreenOn) { 1242 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG; 1243 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: " 1244 + Integer.toHexString(mHistoryCur.states)); 1245 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1246 mGpsNesting++; 1247 mScreenOn = true; 1248 mScreenOnTimer.startRunningLocked(this); 1249 if (mScreenBrightnessBin >= 0) { 1250 mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this); 1251 } 1252 } 1253 } 1254 1255 public void noteScreenOffLocked() { 1256 if (mScreenOn) { 1257 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG; 1258 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: " 1259 + Integer.toHexString(mHistoryCur.states)); 1260 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1261 mScreenOn = false; 1262 mScreenOnTimer.stopRunningLocked(this); 1263 if (mScreenBrightnessBin >= 0) { 1264 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this); 1265 } 1266 } 1267 } 1268 1269 public void noteScreenBrightnessLocked(int brightness) { 1270 // Bin the brightness. 1271 int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS); 1272 if (bin < 0) bin = 0; 1273 else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1; 1274 if (mScreenBrightnessBin != bin) { 1275 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK) 1276 | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT); 1277 if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: " 1278 + Integer.toHexString(mHistoryCur.states)); 1279 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1280 if (mScreenOn) { 1281 if (mScreenBrightnessBin >= 0) { 1282 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this); 1283 } 1284 mScreenBrightnessTimer[bin].startRunningLocked(this); 1285 } 1286 mScreenBrightnessBin = bin; 1287 } 1288 } 1289 1290 public void noteInputEventAtomic() { 1291 mInputEventCounter.stepAtomic(); 1292 } 1293 1294 public void noteUserActivityLocked(int uid, int event) { 1295 getUidStatsLocked(uid).noteUserActivityLocked(event); 1296 } 1297 1298 public void notePhoneOnLocked() { 1299 if (!mPhoneOn) { 1300 mHistoryCur.states |= HistoryItem.STATE_PHONE_ON_FLAG; 1301 if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: " 1302 + Integer.toHexString(mHistoryCur.states)); 1303 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1304 mPhoneOn = true; 1305 mPhoneOnTimer.startRunningLocked(this); 1306 } 1307 } 1308 1309 public void notePhoneOffLocked() { 1310 if (mPhoneOn) { 1311 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_ON_FLAG; 1312 if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: " 1313 + Integer.toHexString(mHistoryCur.states)); 1314 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1315 mPhoneOn = false; 1316 mPhoneOnTimer.stopRunningLocked(this); 1317 } 1318 } 1319 1320 /** 1321 * Telephony stack updates the phone state. 1322 * @param state phone state from ServiceState.getState() 1323 */ 1324 public void notePhoneStateLocked(int state) { 1325 int bin = mPhoneSignalStrengthBin; 1326 boolean isAirplaneMode = state == ServiceState.STATE_POWER_OFF; 1327 // Stop all timers 1328 if (isAirplaneMode || state == ServiceState.STATE_OUT_OF_SERVICE) { 1329 for (int i = 0; i < NUM_SIGNAL_STRENGTH_BINS; i++) { 1330 while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) { 1331 mPhoneSignalStrengthsTimer[i].stopRunningLocked(this); 1332 } 1333 } 1334 } 1335 // Stop Signal Scanning timer, in case we're going into service 1336 if (mPhoneSignalScanningTimer.isRunningLocked()) { 1337 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG; 1338 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: " 1339 + Integer.toHexString(mHistoryCur.states)); 1340 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1341 mPhoneSignalScanningTimer.stopRunningLocked(this); 1342 } 1343 1344 // If we're back in service or continuing in service, restart the old timer. 1345 if (state == ServiceState.STATE_IN_SERVICE) { 1346 if (bin == -1) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1347 if (!mPhoneSignalStrengthsTimer[bin].isRunningLocked()) { 1348 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this); 1349 } 1350 } else if (state == ServiceState.STATE_OUT_OF_SERVICE) { 1351 mPhoneSignalStrengthBin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1352 if (!mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].isRunningLocked()) { 1353 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].startRunningLocked(this); 1354 } 1355 if (!mPhoneSignalScanningTimer.isRunningLocked()) { 1356 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG; 1357 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: " 1358 + Integer.toHexString(mHistoryCur.states)); 1359 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1360 mPhoneSignalScanningTimer.startRunningLocked(this); 1361 } 1362 } 1363 1364 if (mPhoneServiceState != state) { 1365 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK) 1366 | (state << HistoryItem.STATE_PHONE_STATE_SHIFT); 1367 if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + bin + " to: " 1368 + Integer.toHexString(mHistoryCur.states)); 1369 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1370 mPhoneServiceState = state; 1371 } 1372 } 1373 1374 public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) { 1375 // Bin the strength. 1376 int bin; 1377 if (mPhoneServiceState == ServiceState.STATE_POWER_OFF 1378 || mPhoneServiceState == ServiceState.STATE_OUT_OF_SERVICE) { 1379 // Ignore any signal strength changes when radio was turned off or out of service. 1380 return; 1381 } 1382 if (!signalStrength.isGsm()) { 1383 int dBm = signalStrength.getCdmaDbm(); 1384 if (dBm >= -75) bin = SIGNAL_STRENGTH_GREAT; 1385 else if (dBm >= -85) bin = SIGNAL_STRENGTH_GOOD; 1386 else if (dBm >= -95) bin = SIGNAL_STRENGTH_MODERATE; 1387 else if (dBm >= -100) bin = SIGNAL_STRENGTH_POOR; 1388 else bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1389 } else { 1390 int asu = signalStrength.getGsmSignalStrength(); 1391 if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1392 else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT; 1393 else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD; 1394 else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE; 1395 else bin = SIGNAL_STRENGTH_POOR; 1396 } 1397 if (mPhoneSignalStrengthBin != bin) { 1398 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_SIGNAL_STRENGTH_MASK) 1399 | (bin << HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT); 1400 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + bin + " to: " 1401 + Integer.toHexString(mHistoryCur.states)); 1402 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1403 if (mPhoneSignalStrengthBin >= 0) { 1404 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this); 1405 } 1406 mPhoneSignalStrengthBin = bin; 1407 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this); 1408 } 1409 } 1410 1411 public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) { 1412 int bin = DATA_CONNECTION_NONE; 1413 if (hasData) { 1414 switch (dataType) { 1415 case TelephonyManager.NETWORK_TYPE_EDGE: 1416 bin = DATA_CONNECTION_EDGE; 1417 break; 1418 case TelephonyManager.NETWORK_TYPE_GPRS: 1419 bin = DATA_CONNECTION_GPRS; 1420 break; 1421 case TelephonyManager.NETWORK_TYPE_UMTS: 1422 bin = DATA_CONNECTION_UMTS; 1423 break; 1424 case TelephonyManager.NETWORK_TYPE_CDMA: 1425 bin = DATA_CONNECTION_CDMA; 1426 break; 1427 case TelephonyManager.NETWORK_TYPE_EVDO_0: 1428 bin = DATA_CONNECTION_EVDO_0; 1429 break; 1430 case TelephonyManager.NETWORK_TYPE_EVDO_A: 1431 bin = DATA_CONNECTION_EVDO_A; 1432 break; 1433 case TelephonyManager.NETWORK_TYPE_1xRTT: 1434 bin = DATA_CONNECTION_1xRTT; 1435 break; 1436 case TelephonyManager.NETWORK_TYPE_HSDPA: 1437 bin = DATA_CONNECTION_HSDPA; 1438 break; 1439 case TelephonyManager.NETWORK_TYPE_HSUPA: 1440 bin = DATA_CONNECTION_HSUPA; 1441 break; 1442 case TelephonyManager.NETWORK_TYPE_HSPA: 1443 bin = DATA_CONNECTION_HSPA; 1444 break; 1445 case TelephonyManager.NETWORK_TYPE_IDEN: 1446 bin = DATA_CONNECTION_IDEN; 1447 break; 1448 case TelephonyManager.NETWORK_TYPE_EVDO_B: 1449 bin = DATA_CONNECTION_EVDO_B; 1450 break; 1451 default: 1452 bin = DATA_CONNECTION_OTHER; 1453 break; 1454 } 1455 } 1456 if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData); 1457 if (mPhoneDataConnectionType != bin) { 1458 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK) 1459 | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT); 1460 if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: " 1461 + Integer.toHexString(mHistoryCur.states)); 1462 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1463 if (mPhoneDataConnectionType >= 0) { 1464 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this); 1465 } 1466 mPhoneDataConnectionType = bin; 1467 mPhoneDataConnectionsTimer[bin].startRunningLocked(this); 1468 } 1469 } 1470 1471 public void noteWifiOnLocked(int uid) { 1472 if (!mWifiOn) { 1473 mHistoryCur.states |= HistoryItem.STATE_WIFI_ON_FLAG; 1474 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: " 1475 + Integer.toHexString(mHistoryCur.states)); 1476 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1477 mWifiOn = true; 1478 mWifiOnTimer.startRunningLocked(this); 1479 } 1480 if (mWifiOnUid != uid) { 1481 if (mWifiOnUid >= 0) { 1482 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked(); 1483 } 1484 mWifiOnUid = uid; 1485 getUidStatsLocked(uid).noteWifiTurnedOnLocked(); 1486 } 1487 } 1488 1489 public void noteWifiOffLocked(int uid) { 1490 if (mWifiOn) { 1491 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_ON_FLAG; 1492 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: " 1493 + Integer.toHexString(mHistoryCur.states)); 1494 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1495 mWifiOn = false; 1496 mWifiOnTimer.stopRunningLocked(this); 1497 } 1498 if (mWifiOnUid >= 0) { 1499 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked(); 1500 mWifiOnUid = -1; 1501 } 1502 } 1503 1504 public void noteAudioOnLocked(int uid) { 1505 if (!mAudioOn) { 1506 mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG; 1507 if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: " 1508 + Integer.toHexString(mHistoryCur.states)); 1509 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1510 mAudioOn = true; 1511 mAudioOnTimer.startRunningLocked(this); 1512 } 1513 getUidStatsLocked(uid).noteAudioTurnedOnLocked(); 1514 } 1515 1516 public void noteAudioOffLocked(int uid) { 1517 if (mAudioOn) { 1518 mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG; 1519 if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: " 1520 + Integer.toHexString(mHistoryCur.states)); 1521 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1522 mAudioOn = false; 1523 mAudioOnTimer.stopRunningLocked(this); 1524 } 1525 getUidStatsLocked(uid).noteAudioTurnedOffLocked(); 1526 } 1527 1528 public void noteVideoOnLocked(int uid) { 1529 if (!mVideoOn) { 1530 mHistoryCur.states |= HistoryItem.STATE_VIDEO_ON_FLAG; 1531 if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: " 1532 + Integer.toHexString(mHistoryCur.states)); 1533 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1534 mVideoOn = true; 1535 mVideoOnTimer.startRunningLocked(this); 1536 } 1537 getUidStatsLocked(uid).noteVideoTurnedOnLocked(); 1538 } 1539 1540 public void noteVideoOffLocked(int uid) { 1541 if (mVideoOn) { 1542 mHistoryCur.states &= ~HistoryItem.STATE_VIDEO_ON_FLAG; 1543 if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: " 1544 + Integer.toHexString(mHistoryCur.states)); 1545 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1546 mVideoOn = false; 1547 mVideoOnTimer.stopRunningLocked(this); 1548 } 1549 getUidStatsLocked(uid).noteVideoTurnedOffLocked(); 1550 } 1551 1552 public void noteWifiRunningLocked() { 1553 if (!mWifiRunning) { 1554 mHistoryCur.states |= HistoryItem.STATE_WIFI_RUNNING_FLAG; 1555 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: " 1556 + Integer.toHexString(mHistoryCur.states)); 1557 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1558 mWifiRunning = true; 1559 mWifiRunningTimer.startRunningLocked(this); 1560 } 1561 } 1562 1563 public void noteWifiStoppedLocked() { 1564 if (mWifiRunning) { 1565 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RUNNING_FLAG; 1566 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: " 1567 + Integer.toHexString(mHistoryCur.states)); 1568 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1569 mWifiRunning = false; 1570 mWifiRunningTimer.stopRunningLocked(this); 1571 } 1572 } 1573 1574 public void noteBluetoothOnLocked() { 1575 if (!mBluetoothOn) { 1576 mHistoryCur.states |= HistoryItem.STATE_BLUETOOTH_ON_FLAG; 1577 if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth on to: " 1578 + Integer.toHexString(mHistoryCur.states)); 1579 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1580 mBluetoothOn = true; 1581 mBluetoothOnTimer.startRunningLocked(this); 1582 } 1583 } 1584 1585 public void noteBluetoothOffLocked() { 1586 if (mBluetoothOn) { 1587 mHistoryCur.states &= ~HistoryItem.STATE_BLUETOOTH_ON_FLAG; 1588 if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth off to: " 1589 + Integer.toHexString(mHistoryCur.states)); 1590 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1591 mBluetoothOn = false; 1592 mBluetoothOnTimer.stopRunningLocked(this); 1593 } 1594 } 1595 1596 int mWifiFullLockNesting = 0; 1597 1598 public void noteFullWifiLockAcquiredLocked(int uid) { 1599 if (mWifiFullLockNesting == 0) { 1600 mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG; 1601 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: " 1602 + Integer.toHexString(mHistoryCur.states)); 1603 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1604 } 1605 mWifiFullLockNesting++; 1606 getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(); 1607 } 1608 1609 public void noteFullWifiLockReleasedLocked(int uid) { 1610 mWifiFullLockNesting--; 1611 if (mWifiFullLockNesting == 0) { 1612 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG; 1613 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: " 1614 + Integer.toHexString(mHistoryCur.states)); 1615 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1616 } 1617 getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(); 1618 } 1619 1620 int mWifiScanLockNesting = 0; 1621 1622 public void noteScanWifiLockAcquiredLocked(int uid) { 1623 if (mWifiScanLockNesting == 0) { 1624 mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG; 1625 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock on to: " 1626 + Integer.toHexString(mHistoryCur.states)); 1627 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1628 } 1629 mWifiScanLockNesting++; 1630 getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked(); 1631 } 1632 1633 public void noteScanWifiLockReleasedLocked(int uid) { 1634 mWifiScanLockNesting--; 1635 if (mWifiScanLockNesting == 0) { 1636 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG; 1637 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock off to: " 1638 + Integer.toHexString(mHistoryCur.states)); 1639 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1640 } 1641 getUidStatsLocked(uid).noteScanWifiLockReleasedLocked(); 1642 } 1643 1644 int mWifiMulticastNesting = 0; 1645 1646 public void noteWifiMulticastEnabledLocked(int uid) { 1647 if (mWifiMulticastNesting == 0) { 1648 mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG; 1649 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: " 1650 + Integer.toHexString(mHistoryCur.states)); 1651 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1652 } 1653 mWifiMulticastNesting++; 1654 getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(); 1655 } 1656 1657 public void noteWifiMulticastDisabledLocked(int uid) { 1658 mWifiMulticastNesting--; 1659 if (mWifiMulticastNesting == 0) { 1660 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG; 1661 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: " 1662 + Integer.toHexString(mHistoryCur.states)); 1663 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1664 } 1665 getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(); 1666 } 1667 1668 @Override public long getScreenOnTime(long batteryRealtime, int which) { 1669 return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which); 1670 } 1671 1672 @Override public long getScreenBrightnessTime(int brightnessBin, 1673 long batteryRealtime, int which) { 1674 return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked( 1675 batteryRealtime, which); 1676 } 1677 1678 @Override public int getInputEventCount(int which) { 1679 return mInputEventCounter.getCountLocked(which); 1680 } 1681 1682 @Override public long getPhoneOnTime(long batteryRealtime, int which) { 1683 return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which); 1684 } 1685 1686 @Override public long getPhoneSignalStrengthTime(int strengthBin, 1687 long batteryRealtime, int which) { 1688 return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked( 1689 batteryRealtime, which); 1690 } 1691 1692 @Override public long getPhoneSignalScanningTime( 1693 long batteryRealtime, int which) { 1694 return mPhoneSignalScanningTimer.getTotalTimeLocked( 1695 batteryRealtime, which); 1696 } 1697 1698 @Override public int getPhoneSignalStrengthCount(int dataType, int which) { 1699 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1700 } 1701 1702 @Override public long getPhoneDataConnectionTime(int dataType, 1703 long batteryRealtime, int which) { 1704 return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked( 1705 batteryRealtime, which); 1706 } 1707 1708 @Override public int getPhoneDataConnectionCount(int dataType, int which) { 1709 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1710 } 1711 1712 @Override public long getWifiOnTime(long batteryRealtime, int which) { 1713 return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which); 1714 } 1715 1716 @Override public long getWifiRunningTime(long batteryRealtime, int which) { 1717 return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which); 1718 } 1719 1720 @Override public long getBluetoothOnTime(long batteryRealtime, int which) { 1721 return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which); 1722 } 1723 1724 @Override public boolean getIsOnBattery() { 1725 return mOnBattery; 1726 } 1727 1728 @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() { 1729 return mUidStats; 1730 } 1731 1732 /** 1733 * The statistics associated with a particular uid. 1734 */ 1735 public final class Uid extends BatteryStats.Uid { 1736 1737 final int mUid; 1738 long mLoadedTcpBytesReceived; 1739 long mLoadedTcpBytesSent; 1740 long mCurrentTcpBytesReceived; 1741 long mCurrentTcpBytesSent; 1742 long mTcpBytesReceivedAtLastUnplug; 1743 long mTcpBytesSentAtLastUnplug; 1744 1745 // These are not saved/restored when parcelling, since we want 1746 // to return from the parcel with a snapshot of the state. 1747 long mStartedTcpBytesReceived = -1; 1748 long mStartedTcpBytesSent = -1; 1749 1750 boolean mWifiTurnedOn; 1751 StopwatchTimer mWifiTurnedOnTimer; 1752 1753 boolean mFullWifiLockOut; 1754 StopwatchTimer mFullWifiLockTimer; 1755 1756 boolean mScanWifiLockOut; 1757 StopwatchTimer mScanWifiLockTimer; 1758 1759 boolean mWifiMulticastEnabled; 1760 StopwatchTimer mWifiMulticastTimer; 1761 1762 boolean mAudioTurnedOn; 1763 StopwatchTimer mAudioTurnedOnTimer; 1764 1765 boolean mVideoTurnedOn; 1766 StopwatchTimer mVideoTurnedOnTimer; 1767 1768 Counter[] mUserActivityCounters; 1769 1770 /** 1771 * The statistics we have collected for this uid's wake locks. 1772 */ 1773 final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>(); 1774 1775 /** 1776 * The statistics we have collected for this uid's sensor activations. 1777 */ 1778 final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>(); 1779 1780 /** 1781 * The statistics we have collected for this uid's processes. 1782 */ 1783 final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>(); 1784 1785 /** 1786 * The statistics we have collected for this uid's processes. 1787 */ 1788 final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>(); 1789 1790 public Uid(int uid) { 1791 mUid = uid; 1792 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables); 1793 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables); 1794 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables); 1795 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1796 null, mUnpluggables); 1797 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables); 1798 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables); 1799 } 1800 1801 @Override 1802 public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() { 1803 return mWakelockStats; 1804 } 1805 1806 @Override 1807 public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() { 1808 return mSensorStats; 1809 } 1810 1811 @Override 1812 public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() { 1813 return mProcessStats; 1814 } 1815 1816 @Override 1817 public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { 1818 return mPackageStats; 1819 } 1820 1821 @Override 1822 public int getUid() { 1823 return mUid; 1824 } 1825 1826 @Override 1827 public long getTcpBytesReceived(int which) { 1828 if (which == STATS_LAST) { 1829 return mLoadedTcpBytesReceived; 1830 } else { 1831 long current = computeCurrentTcpBytesReceived(); 1832 if (which == STATS_SINCE_UNPLUGGED) { 1833 current -= mTcpBytesReceivedAtLastUnplug; 1834 } else if (which == STATS_SINCE_CHARGED) { 1835 current += mLoadedTcpBytesReceived; 1836 } 1837 return current; 1838 } 1839 } 1840 1841 public long computeCurrentTcpBytesReceived() { 1842 return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0 1843 ? (TrafficStats.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0); 1844 } 1845 1846 @Override 1847 public long getTcpBytesSent(int which) { 1848 if (which == STATS_LAST) { 1849 return mLoadedTcpBytesSent; 1850 } else { 1851 long current = computeCurrentTcpBytesSent(); 1852 if (which == STATS_SINCE_UNPLUGGED) { 1853 current -= mTcpBytesSentAtLastUnplug; 1854 } else if (which == STATS_SINCE_CHARGED) { 1855 current += mLoadedTcpBytesSent; 1856 } 1857 return current; 1858 } 1859 } 1860 1861 @Override 1862 public void noteWifiTurnedOnLocked() { 1863 if (!mWifiTurnedOn) { 1864 mWifiTurnedOn = true; 1865 if (mWifiTurnedOnTimer == null) { 1866 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, 1867 null, mUnpluggables); 1868 } 1869 mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1870 } 1871 } 1872 1873 @Override 1874 public void noteWifiTurnedOffLocked() { 1875 if (mWifiTurnedOn) { 1876 mWifiTurnedOn = false; 1877 mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1878 } 1879 } 1880 1881 @Override 1882 public void noteFullWifiLockAcquiredLocked() { 1883 if (!mFullWifiLockOut) { 1884 mFullWifiLockOut = true; 1885 if (mFullWifiLockTimer == null) { 1886 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, 1887 null, mUnpluggables); 1888 } 1889 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 1890 } 1891 } 1892 1893 @Override 1894 public void noteFullWifiLockReleasedLocked() { 1895 if (mFullWifiLockOut) { 1896 mFullWifiLockOut = false; 1897 mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 1898 } 1899 } 1900 1901 @Override 1902 public void noteScanWifiLockAcquiredLocked() { 1903 if (!mScanWifiLockOut) { 1904 mScanWifiLockOut = true; 1905 if (mScanWifiLockTimer == null) { 1906 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, 1907 null, mUnpluggables); 1908 } 1909 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 1910 } 1911 } 1912 1913 @Override 1914 public void noteScanWifiLockReleasedLocked() { 1915 if (mScanWifiLockOut) { 1916 mScanWifiLockOut = false; 1917 mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 1918 } 1919 } 1920 1921 @Override 1922 public void noteWifiMulticastEnabledLocked() { 1923 if (!mWifiMulticastEnabled) { 1924 mWifiMulticastEnabled = true; 1925 if (mWifiMulticastTimer == null) { 1926 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1927 null, mUnpluggables); 1928 } 1929 mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this); 1930 } 1931 } 1932 1933 @Override 1934 public void noteWifiMulticastDisabledLocked() { 1935 if (mWifiMulticastEnabled) { 1936 mWifiMulticastEnabled = false; 1937 mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this); 1938 } 1939 } 1940 1941 @Override 1942 public void noteAudioTurnedOnLocked() { 1943 if (!mAudioTurnedOn) { 1944 mAudioTurnedOn = true; 1945 if (mAudioTurnedOnTimer == null) { 1946 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, 1947 null, mUnpluggables); 1948 } 1949 mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1950 } 1951 } 1952 1953 @Override 1954 public void noteAudioTurnedOffLocked() { 1955 if (mAudioTurnedOn) { 1956 mAudioTurnedOn = false; 1957 mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1958 } 1959 } 1960 1961 @Override 1962 public void noteVideoTurnedOnLocked() { 1963 if (!mVideoTurnedOn) { 1964 mVideoTurnedOn = true; 1965 if (mVideoTurnedOnTimer == null) { 1966 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, 1967 null, mUnpluggables); 1968 } 1969 mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1970 } 1971 } 1972 1973 @Override 1974 public void noteVideoTurnedOffLocked() { 1975 if (mVideoTurnedOn) { 1976 mVideoTurnedOn = false; 1977 mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1978 } 1979 } 1980 1981 @Override 1982 public long getWifiTurnedOnTime(long batteryRealtime, int which) { 1983 if (mWifiTurnedOnTimer == null) { 1984 return 0; 1985 } 1986 return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1987 } 1988 1989 @Override 1990 public long getFullWifiLockTime(long batteryRealtime, int which) { 1991 if (mFullWifiLockTimer == null) { 1992 return 0; 1993 } 1994 return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 1995 } 1996 1997 @Override 1998 public long getScanWifiLockTime(long batteryRealtime, int which) { 1999 if (mScanWifiLockTimer == null) { 2000 return 0; 2001 } 2002 return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 2003 } 2004 2005 @Override 2006 public long getWifiMulticastTime(long batteryRealtime, int which) { 2007 if (mWifiMulticastTimer == null) { 2008 return 0; 2009 } 2010 return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime, 2011 which); 2012 } 2013 2014 @Override 2015 public long getAudioTurnedOnTime(long batteryRealtime, int which) { 2016 if (mAudioTurnedOnTimer == null) { 2017 return 0; 2018 } 2019 return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 2020 } 2021 2022 @Override 2023 public long getVideoTurnedOnTime(long batteryRealtime, int which) { 2024 if (mVideoTurnedOnTimer == null) { 2025 return 0; 2026 } 2027 return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 2028 } 2029 2030 @Override 2031 public void noteUserActivityLocked(int type) { 2032 if (mUserActivityCounters == null) { 2033 initUserActivityLocked(); 2034 } 2035 if (type < 0) type = 0; 2036 else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1; 2037 mUserActivityCounters[type].stepAtomic(); 2038 } 2039 2040 @Override 2041 public boolean hasUserActivity() { 2042 return mUserActivityCounters != null; 2043 } 2044 2045 @Override 2046 public int getUserActivityCount(int type, int which) { 2047 if (mUserActivityCounters == null) { 2048 return 0; 2049 } 2050 return mUserActivityCounters[type].getCountLocked(which); 2051 } 2052 2053 void initUserActivityLocked() { 2054 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 2055 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 2056 mUserActivityCounters[i] = new Counter(mUnpluggables); 2057 } 2058 } 2059 2060 public long computeCurrentTcpBytesSent() { 2061 return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0 2062 ? (TrafficStats.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0); 2063 } 2064 2065 /** 2066 * Clear all stats for this uid. Returns true if the uid is completely 2067 * inactive so can be dropped. 2068 */ 2069 boolean reset() { 2070 boolean active = false; 2071 2072 if (mWifiTurnedOnTimer != null) { 2073 active |= !mWifiTurnedOnTimer.reset(false); 2074 active |= mWifiTurnedOn; 2075 } 2076 if (mFullWifiLockTimer != null) { 2077 active |= !mFullWifiLockTimer.reset(false); 2078 active |= mFullWifiLockOut; 2079 } 2080 if (mScanWifiLockTimer != null) { 2081 active |= !mScanWifiLockTimer.reset(false); 2082 active |= mScanWifiLockOut; 2083 } 2084 if (mWifiMulticastTimer != null) { 2085 active |= !mWifiMulticastTimer.reset(false); 2086 active |= mWifiMulticastEnabled; 2087 } 2088 if (mAudioTurnedOnTimer != null) { 2089 active |= !mAudioTurnedOnTimer.reset(false); 2090 active |= mAudioTurnedOn; 2091 } 2092 if (mVideoTurnedOnTimer != null) { 2093 active |= !mVideoTurnedOnTimer.reset(false); 2094 active |= mVideoTurnedOn; 2095 } 2096 2097 mLoadedTcpBytesReceived = mLoadedTcpBytesSent = 0; 2098 mCurrentTcpBytesReceived = mCurrentTcpBytesSent = 0; 2099 2100 if (mUserActivityCounters != null) { 2101 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 2102 mUserActivityCounters[i].reset(false); 2103 } 2104 } 2105 2106 if (mWakelockStats.size() > 0) { 2107 Iterator<Map.Entry<String, Wakelock>> it = mWakelockStats.entrySet().iterator(); 2108 while (it.hasNext()) { 2109 Map.Entry<String, Wakelock> wakelockEntry = it.next(); 2110 Wakelock wl = wakelockEntry.getValue(); 2111 if (wl.reset()) { 2112 it.remove(); 2113 } else { 2114 active = true; 2115 } 2116 } 2117 } 2118 if (mSensorStats.size() > 0) { 2119 Iterator<Map.Entry<Integer, Sensor>> it = mSensorStats.entrySet().iterator(); 2120 while (it.hasNext()) { 2121 Map.Entry<Integer, Sensor> sensorEntry = it.next(); 2122 Sensor s = sensorEntry.getValue(); 2123 if (s.reset()) { 2124 it.remove(); 2125 } else { 2126 active = true; 2127 } 2128 } 2129 } 2130 if (mProcessStats.size() > 0) { 2131 Iterator<Map.Entry<String, Proc>> it = mProcessStats.entrySet().iterator(); 2132 while (it.hasNext()) { 2133 Map.Entry<String, Proc> procEntry = it.next(); 2134 procEntry.getValue().detach(); 2135 } 2136 mProcessStats.clear(); 2137 } 2138 if (mPackageStats.size() > 0) { 2139 Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator(); 2140 while (it.hasNext()) { 2141 Map.Entry<String, Pkg> pkgEntry = it.next(); 2142 Pkg p = pkgEntry.getValue(); 2143 p.detach(); 2144 if (p.mServiceStats.size() > 0) { 2145 Iterator<Map.Entry<String, Pkg.Serv>> it2 2146 = p.mServiceStats.entrySet().iterator(); 2147 while (it2.hasNext()) { 2148 Map.Entry<String, Pkg.Serv> servEntry = it2.next(); 2149 servEntry.getValue().detach(); 2150 } 2151 } 2152 } 2153 mPackageStats.clear(); 2154 } 2155 2156 if (!active) { 2157 if (mWifiTurnedOnTimer != null) { 2158 mWifiTurnedOnTimer.detach(); 2159 } 2160 if (mFullWifiLockTimer != null) { 2161 mFullWifiLockTimer.detach(); 2162 } 2163 if (mScanWifiLockTimer != null) { 2164 mScanWifiLockTimer.detach(); 2165 } 2166 if (mWifiMulticastTimer != null) { 2167 mWifiMulticastTimer.detach(); 2168 } 2169 if (mAudioTurnedOnTimer != null) { 2170 mAudioTurnedOnTimer.detach(); 2171 } 2172 if (mVideoTurnedOnTimer != null) { 2173 mVideoTurnedOnTimer.detach(); 2174 } 2175 if (mUserActivityCounters != null) { 2176 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 2177 mUserActivityCounters[i].detach(); 2178 } 2179 } 2180 } 2181 2182 return !active; 2183 } 2184 2185 void writeToParcelLocked(Parcel out, long batteryRealtime) { 2186 out.writeInt(mWakelockStats.size()); 2187 for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) { 2188 out.writeString(wakelockEntry.getKey()); 2189 Uid.Wakelock wakelock = wakelockEntry.getValue(); 2190 wakelock.writeToParcelLocked(out, batteryRealtime); 2191 } 2192 2193 out.writeInt(mSensorStats.size()); 2194 for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) { 2195 out.writeInt(sensorEntry.getKey()); 2196 Uid.Sensor sensor = sensorEntry.getValue(); 2197 sensor.writeToParcelLocked(out, batteryRealtime); 2198 } 2199 2200 out.writeInt(mProcessStats.size()); 2201 for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) { 2202 out.writeString(procEntry.getKey()); 2203 Uid.Proc proc = procEntry.getValue(); 2204 proc.writeToParcelLocked(out); 2205 } 2206 2207 out.writeInt(mPackageStats.size()); 2208 for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) { 2209 out.writeString(pkgEntry.getKey()); 2210 Uid.Pkg pkg = pkgEntry.getValue(); 2211 pkg.writeToParcelLocked(out); 2212 } 2213 2214 out.writeLong(mLoadedTcpBytesReceived); 2215 out.writeLong(mLoadedTcpBytesSent); 2216 out.writeLong(computeCurrentTcpBytesReceived()); 2217 out.writeLong(computeCurrentTcpBytesSent()); 2218 out.writeLong(mTcpBytesReceivedAtLastUnplug); 2219 out.writeLong(mTcpBytesSentAtLastUnplug); 2220 if (mWifiTurnedOnTimer != null) { 2221 out.writeInt(1); 2222 mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime); 2223 } else { 2224 out.writeInt(0); 2225 } 2226 if (mFullWifiLockTimer != null) { 2227 out.writeInt(1); 2228 mFullWifiLockTimer.writeToParcel(out, batteryRealtime); 2229 } else { 2230 out.writeInt(0); 2231 } 2232 if (mScanWifiLockTimer != null) { 2233 out.writeInt(1); 2234 mScanWifiLockTimer.writeToParcel(out, batteryRealtime); 2235 } else { 2236 out.writeInt(0); 2237 } 2238 if (mWifiMulticastTimer != null) { 2239 out.writeInt(1); 2240 mWifiMulticastTimer.writeToParcel(out, batteryRealtime); 2241 } else { 2242 out.writeInt(0); 2243 } 2244 if (mAudioTurnedOnTimer != null) { 2245 out.writeInt(1); 2246 mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime); 2247 } else { 2248 out.writeInt(0); 2249 } 2250 if (mVideoTurnedOnTimer != null) { 2251 out.writeInt(1); 2252 mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime); 2253 } else { 2254 out.writeInt(0); 2255 } 2256 if (mUserActivityCounters != null) { 2257 out.writeInt(1); 2258 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 2259 mUserActivityCounters[i].writeToParcel(out); 2260 } 2261 } else { 2262 out.writeInt(0); 2263 } 2264 } 2265 2266 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 2267 int numWakelocks = in.readInt(); 2268 mWakelockStats.clear(); 2269 for (int j = 0; j < numWakelocks; j++) { 2270 String wakelockName = in.readString(); 2271 Uid.Wakelock wakelock = new Wakelock(); 2272 wakelock.readFromParcelLocked(unpluggables, in); 2273 if (mWakelockStats.size() < MAX_WAKELOCKS_PER_UID) { 2274 // We will just drop some random set of wakelocks if 2275 // the previous run of the system was an older version 2276 // that didn't impose a limit. 2277 mWakelockStats.put(wakelockName, wakelock); 2278 } 2279 } 2280 2281 int numSensors = in.readInt(); 2282 mSensorStats.clear(); 2283 for (int k = 0; k < numSensors; k++) { 2284 int sensorNumber = in.readInt(); 2285 Uid.Sensor sensor = new Sensor(sensorNumber); 2286 sensor.readFromParcelLocked(mUnpluggables, in); 2287 mSensorStats.put(sensorNumber, sensor); 2288 } 2289 2290 int numProcs = in.readInt(); 2291 mProcessStats.clear(); 2292 for (int k = 0; k < numProcs; k++) { 2293 String processName = in.readString(); 2294 Uid.Proc proc = new Proc(); 2295 proc.readFromParcelLocked(in); 2296 mProcessStats.put(processName, proc); 2297 } 2298 2299 int numPkgs = in.readInt(); 2300 mPackageStats.clear(); 2301 for (int l = 0; l < numPkgs; l++) { 2302 String packageName = in.readString(); 2303 Uid.Pkg pkg = new Pkg(); 2304 pkg.readFromParcelLocked(in); 2305 mPackageStats.put(packageName, pkg); 2306 } 2307 2308 mLoadedTcpBytesReceived = in.readLong(); 2309 mLoadedTcpBytesSent = in.readLong(); 2310 mCurrentTcpBytesReceived = in.readLong(); 2311 mCurrentTcpBytesSent = in.readLong(); 2312 mTcpBytesReceivedAtLastUnplug = in.readLong(); 2313 mTcpBytesSentAtLastUnplug = in.readLong(); 2314 mWifiTurnedOn = false; 2315 if (in.readInt() != 0) { 2316 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, 2317 null, mUnpluggables, in); 2318 } else { 2319 mWifiTurnedOnTimer = null; 2320 } 2321 mFullWifiLockOut = false; 2322 if (in.readInt() != 0) { 2323 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, 2324 null, mUnpluggables, in); 2325 } else { 2326 mFullWifiLockTimer = null; 2327 } 2328 mScanWifiLockOut = false; 2329 if (in.readInt() != 0) { 2330 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, 2331 null, mUnpluggables, in); 2332 } else { 2333 mScanWifiLockTimer = null; 2334 } 2335 mWifiMulticastEnabled = false; 2336 if (in.readInt() != 0) { 2337 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 2338 null, mUnpluggables, in); 2339 } else { 2340 mWifiMulticastTimer = null; 2341 } 2342 mAudioTurnedOn = false; 2343 if (in.readInt() != 0) { 2344 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, 2345 null, mUnpluggables, in); 2346 } else { 2347 mAudioTurnedOnTimer = null; 2348 } 2349 mVideoTurnedOn = false; 2350 if (in.readInt() != 0) { 2351 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, 2352 null, mUnpluggables, in); 2353 } else { 2354 mVideoTurnedOnTimer = null; 2355 } 2356 if (in.readInt() != 0) { 2357 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 2358 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 2359 mUserActivityCounters[i] = new Counter(mUnpluggables, in); 2360 } 2361 } else { 2362 mUserActivityCounters = null; 2363 } 2364 } 2365 2366 /** 2367 * The statistics associated with a particular wake lock. 2368 */ 2369 public final class Wakelock extends BatteryStats.Uid.Wakelock { 2370 /** 2371 * How long (in ms) this uid has been keeping the device partially awake. 2372 */ 2373 StopwatchTimer mTimerPartial; 2374 2375 /** 2376 * How long (in ms) this uid has been keeping the device fully awake. 2377 */ 2378 StopwatchTimer mTimerFull; 2379 2380 /** 2381 * How long (in ms) this uid has had a window keeping the device awake. 2382 */ 2383 StopwatchTimer mTimerWindow; 2384 2385 /** 2386 * Reads a possibly null Timer from a Parcel. The timer is associated with the 2387 * proper timer pool from the given BatteryStatsImpl object. 2388 * 2389 * @param in the Parcel to be read from. 2390 * return a new Timer, or null. 2391 */ 2392 private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, 2393 ArrayList<Unpluggable> unpluggables, Parcel in) { 2394 if (in.readInt() == 0) { 2395 return null; 2396 } 2397 2398 return new StopwatchTimer(type, pool, unpluggables, in); 2399 } 2400 2401 boolean reset() { 2402 boolean wlactive = false; 2403 if (mTimerFull != null) { 2404 wlactive |= !mTimerFull.reset(false); 2405 } 2406 if (mTimerPartial != null) { 2407 wlactive |= !mTimerPartial.reset(false); 2408 } 2409 if (mTimerWindow != null) { 2410 wlactive |= !mTimerWindow.reset(false); 2411 } 2412 if (!wlactive) { 2413 if (mTimerFull != null) { 2414 mTimerFull.detach(); 2415 mTimerFull = null; 2416 } 2417 if (mTimerPartial != null) { 2418 mTimerPartial.detach(); 2419 mTimerPartial = null; 2420 } 2421 if (mTimerWindow != null) { 2422 mTimerWindow.detach(); 2423 mTimerWindow = null; 2424 } 2425 } 2426 return !wlactive; 2427 } 2428 2429 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 2430 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL, 2431 mPartialTimers, unpluggables, in); 2432 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, 2433 mFullTimers, unpluggables, in); 2434 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, 2435 mWindowTimers, unpluggables, in); 2436 } 2437 2438 void writeToParcelLocked(Parcel out, long batteryRealtime) { 2439 Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime); 2440 Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime); 2441 Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime); 2442 } 2443 2444 @Override 2445 public Timer getWakeTime(int type) { 2446 switch (type) { 2447 case WAKE_TYPE_FULL: return mTimerFull; 2448 case WAKE_TYPE_PARTIAL: return mTimerPartial; 2449 case WAKE_TYPE_WINDOW: return mTimerWindow; 2450 default: throw new IllegalArgumentException("type = " + type); 2451 } 2452 } 2453 } 2454 2455 public final class Sensor extends BatteryStats.Uid.Sensor { 2456 final int mHandle; 2457 StopwatchTimer mTimer; 2458 2459 public Sensor(int handle) { 2460 mHandle = handle; 2461 } 2462 2463 private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables, 2464 Parcel in) { 2465 if (in.readInt() == 0) { 2466 return null; 2467 } 2468 2469 ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle); 2470 if (pool == null) { 2471 pool = new ArrayList<StopwatchTimer>(); 2472 mSensorTimers.put(mHandle, pool); 2473 } 2474 return new StopwatchTimer(0, pool, unpluggables, in); 2475 } 2476 2477 boolean reset() { 2478 if (mTimer.reset(true)) { 2479 mTimer = null; 2480 return true; 2481 } 2482 return false; 2483 } 2484 2485 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 2486 mTimer = readTimerFromParcel(unpluggables, in); 2487 } 2488 2489 void writeToParcelLocked(Parcel out, long batteryRealtime) { 2490 Timer.writeTimerToParcel(out, mTimer, batteryRealtime); 2491 } 2492 2493 @Override 2494 public Timer getSensorTime() { 2495 return mTimer; 2496 } 2497 2498 @Override 2499 public int getHandle() { 2500 return mHandle; 2501 } 2502 } 2503 2504 /** 2505 * The statistics associated with a particular process. 2506 */ 2507 public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable { 2508 /** 2509 * Total time (in 1/100 sec) spent executing in user code. 2510 */ 2511 long mUserTime; 2512 2513 /** 2514 * Total time (in 1/100 sec) spent executing in kernel code. 2515 */ 2516 long mSystemTime; 2517 2518 /** 2519 * Number of times the process has been started. 2520 */ 2521 int mStarts; 2522 2523 /** 2524 * Amount of time the process was running in the foreground. 2525 */ 2526 long mForegroundTime; 2527 2528 /** 2529 * The amount of user time loaded from a previous save. 2530 */ 2531 long mLoadedUserTime; 2532 2533 /** 2534 * The amount of system time loaded from a previous save. 2535 */ 2536 long mLoadedSystemTime; 2537 2538 /** 2539 * The number of times the process has started from a previous save. 2540 */ 2541 int mLoadedStarts; 2542 2543 /** 2544 * The amount of foreground time loaded from a previous save. 2545 */ 2546 long mLoadedForegroundTime; 2547 2548 /** 2549 * The amount of user time loaded from the previous run. 2550 */ 2551 long mLastUserTime; 2552 2553 /** 2554 * The amount of system time loaded from the previous run. 2555 */ 2556 long mLastSystemTime; 2557 2558 /** 2559 * The number of times the process has started from the previous run. 2560 */ 2561 int mLastStarts; 2562 2563 /** 2564 * The amount of foreground time loaded from the previous run 2565 */ 2566 long mLastForegroundTime; 2567 2568 /** 2569 * The amount of user time when last unplugged. 2570 */ 2571 long mUnpluggedUserTime; 2572 2573 /** 2574 * The amount of system time when last unplugged. 2575 */ 2576 long mUnpluggedSystemTime; 2577 2578 /** 2579 * The number of times the process has started before unplugged. 2580 */ 2581 int mUnpluggedStarts; 2582 2583 /** 2584 * The amount of foreground time since unplugged. 2585 */ 2586 long mUnpluggedForegroundTime; 2587 2588 SamplingCounter[] mSpeedBins; 2589 2590 Proc() { 2591 mUnpluggables.add(this); 2592 mSpeedBins = new SamplingCounter[getCpuSpeedSteps()]; 2593 } 2594 2595 public void unplug(long batteryUptime, long batteryRealtime) { 2596 mUnpluggedUserTime = mUserTime; 2597 mUnpluggedSystemTime = mSystemTime; 2598 mUnpluggedStarts = mStarts; 2599 mUnpluggedForegroundTime = mForegroundTime; 2600 } 2601 2602 public void plug(long batteryUptime, long batteryRealtime) { 2603 } 2604 2605 void detach() { 2606 mUnpluggables.remove(this); 2607 for (int i = 0; i < mSpeedBins.length; i++) { 2608 SamplingCounter c = mSpeedBins[i]; 2609 if (c != null) { 2610 mUnpluggables.remove(c); 2611 mSpeedBins[i] = null; 2612 } 2613 } 2614 } 2615 2616 void writeToParcelLocked(Parcel out) { 2617 out.writeLong(mUserTime); 2618 out.writeLong(mSystemTime); 2619 out.writeLong(mForegroundTime); 2620 out.writeInt(mStarts); 2621 out.writeLong(mLoadedUserTime); 2622 out.writeLong(mLoadedSystemTime); 2623 out.writeLong(mLoadedForegroundTime); 2624 out.writeInt(mLoadedStarts); 2625 out.writeLong(mLastUserTime); 2626 out.writeLong(mLastSystemTime); 2627 out.writeLong(mLastForegroundTime); 2628 out.writeInt(mLastStarts); 2629 out.writeLong(mUnpluggedUserTime); 2630 out.writeLong(mUnpluggedSystemTime); 2631 out.writeLong(mUnpluggedForegroundTime); 2632 out.writeInt(mUnpluggedStarts); 2633 2634 out.writeInt(mSpeedBins.length); 2635 for (int i = 0; i < mSpeedBins.length; i++) { 2636 SamplingCounter c = mSpeedBins[i]; 2637 if (c != null) { 2638 out.writeInt(1); 2639 c.writeToParcel(out); 2640 } else { 2641 out.writeInt(0); 2642 } 2643 } 2644 } 2645 2646 void readFromParcelLocked(Parcel in) { 2647 mUserTime = in.readLong(); 2648 mSystemTime = in.readLong(); 2649 mForegroundTime = in.readLong(); 2650 mStarts = in.readInt(); 2651 mLoadedUserTime = in.readLong(); 2652 mLoadedSystemTime = in.readLong(); 2653 mLoadedForegroundTime = in.readLong(); 2654 mLoadedStarts = in.readInt(); 2655 mLastUserTime = in.readLong(); 2656 mLastSystemTime = in.readLong(); 2657 mLastForegroundTime = in.readLong(); 2658 mLastStarts = in.readInt(); 2659 mUnpluggedUserTime = in.readLong(); 2660 mUnpluggedSystemTime = in.readLong(); 2661 mUnpluggedForegroundTime = in.readLong(); 2662 mUnpluggedStarts = in.readInt(); 2663 2664 int bins = in.readInt(); 2665 int steps = getCpuSpeedSteps(); 2666 mSpeedBins = new SamplingCounter[bins >= steps ? bins : steps]; 2667 for (int i = 0; i < bins; i++) { 2668 if (in.readInt() != 0) { 2669 mSpeedBins[i] = new SamplingCounter(mUnpluggables, in); 2670 } 2671 } 2672 } 2673 2674 public BatteryStatsImpl getBatteryStats() { 2675 return BatteryStatsImpl.this; 2676 } 2677 2678 public void addCpuTimeLocked(int utime, int stime) { 2679 mUserTime += utime; 2680 mSystemTime += stime; 2681 } 2682 2683 public void addForegroundTimeLocked(long ttime) { 2684 mForegroundTime += ttime; 2685 } 2686 2687 public void incStartsLocked() { 2688 mStarts++; 2689 } 2690 2691 @Override 2692 public long getUserTime(int which) { 2693 long val; 2694 if (which == STATS_LAST) { 2695 val = mLastUserTime; 2696 } else { 2697 val = mUserTime; 2698 if (which == STATS_CURRENT) { 2699 val -= mLoadedUserTime; 2700 } else if (which == STATS_SINCE_UNPLUGGED) { 2701 val -= mUnpluggedUserTime; 2702 } 2703 } 2704 return val; 2705 } 2706 2707 @Override 2708 public long getSystemTime(int which) { 2709 long val; 2710 if (which == STATS_LAST) { 2711 val = mLastSystemTime; 2712 } else { 2713 val = mSystemTime; 2714 if (which == STATS_CURRENT) { 2715 val -= mLoadedSystemTime; 2716 } else if (which == STATS_SINCE_UNPLUGGED) { 2717 val -= mUnpluggedSystemTime; 2718 } 2719 } 2720 return val; 2721 } 2722 2723 @Override 2724 public long getForegroundTime(int which) { 2725 long val; 2726 if (which == STATS_LAST) { 2727 val = mLastForegroundTime; 2728 } else { 2729 val = mForegroundTime; 2730 if (which == STATS_CURRENT) { 2731 val -= mLoadedForegroundTime; 2732 } else if (which == STATS_SINCE_UNPLUGGED) { 2733 val -= mUnpluggedForegroundTime; 2734 } 2735 } 2736 return val; 2737 } 2738 2739 @Override 2740 public int getStarts(int which) { 2741 int val; 2742 if (which == STATS_LAST) { 2743 val = mLastStarts; 2744 } else { 2745 val = mStarts; 2746 if (which == STATS_CURRENT) { 2747 val -= mLoadedStarts; 2748 } else if (which == STATS_SINCE_UNPLUGGED) { 2749 val -= mUnpluggedStarts; 2750 } 2751 } 2752 return val; 2753 } 2754 2755 /* Called by ActivityManagerService when CPU times are updated. */ 2756 public void addSpeedStepTimes(long[] values) { 2757 for (int i = 0; i < mSpeedBins.length && i < values.length; i++) { 2758 long amt = values[i]; 2759 if (amt != 0) { 2760 SamplingCounter c = mSpeedBins[i]; 2761 if (c == null) { 2762 mSpeedBins[i] = c = new SamplingCounter(mUnpluggables); 2763 } 2764 c.addCountAtomic(values[i]); 2765 } 2766 } 2767 } 2768 2769 @Override 2770 public long getTimeAtCpuSpeedStep(int speedStep, int which) { 2771 if (speedStep < mSpeedBins.length) { 2772 SamplingCounter c = mSpeedBins[speedStep]; 2773 return c != null ? c.getCountLocked(which) : 0; 2774 } else { 2775 return 0; 2776 } 2777 } 2778 } 2779 2780 /** 2781 * The statistics associated with a particular package. 2782 */ 2783 public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable { 2784 /** 2785 * Number of times this package has done something that could wake up the 2786 * device from sleep. 2787 */ 2788 int mWakeups; 2789 2790 /** 2791 * Number of things that could wake up the device loaded from a 2792 * previous save. 2793 */ 2794 int mLoadedWakeups; 2795 2796 /** 2797 * Number of things that could wake up the device as of the 2798 * last run. 2799 */ 2800 int mLastWakeups; 2801 2802 /** 2803 * Number of things that could wake up the device as of the 2804 * last run. 2805 */ 2806 int mUnpluggedWakeups; 2807 2808 /** 2809 * The statics we have collected for this package's services. 2810 */ 2811 final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>(); 2812 2813 Pkg() { 2814 mUnpluggables.add(this); 2815 } 2816 2817 public void unplug(long batteryUptime, long batteryRealtime) { 2818 mUnpluggedWakeups = mWakeups; 2819 } 2820 2821 public void plug(long batteryUptime, long batteryRealtime) { 2822 } 2823 2824 void detach() { 2825 mUnpluggables.remove(this); 2826 } 2827 2828 void readFromParcelLocked(Parcel in) { 2829 mWakeups = in.readInt(); 2830 mLoadedWakeups = in.readInt(); 2831 mLastWakeups = in.readInt(); 2832 mUnpluggedWakeups = in.readInt(); 2833 2834 int numServs = in.readInt(); 2835 mServiceStats.clear(); 2836 for (int m = 0; m < numServs; m++) { 2837 String serviceName = in.readString(); 2838 Uid.Pkg.Serv serv = new Serv(); 2839 mServiceStats.put(serviceName, serv); 2840 2841 serv.readFromParcelLocked(in); 2842 } 2843 } 2844 2845 void writeToParcelLocked(Parcel out) { 2846 out.writeInt(mWakeups); 2847 out.writeInt(mLoadedWakeups); 2848 out.writeInt(mLastWakeups); 2849 out.writeInt(mUnpluggedWakeups); 2850 2851 out.writeInt(mServiceStats.size()); 2852 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) { 2853 out.writeString(servEntry.getKey()); 2854 Uid.Pkg.Serv serv = servEntry.getValue(); 2855 2856 serv.writeToParcelLocked(out); 2857 } 2858 } 2859 2860 @Override 2861 public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() { 2862 return mServiceStats; 2863 } 2864 2865 @Override 2866 public int getWakeups(int which) { 2867 int val; 2868 if (which == STATS_LAST) { 2869 val = mLastWakeups; 2870 } else { 2871 val = mWakeups; 2872 if (which == STATS_CURRENT) { 2873 val -= mLoadedWakeups; 2874 } else if (which == STATS_SINCE_UNPLUGGED) { 2875 val -= mUnpluggedWakeups; 2876 } 2877 } 2878 2879 return val; 2880 } 2881 2882 /** 2883 * The statistics associated with a particular service. 2884 */ 2885 public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable { 2886 /** 2887 * Total time (ms in battery uptime) the service has been left started. 2888 */ 2889 long mStartTime; 2890 2891 /** 2892 * If service has been started and not yet stopped, this is 2893 * when it was started. 2894 */ 2895 long mRunningSince; 2896 2897 /** 2898 * True if we are currently running. 2899 */ 2900 boolean mRunning; 2901 2902 /** 2903 * Total number of times startService() has been called. 2904 */ 2905 int mStarts; 2906 2907 /** 2908 * Total time (ms in battery uptime) the service has been left launched. 2909 */ 2910 long mLaunchedTime; 2911 2912 /** 2913 * If service has been launched and not yet exited, this is 2914 * when it was launched (ms in battery uptime). 2915 */ 2916 long mLaunchedSince; 2917 2918 /** 2919 * True if we are currently launched. 2920 */ 2921 boolean mLaunched; 2922 2923 /** 2924 * Total number times the service has been launched. 2925 */ 2926 int mLaunches; 2927 2928 /** 2929 * The amount of time spent started loaded from a previous save 2930 * (ms in battery uptime). 2931 */ 2932 long mLoadedStartTime; 2933 2934 /** 2935 * The number of starts loaded from a previous save. 2936 */ 2937 int mLoadedStarts; 2938 2939 /** 2940 * The number of launches loaded from a previous save. 2941 */ 2942 int mLoadedLaunches; 2943 2944 /** 2945 * The amount of time spent started as of the last run (ms 2946 * in battery uptime). 2947 */ 2948 long mLastStartTime; 2949 2950 /** 2951 * The number of starts as of the last run. 2952 */ 2953 int mLastStarts; 2954 2955 /** 2956 * The number of launches as of the last run. 2957 */ 2958 int mLastLaunches; 2959 2960 /** 2961 * The amount of time spent started when last unplugged (ms 2962 * in battery uptime). 2963 */ 2964 long mUnpluggedStartTime; 2965 2966 /** 2967 * The number of starts when last unplugged. 2968 */ 2969 int mUnpluggedStarts; 2970 2971 /** 2972 * The number of launches when last unplugged. 2973 */ 2974 int mUnpluggedLaunches; 2975 2976 Serv() { 2977 mUnpluggables.add(this); 2978 } 2979 2980 public void unplug(long batteryUptime, long batteryRealtime) { 2981 mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime); 2982 mUnpluggedStarts = mStarts; 2983 mUnpluggedLaunches = mLaunches; 2984 } 2985 2986 public void plug(long batteryUptime, long batteryRealtime) { 2987 } 2988 2989 void detach() { 2990 mUnpluggables.remove(this); 2991 } 2992 2993 void readFromParcelLocked(Parcel in) { 2994 mStartTime = in.readLong(); 2995 mRunningSince = in.readLong(); 2996 mRunning = in.readInt() != 0; 2997 mStarts = in.readInt(); 2998 mLaunchedTime = in.readLong(); 2999 mLaunchedSince = in.readLong(); 3000 mLaunched = in.readInt() != 0; 3001 mLaunches = in.readInt(); 3002 mLoadedStartTime = in.readLong(); 3003 mLoadedStarts = in.readInt(); 3004 mLoadedLaunches = in.readInt(); 3005 mLastStartTime = in.readLong(); 3006 mLastStarts = in.readInt(); 3007 mLastLaunches = in.readInt(); 3008 mUnpluggedStartTime = in.readLong(); 3009 mUnpluggedStarts = in.readInt(); 3010 mUnpluggedLaunches = in.readInt(); 3011 } 3012 3013 void writeToParcelLocked(Parcel out) { 3014 out.writeLong(mStartTime); 3015 out.writeLong(mRunningSince); 3016 out.writeInt(mRunning ? 1 : 0); 3017 out.writeInt(mStarts); 3018 out.writeLong(mLaunchedTime); 3019 out.writeLong(mLaunchedSince); 3020 out.writeInt(mLaunched ? 1 : 0); 3021 out.writeInt(mLaunches); 3022 out.writeLong(mLoadedStartTime); 3023 out.writeInt(mLoadedStarts); 3024 out.writeInt(mLoadedLaunches); 3025 out.writeLong(mLastStartTime); 3026 out.writeInt(mLastStarts); 3027 out.writeInt(mLastLaunches); 3028 out.writeLong(mUnpluggedStartTime); 3029 out.writeInt(mUnpluggedStarts); 3030 out.writeInt(mUnpluggedLaunches); 3031 } 3032 3033 long getLaunchTimeToNowLocked(long batteryUptime) { 3034 if (!mLaunched) return mLaunchedTime; 3035 return mLaunchedTime + batteryUptime - mLaunchedSince; 3036 } 3037 3038 long getStartTimeToNowLocked(long batteryUptime) { 3039 if (!mRunning) return mStartTime; 3040 return mStartTime + batteryUptime - mRunningSince; 3041 } 3042 3043 public void startLaunchedLocked() { 3044 if (!mLaunched) { 3045 mLaunches++; 3046 mLaunchedSince = getBatteryUptimeLocked(); 3047 mLaunched = true; 3048 } 3049 } 3050 3051 public void stopLaunchedLocked() { 3052 if (mLaunched) { 3053 long time = getBatteryUptimeLocked() - mLaunchedSince; 3054 if (time > 0) { 3055 mLaunchedTime += time; 3056 } else { 3057 mLaunches--; 3058 } 3059 mLaunched = false; 3060 } 3061 } 3062 3063 public void startRunningLocked() { 3064 if (!mRunning) { 3065 mStarts++; 3066 mRunningSince = getBatteryUptimeLocked(); 3067 mRunning = true; 3068 } 3069 } 3070 3071 public void stopRunningLocked() { 3072 if (mRunning) { 3073 long time = getBatteryUptimeLocked() - mRunningSince; 3074 if (time > 0) { 3075 mStartTime += time; 3076 } else { 3077 mStarts--; 3078 } 3079 mRunning = false; 3080 } 3081 } 3082 3083 public BatteryStatsImpl getBatteryStats() { 3084 return BatteryStatsImpl.this; 3085 } 3086 3087 @Override 3088 public int getLaunches(int which) { 3089 int val; 3090 3091 if (which == STATS_LAST) { 3092 val = mLastLaunches; 3093 } else { 3094 val = mLaunches; 3095 if (which == STATS_CURRENT) { 3096 val -= mLoadedLaunches; 3097 } else if (which == STATS_SINCE_UNPLUGGED) { 3098 val -= mUnpluggedLaunches; 3099 } 3100 } 3101 3102 return val; 3103 } 3104 3105 @Override 3106 public long getStartTime(long now, int which) { 3107 long val; 3108 if (which == STATS_LAST) { 3109 val = mLastStartTime; 3110 } else { 3111 val = getStartTimeToNowLocked(now); 3112 if (which == STATS_CURRENT) { 3113 val -= mLoadedStartTime; 3114 } else if (which == STATS_SINCE_UNPLUGGED) { 3115 val -= mUnpluggedStartTime; 3116 } 3117 } 3118 3119 return val; 3120 } 3121 3122 @Override 3123 public int getStarts(int which) { 3124 int val; 3125 if (which == STATS_LAST) { 3126 val = mLastStarts; 3127 } else { 3128 val = mStarts; 3129 if (which == STATS_CURRENT) { 3130 val -= mLoadedStarts; 3131 } else if (which == STATS_SINCE_UNPLUGGED) { 3132 val -= mUnpluggedStarts; 3133 } 3134 } 3135 3136 return val; 3137 } 3138 } 3139 3140 public BatteryStatsImpl getBatteryStats() { 3141 return BatteryStatsImpl.this; 3142 } 3143 3144 public void incWakeupsLocked() { 3145 mWakeups++; 3146 } 3147 3148 final Serv newServiceStatsLocked() { 3149 return new Serv(); 3150 } 3151 } 3152 3153 /** 3154 * Retrieve the statistics object for a particular process, creating 3155 * if needed. 3156 */ 3157 public Proc getProcessStatsLocked(String name) { 3158 Proc ps = mProcessStats.get(name); 3159 if (ps == null) { 3160 ps = new Proc(); 3161 mProcessStats.put(name, ps); 3162 } 3163 3164 return ps; 3165 } 3166 3167 /** 3168 * Retrieve the statistics object for a particular service, creating 3169 * if needed. 3170 */ 3171 public Pkg getPackageStatsLocked(String name) { 3172 Pkg ps = mPackageStats.get(name); 3173 if (ps == null) { 3174 ps = new Pkg(); 3175 mPackageStats.put(name, ps); 3176 } 3177 3178 return ps; 3179 } 3180 3181 /** 3182 * Retrieve the statistics object for a particular service, creating 3183 * if needed. 3184 */ 3185 public Pkg.Serv getServiceStatsLocked(String pkg, String serv) { 3186 Pkg ps = getPackageStatsLocked(pkg); 3187 Pkg.Serv ss = ps.mServiceStats.get(serv); 3188 if (ss == null) { 3189 ss = ps.newServiceStatsLocked(); 3190 ps.mServiceStats.put(serv, ss); 3191 } 3192 3193 return ss; 3194 } 3195 3196 public StopwatchTimer getWakeTimerLocked(String name, int type) { 3197 Wakelock wl = mWakelockStats.get(name); 3198 if (wl == null) { 3199 if (mWakelockStats.size() > MAX_WAKELOCKS_PER_UID) { 3200 name = BATCHED_WAKELOCK_NAME; 3201 wl = mWakelockStats.get(name); 3202 } 3203 if (wl == null) { 3204 wl = new Wakelock(); 3205 mWakelockStats.put(name, wl); 3206 } 3207 } 3208 StopwatchTimer t = null; 3209 switch (type) { 3210 case WAKE_TYPE_PARTIAL: 3211 t = wl.mTimerPartial; 3212 if (t == null) { 3213 t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables); 3214 wl.mTimerPartial = t; 3215 } 3216 return t; 3217 case WAKE_TYPE_FULL: 3218 t = wl.mTimerFull; 3219 if (t == null) { 3220 t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables); 3221 wl.mTimerFull = t; 3222 } 3223 return t; 3224 case WAKE_TYPE_WINDOW: 3225 t = wl.mTimerWindow; 3226 if (t == null) { 3227 t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables); 3228 wl.mTimerWindow = t; 3229 } 3230 return t; 3231 default: 3232 throw new IllegalArgumentException("type=" + type); 3233 } 3234 } 3235 3236 public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) { 3237 Sensor se = mSensorStats.get(sensor); 3238 if (se == null) { 3239 if (!create) { 3240 return null; 3241 } 3242 se = new Sensor(sensor); 3243 mSensorStats.put(sensor, se); 3244 } 3245 StopwatchTimer t = se.mTimer; 3246 if (t != null) { 3247 return t; 3248 } 3249 ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor); 3250 if (timers == null) { 3251 timers = new ArrayList<StopwatchTimer>(); 3252 mSensorTimers.put(sensor, timers); 3253 } 3254 t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables); 3255 se.mTimer = t; 3256 return t; 3257 } 3258 3259 public void noteStartWakeLocked(String name, int type) { 3260 StopwatchTimer t = getWakeTimerLocked(name, type); 3261 if (t != null) { 3262 t.startRunningLocked(BatteryStatsImpl.this); 3263 } 3264 } 3265 3266 public void noteStopWakeLocked(String name, int type) { 3267 StopwatchTimer t = getWakeTimerLocked(name, type); 3268 if (t != null) { 3269 t.stopRunningLocked(BatteryStatsImpl.this); 3270 } 3271 } 3272 3273 public void noteStartSensor(int sensor) { 3274 StopwatchTimer t = getSensorTimerLocked(sensor, true); 3275 if (t != null) { 3276 t.startRunningLocked(BatteryStatsImpl.this); 3277 } 3278 } 3279 3280 public void noteStopSensor(int sensor) { 3281 // Don't create a timer if one doesn't already exist 3282 StopwatchTimer t = getSensorTimerLocked(sensor, false); 3283 if (t != null) { 3284 t.stopRunningLocked(BatteryStatsImpl.this); 3285 } 3286 } 3287 3288 public void noteStartGps() { 3289 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true); 3290 if (t != null) { 3291 t.startRunningLocked(BatteryStatsImpl.this); 3292 } 3293 } 3294 3295 public void noteStopGps() { 3296 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false); 3297 if (t != null) { 3298 t.stopRunningLocked(BatteryStatsImpl.this); 3299 } 3300 } 3301 3302 public BatteryStatsImpl getBatteryStats() { 3303 return BatteryStatsImpl.this; 3304 } 3305 } 3306 3307 public BatteryStatsImpl(String filename) { 3308 mFile = new JournaledFile(new File(filename), new File(filename + ".tmp")); 3309 mStartCount++; 3310 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables); 3311 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3312 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables); 3313 } 3314 mInputEventCounter = new Counter(mUnpluggables); 3315 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables); 3316 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3317 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables); 3318 } 3319 mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables); 3320 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3321 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables); 3322 } 3323 mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables); 3324 mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables); 3325 mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables); 3326 mAudioOnTimer = new StopwatchTimer(-6, null, mUnpluggables); 3327 mVideoOnTimer = new StopwatchTimer(-7, null, mUnpluggables); 3328 mOnBattery = mOnBatteryInternal = false; 3329 initTimes(); 3330 mTrackBatteryPastUptime = 0; 3331 mTrackBatteryPastRealtime = 0; 3332 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; 3333 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; 3334 mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); 3335 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); 3336 mDischargeStartLevel = 0; 3337 mDischargeUnplugLevel = 0; 3338 mDischargeCurrentLevel = 0; 3339 } 3340 3341 public BatteryStatsImpl(Parcel p) { 3342 mFile = null; 3343 readFromParcel(p); 3344 } 3345 3346 public void setNumSpeedSteps(int steps) { 3347 if (sNumSpeedSteps == 0) sNumSpeedSteps = steps; 3348 } 3349 3350 public void setRadioScanningTimeout(long timeout) { 3351 if (mPhoneSignalScanningTimer != null) { 3352 mPhoneSignalScanningTimer.setTimeout(timeout); 3353 } 3354 } 3355 3356 @Override 3357 public HistoryItem getHistory() { 3358 return mHistory; 3359 } 3360 3361 @Override 3362 public int getStartCount() { 3363 return mStartCount; 3364 } 3365 3366 public boolean isOnBattery() { 3367 return mOnBattery; 3368 } 3369 3370 void initTimes() { 3371 mBatteryRealtime = mTrackBatteryPastUptime = 0; 3372 mBatteryUptime = mTrackBatteryPastRealtime = 0; 3373 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; 3374 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; 3375 mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); 3376 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); 3377 } 3378 3379 public void resetAllStatsLocked() { 3380 mStartCount = 0; 3381 initTimes(); 3382 mScreenOnTimer.reset(false); 3383 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3384 mScreenBrightnessTimer[i].reset(false); 3385 } 3386 mInputEventCounter.reset(false); 3387 mPhoneOnTimer.reset(false); 3388 mAudioOnTimer.reset(false); 3389 mVideoOnTimer.reset(false); 3390 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3391 mPhoneSignalStrengthsTimer[i].reset(false); 3392 } 3393 mPhoneSignalScanningTimer.reset(false); 3394 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3395 mPhoneDataConnectionsTimer[i].reset(false); 3396 } 3397 mWifiOnTimer.reset(false); 3398 mWifiRunningTimer.reset(false); 3399 mBluetoothOnTimer.reset(false); 3400 3401 for (int i=0; i<mUidStats.size(); i++) { 3402 if (mUidStats.valueAt(i).reset()) { 3403 mUidStats.remove(mUidStats.keyAt(i)); 3404 i--; 3405 } 3406 } 3407 3408 if (mKernelWakelockStats.size() > 0) { 3409 for (SamplingTimer timer : mKernelWakelockStats.values()) { 3410 mUnpluggables.remove(timer); 3411 } 3412 mKernelWakelockStats.clear(); 3413 } 3414 3415 clearHistoryLocked(); 3416 } 3417 3418 void setOnBattery(boolean onBattery, int oldStatus, int level) { 3419 synchronized(this) { 3420 boolean doWrite = false; 3421 mOnBattery = mOnBatteryInternal = onBattery; 3422 3423 long uptime = SystemClock.uptimeMillis() * 1000; 3424 long mSecRealtime = SystemClock.elapsedRealtime(); 3425 long realtime = mSecRealtime * 1000; 3426 if (onBattery) { 3427 // We will reset our status if we are unplugging after the 3428 // battery was last full, or the level is at 100, or 3429 // we have gone through a significant charge (from a very low 3430 // level to a now very high level). 3431 if (oldStatus == BatteryManager.BATTERY_STATUS_FULL 3432 || level >= 100 3433 || (mDischargeCurrentLevel < 20 && level > 90)) { 3434 doWrite = true; 3435 resetAllStatsLocked(); 3436 mDischargeStartLevel = level; 3437 } 3438 updateKernelWakelocksLocked(); 3439 mHistoryCur.batteryLevel = (byte)level; 3440 mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; 3441 if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: " 3442 + Integer.toHexString(mHistoryCur.states)); 3443 addHistoryRecordLocked(mSecRealtime); 3444 mTrackBatteryUptimeStart = uptime; 3445 mTrackBatteryRealtimeStart = realtime; 3446 mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); 3447 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); 3448 mDischargeCurrentLevel = mDischargeUnplugLevel = level; 3449 doUnplugLocked(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); 3450 } else { 3451 updateKernelWakelocksLocked(); 3452 mHistoryCur.batteryLevel = (byte)level; 3453 mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; 3454 if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: " 3455 + Integer.toHexString(mHistoryCur.states)); 3456 addHistoryRecordLocked(mSecRealtime); 3457 mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; 3458 mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; 3459 mDischargeCurrentLevel = level; 3460 doPlugLocked(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); 3461 } 3462 if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) { 3463 if (mFile != null) { 3464 writeLocked(); 3465 } 3466 } 3467 } 3468 } 3469 3470 // This should probably be exposed in the API, though it's not critical 3471 private static final int BATTERY_PLUGGED_NONE = 0; 3472 3473 public void setBatteryState(int status, int health, int plugType, int level, 3474 int temp, int volt) { 3475 boolean onBattery = plugType == BATTERY_PLUGGED_NONE; 3476 int oldStatus = mHistoryCur.batteryStatus; 3477 if (!mHaveBatteryLevel) { 3478 mHaveBatteryLevel = true; 3479 // We start out assuming that the device is plugged in (not 3480 // on battery). If our first report is now that we are indeed 3481 // plugged in, then twiddle our state to correctly reflect that 3482 // since we won't be going through the full setOnBattery(). 3483 if (onBattery == mOnBattery) { 3484 if (onBattery) { 3485 mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; 3486 } else { 3487 mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; 3488 } 3489 } 3490 oldStatus = status; 3491 } 3492 if (onBattery) { 3493 mDischargeCurrentLevel = level; 3494 mRecordingHistory = true; 3495 } 3496 if (onBattery != mOnBattery) { 3497 mHistoryCur.batteryLevel = (byte)level; 3498 mHistoryCur.batteryStatus = (byte)status; 3499 mHistoryCur.batteryHealth = (byte)health; 3500 mHistoryCur.batteryPlugType = (byte)plugType; 3501 mHistoryCur.batteryTemperature = (char)temp; 3502 mHistoryCur.batteryVoltage = (char)volt; 3503 setOnBattery(onBattery, oldStatus, level); 3504 } else { 3505 boolean changed = false; 3506 if (mHistoryCur.batteryLevel != level) { 3507 mHistoryCur.batteryLevel = (byte)level; 3508 changed = true; 3509 } 3510 if (mHistoryCur.batteryStatus != status) { 3511 mHistoryCur.batteryStatus = (byte)status; 3512 changed = true; 3513 } 3514 if (mHistoryCur.batteryHealth != health) { 3515 mHistoryCur.batteryHealth = (byte)health; 3516 changed = true; 3517 } 3518 if (mHistoryCur.batteryPlugType != plugType) { 3519 mHistoryCur.batteryPlugType = (byte)plugType; 3520 changed = true; 3521 } 3522 if (mHistoryCur.batteryTemperature != temp) { 3523 mHistoryCur.batteryTemperature = (char)temp; 3524 changed = true; 3525 } 3526 if (mHistoryCur.batteryVoltage != volt) { 3527 mHistoryCur.batteryVoltage = (char)volt; 3528 changed = true; 3529 } 3530 if (changed) { 3531 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 3532 } 3533 } 3534 if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) { 3535 // We don't record history while we are plugged in and fully charged. 3536 // The next time we are unplugged, history will be cleared. 3537 mRecordingHistory = false; 3538 } 3539 } 3540 3541 public void updateKernelWakelocksLocked() { 3542 Map<String, KernelWakelockStats> m = readKernelWakelockStats(); 3543 3544 if (m == null) { 3545 // Not crashing might make board bringup easier. 3546 Slog.w(TAG, "Couldn't get kernel wake lock stats"); 3547 return; 3548 } 3549 3550 for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) { 3551 String name = ent.getKey(); 3552 KernelWakelockStats kws = ent.getValue(); 3553 3554 SamplingTimer kwlt = mKernelWakelockStats.get(name); 3555 if (kwlt == null) { 3556 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 3557 true /* track reported values */); 3558 mKernelWakelockStats.put(name, kwlt); 3559 } 3560 kwlt.updateCurrentReportedCount(kws.mCount); 3561 kwlt.updateCurrentReportedTotalTime(kws.mTotalTime); 3562 kwlt.setUpdateVersion(sKernelWakelockUpdateVersion); 3563 } 3564 3565 if (m.size() != mKernelWakelockStats.size()) { 3566 // Set timers to stale if they didn't appear in /proc/wakelocks this time. 3567 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 3568 SamplingTimer st = ent.getValue(); 3569 if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) { 3570 st.setStale(); 3571 } 3572 } 3573 } 3574 } 3575 3576 public long getAwakeTimeBattery() { 3577 return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT); 3578 } 3579 3580 public long getAwakeTimePlugged() { 3581 return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery(); 3582 } 3583 3584 @Override 3585 public long computeUptime(long curTime, int which) { 3586 switch (which) { 3587 case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart); 3588 case STATS_LAST: return mLastUptime; 3589 case STATS_CURRENT: return (curTime-mUptimeStart); 3590 case STATS_SINCE_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart); 3591 } 3592 return 0; 3593 } 3594 3595 @Override 3596 public long computeRealtime(long curTime, int which) { 3597 switch (which) { 3598 case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart); 3599 case STATS_LAST: return mLastRealtime; 3600 case STATS_CURRENT: return (curTime-mRealtimeStart); 3601 case STATS_SINCE_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart); 3602 } 3603 return 0; 3604 } 3605 3606 @Override 3607 public long computeBatteryUptime(long curTime, int which) { 3608 switch (which) { 3609 case STATS_SINCE_CHARGED: 3610 return mBatteryUptime + getBatteryUptime(curTime); 3611 case STATS_LAST: 3612 return mBatteryLastUptime; 3613 case STATS_CURRENT: 3614 return getBatteryUptime(curTime); 3615 case STATS_SINCE_UNPLUGGED: 3616 return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime; 3617 } 3618 return 0; 3619 } 3620 3621 @Override 3622 public long computeBatteryRealtime(long curTime, int which) { 3623 switch (which) { 3624 case STATS_SINCE_CHARGED: 3625 return mBatteryRealtime + getBatteryRealtimeLocked(curTime); 3626 case STATS_LAST: 3627 return mBatteryLastRealtime; 3628 case STATS_CURRENT: 3629 return getBatteryRealtimeLocked(curTime); 3630 case STATS_SINCE_UNPLUGGED: 3631 return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime; 3632 } 3633 return 0; 3634 } 3635 3636 long getBatteryUptimeLocked(long curTime) { 3637 long time = mTrackBatteryPastUptime; 3638 if (mOnBatteryInternal) { 3639 time += curTime - mTrackBatteryUptimeStart; 3640 } 3641 return time; 3642 } 3643 3644 long getBatteryUptimeLocked() { 3645 return getBatteryUptime(SystemClock.uptimeMillis() * 1000); 3646 } 3647 3648 @Override 3649 public long getBatteryUptime(long curTime) { 3650 return getBatteryUptimeLocked(curTime); 3651 } 3652 3653 long getBatteryRealtimeLocked(long curTime) { 3654 long time = mTrackBatteryPastRealtime; 3655 if (mOnBatteryInternal) { 3656 time += curTime - mTrackBatteryRealtimeStart; 3657 } 3658 return time; 3659 } 3660 3661 @Override 3662 public long getBatteryRealtime(long curTime) { 3663 return getBatteryRealtimeLocked(curTime); 3664 } 3665 3666 private long getTcpBytes(long current, long[] dataBytes, int which) { 3667 if (which == STATS_LAST) { 3668 return dataBytes[STATS_LAST]; 3669 } else { 3670 if (which == STATS_SINCE_UNPLUGGED) { 3671 if (dataBytes[STATS_SINCE_UNPLUGGED] < 0) { 3672 return dataBytes[STATS_LAST]; 3673 } else { 3674 return current - dataBytes[STATS_SINCE_UNPLUGGED]; 3675 } 3676 } else if (which == STATS_SINCE_CHARGED) { 3677 return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_SINCE_CHARGED]; 3678 } 3679 return current - dataBytes[STATS_CURRENT]; 3680 } 3681 } 3682 3683 /** Only STATS_UNPLUGGED works properly */ 3684 public long getMobileTcpBytesSent(int which) { 3685 return getTcpBytes(TrafficStats.getMobileTxBytes(), mMobileDataTx, which); 3686 } 3687 3688 /** Only STATS_UNPLUGGED works properly */ 3689 public long getMobileTcpBytesReceived(int which) { 3690 return getTcpBytes(TrafficStats.getMobileRxBytes(), mMobileDataRx, which); 3691 } 3692 3693 /** Only STATS_UNPLUGGED works properly */ 3694 public long getTotalTcpBytesSent(int which) { 3695 return getTcpBytes(TrafficStats.getTotalTxBytes(), mTotalDataTx, which); 3696 } 3697 3698 /** Only STATS_UNPLUGGED works properly */ 3699 public long getTotalTcpBytesReceived(int which) { 3700 return getTcpBytes(TrafficStats.getTotalRxBytes(), mTotalDataRx, which); 3701 } 3702 3703 @Override 3704 public int getDischargeStartLevel() { 3705 synchronized(this) { 3706 return getDischargeStartLevelLocked(); 3707 } 3708 } 3709 3710 public int getDischargeStartLevelLocked() { 3711 return mDischargeUnplugLevel; 3712 } 3713 3714 @Override 3715 public int getDischargeCurrentLevel() { 3716 synchronized(this) { 3717 return getDischargeCurrentLevelLocked(); 3718 } 3719 } 3720 3721 public int getDischargeCurrentLevelLocked() { 3722 return mDischargeCurrentLevel; 3723 } 3724 3725 @Override 3726 public int getCpuSpeedSteps() { 3727 return sNumSpeedSteps; 3728 } 3729 3730 /** 3731 * Retrieve the statistics object for a particular uid, creating if needed. 3732 */ 3733 public Uid getUidStatsLocked(int uid) { 3734 Uid u = mUidStats.get(uid); 3735 if (u == null) { 3736 u = new Uid(uid); 3737 mUidStats.put(uid, u); 3738 } 3739 return u; 3740 } 3741 3742 /** 3743 * Remove the statistics object for a particular uid. 3744 */ 3745 public void removeUidStatsLocked(int uid) { 3746 mUidStats.remove(uid); 3747 } 3748 3749 /** 3750 * Retrieve the statistics object for a particular process, creating 3751 * if needed. 3752 */ 3753 public Uid.Proc getProcessStatsLocked(int uid, String name) { 3754 Uid u = getUidStatsLocked(uid); 3755 return u.getProcessStatsLocked(name); 3756 } 3757 3758 /** 3759 * Retrieve the statistics object for a particular process, given 3760 * the name of the process. 3761 * @param name process name 3762 * @return the statistics object for the process 3763 */ 3764 public Uid.Proc getProcessStatsLocked(String name, int pid) { 3765 int uid; 3766 if (mUidCache.containsKey(name)) { 3767 uid = mUidCache.get(name); 3768 } else { 3769 uid = Process.getUidForPid(pid); 3770 mUidCache.put(name, uid); 3771 } 3772 Uid u = getUidStatsLocked(uid); 3773 return u.getProcessStatsLocked(name); 3774 } 3775 3776 /** 3777 * Retrieve the statistics object for a particular process, creating 3778 * if needed. 3779 */ 3780 public Uid.Pkg getPackageStatsLocked(int uid, String pkg) { 3781 Uid u = getUidStatsLocked(uid); 3782 return u.getPackageStatsLocked(pkg); 3783 } 3784 3785 /** 3786 * Retrieve the statistics object for a particular service, creating 3787 * if needed. 3788 */ 3789 public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) { 3790 Uid u = getUidStatsLocked(uid); 3791 return u.getServiceStatsLocked(pkg, name); 3792 } 3793 3794 public void shutdownLocked() { 3795 writeLocked(); 3796 mShuttingDown = true; 3797 } 3798 3799 public void writeLocked() { 3800 if (mFile == null) { 3801 Slog.w("BatteryStats", "writeLocked: no file associated with this instance"); 3802 return; 3803 } 3804 3805 if (mShuttingDown) { 3806 return; 3807 } 3808 3809 try { 3810 FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite()); 3811 Parcel out = Parcel.obtain(); 3812 writeSummaryToParcel(out); 3813 stream.write(out.marshall()); 3814 out.recycle(); 3815 3816 stream.flush(); 3817 stream.close(); 3818 mFile.commit(); 3819 3820 mLastWriteTime = SystemClock.elapsedRealtime(); 3821 return; 3822 } catch (IOException e) { 3823 Slog.w("BatteryStats", "Error writing battery statistics", e); 3824 } 3825 mFile.rollback(); 3826 } 3827 3828 static byte[] readFully(FileInputStream stream) throws java.io.IOException { 3829 int pos = 0; 3830 int avail = stream.available(); 3831 byte[] data = new byte[avail]; 3832 while (true) { 3833 int amt = stream.read(data, pos, data.length-pos); 3834 //Log.i("foo", "Read " + amt + " bytes at " + pos 3835 // + " of avail " + data.length); 3836 if (amt <= 0) { 3837 //Log.i("foo", "**** FINISHED READING: pos=" + pos 3838 // + " len=" + data.length); 3839 return data; 3840 } 3841 pos += amt; 3842 avail = stream.available(); 3843 if (avail > data.length-pos) { 3844 byte[] newData = new byte[pos+avail]; 3845 System.arraycopy(data, 0, newData, 0, pos); 3846 data = newData; 3847 } 3848 } 3849 } 3850 3851 public void readLocked() { 3852 if (mFile == null) { 3853 Slog.w("BatteryStats", "readLocked: no file associated with this instance"); 3854 return; 3855 } 3856 3857 mUidStats.clear(); 3858 3859 try { 3860 File file = mFile.chooseForRead(); 3861 if (!file.exists()) { 3862 return; 3863 } 3864 FileInputStream stream = new FileInputStream(file); 3865 3866 byte[] raw = readFully(stream); 3867 Parcel in = Parcel.obtain(); 3868 in.unmarshall(raw, 0, raw.length); 3869 in.setDataPosition(0); 3870 stream.close(); 3871 3872 readSummaryFromParcel(in); 3873 } catch(java.io.IOException e) { 3874 Slog.e("BatteryStats", "Error reading battery statistics", e); 3875 } 3876 3877 addHistoryRecordLocked(SystemClock.elapsedRealtime(), HistoryItem.CMD_START); 3878 } 3879 3880 public int describeContents() { 3881 return 0; 3882 } 3883 3884 void readHistory(Parcel in) { 3885 mHistory = mHistoryEnd = mHistoryCache = null; 3886 mHistoryBaseTime = 0; 3887 long time; 3888 while ((time=in.readLong()) >= 0) { 3889 HistoryItem rec = new HistoryItem(time, in); 3890 addHistoryRecordLocked(rec); 3891 if (rec.time > mHistoryBaseTime) { 3892 mHistoryBaseTime = rec.time; 3893 } 3894 } 3895 3896 long oldnow = SystemClock.elapsedRealtime() - (5*60*100); 3897 if (oldnow > 0) { 3898 // If the system process has restarted, but not the entire 3899 // system, then the mHistoryBaseTime already accounts for 3900 // much of the elapsed time. We thus want to adjust it back, 3901 // to avoid large gaps in the data. We determine we are 3902 // in this case by arbitrarily saying it is so if at this 3903 // point in boot the elapsed time is already more than 5 seconds. 3904 mHistoryBaseTime -= oldnow; 3905 } 3906 } 3907 3908 void writeHistory(Parcel out) { 3909 HistoryItem rec = mHistory; 3910 while (rec != null) { 3911 if (rec.time >= 0) rec.writeToParcel(out, 0); 3912 rec = rec.next; 3913 } 3914 out.writeLong(-1); 3915 } 3916 3917 private void readSummaryFromParcel(Parcel in) { 3918 final int version = in.readInt(); 3919 if (version != VERSION) { 3920 Slog.w("BatteryStats", "readFromParcel: version got " + version 3921 + ", expected " + VERSION + "; erasing old stats"); 3922 return; 3923 } 3924 3925 readHistory(in); 3926 3927 mStartCount = in.readInt(); 3928 mBatteryUptime = in.readLong(); 3929 mBatteryLastUptime = in.readLong(); 3930 mBatteryRealtime = in.readLong(); 3931 mBatteryLastRealtime = in.readLong(); 3932 mUptime = in.readLong(); 3933 mLastUptime = in.readLong(); 3934 mRealtime = in.readLong(); 3935 mLastRealtime = in.readLong(); 3936 mDischargeUnplugLevel = in.readInt(); 3937 mDischargeCurrentLevel = in.readInt(); 3938 3939 mStartCount++; 3940 3941 mScreenOn = false; 3942 mScreenOnTimer.readSummaryFromParcelLocked(in); 3943 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3944 mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in); 3945 } 3946 mInputEventCounter.readSummaryFromParcelLocked(in); 3947 mPhoneOn = false; 3948 mPhoneOnTimer.readSummaryFromParcelLocked(in); 3949 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3950 mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in); 3951 } 3952 mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in); 3953 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3954 mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in); 3955 } 3956 mWifiOn = false; 3957 mWifiOnTimer.readSummaryFromParcelLocked(in); 3958 mWifiRunning = false; 3959 mWifiRunningTimer.readSummaryFromParcelLocked(in); 3960 mBluetoothOn = false; 3961 mBluetoothOnTimer.readSummaryFromParcelLocked(in); 3962 3963 int NKW = in.readInt(); 3964 if (NKW > 10000) { 3965 Slog.w(TAG, "File corrupt: too many kernel wake locks " + NKW); 3966 return; 3967 } 3968 for (int ikw = 0; ikw < NKW; ikw++) { 3969 if (in.readInt() != 0) { 3970 String kwltName = in.readString(); 3971 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in); 3972 } 3973 } 3974 3975 sNumSpeedSteps = in.readInt(); 3976 3977 final int NU = in.readInt(); 3978 if (NU > 10000) { 3979 Slog.w(TAG, "File corrupt: too many uids " + NU); 3980 return; 3981 } 3982 for (int iu = 0; iu < NU; iu++) { 3983 int uid = in.readInt(); 3984 Uid u = new Uid(uid); 3985 mUidStats.put(uid, u); 3986 3987 u.mWifiTurnedOn = false; 3988 if (in.readInt() != 0) { 3989 u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in); 3990 } 3991 u.mFullWifiLockOut = false; 3992 if (in.readInt() != 0) { 3993 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); 3994 } 3995 u.mScanWifiLockOut = false; 3996 if (in.readInt() != 0) { 3997 u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); 3998 } 3999 u.mWifiMulticastEnabled = false; 4000 if (in.readInt() != 0) { 4001 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in); 4002 } 4003 u.mAudioTurnedOn = false; 4004 if (in.readInt() != 0) { 4005 u.mAudioTurnedOnTimer.readSummaryFromParcelLocked(in); 4006 } 4007 u.mVideoTurnedOn = false; 4008 if (in.readInt() != 0) { 4009 u.mVideoTurnedOnTimer.readSummaryFromParcelLocked(in); 4010 } 4011 4012 if (in.readInt() != 0) { 4013 if (u.mUserActivityCounters == null) { 4014 u.initUserActivityLocked(); 4015 } 4016 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 4017 u.mUserActivityCounters[i].readSummaryFromParcelLocked(in); 4018 } 4019 } 4020 4021 int NW = in.readInt(); 4022 if (NW > 10000) { 4023 Slog.w(TAG, "File corrupt: too many wake locks " + NW); 4024 return; 4025 } 4026 for (int iw = 0; iw < NW; iw++) { 4027 String wlName = in.readString(); 4028 if (in.readInt() != 0) { 4029 u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in); 4030 } 4031 if (in.readInt() != 0) { 4032 u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in); 4033 } 4034 if (in.readInt() != 0) { 4035 u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in); 4036 } 4037 } 4038 4039 int NP = in.readInt(); 4040 if (NP > 10000) { 4041 Slog.w(TAG, "File corrupt: too many sensors " + NP); 4042 return; 4043 } 4044 for (int is = 0; is < NP; is++) { 4045 int seNumber = in.readInt(); 4046 if (in.readInt() != 0) { 4047 u.getSensorTimerLocked(seNumber, true) 4048 .readSummaryFromParcelLocked(in); 4049 } 4050 } 4051 4052 NP = in.readInt(); 4053 if (NP > 10000) { 4054 Slog.w(TAG, "File corrupt: too many processes " + NP); 4055 return; 4056 } 4057 for (int ip = 0; ip < NP; ip++) { 4058 String procName = in.readString(); 4059 Uid.Proc p = u.getProcessStatsLocked(procName); 4060 p.mUserTime = p.mLoadedUserTime = in.readLong(); 4061 p.mLastUserTime = in.readLong(); 4062 p.mSystemTime = p.mLoadedSystemTime = in.readLong(); 4063 p.mLastSystemTime = in.readLong(); 4064 p.mStarts = p.mLoadedStarts = in.readInt(); 4065 p.mLastStarts = in.readInt(); 4066 } 4067 4068 NP = in.readInt(); 4069 if (NP > 10000) { 4070 Slog.w(TAG, "File corrupt: too many packages " + NP); 4071 return; 4072 } 4073 for (int ip = 0; ip < NP; ip++) { 4074 String pkgName = in.readString(); 4075 Uid.Pkg p = u.getPackageStatsLocked(pkgName); 4076 p.mWakeups = p.mLoadedWakeups = in.readInt(); 4077 p.mLastWakeups = in.readInt(); 4078 final int NS = in.readInt(); 4079 for (int is = 0; is < NS; is++) { 4080 String servName = in.readString(); 4081 Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName); 4082 s.mStartTime = s.mLoadedStartTime = in.readLong(); 4083 s.mLastStartTime = in.readLong(); 4084 s.mStarts = s.mLoadedStarts = in.readInt(); 4085 s.mLastStarts = in.readInt(); 4086 s.mLaunches = s.mLoadedLaunches = in.readInt(); 4087 s.mLastLaunches = in.readInt(); 4088 } 4089 } 4090 4091 u.mLoadedTcpBytesReceived = in.readLong(); 4092 u.mLoadedTcpBytesSent = in.readLong(); 4093 } 4094 } 4095 4096 /** 4097 * Writes a summary of the statistics to a Parcel, in a format suitable to be written to 4098 * disk. This format does not allow a lossless round-trip. 4099 * 4100 * @param out the Parcel to be written to. 4101 */ 4102 public void writeSummaryToParcel(Parcel out) { 4103 final long NOW_SYS = SystemClock.uptimeMillis() * 1000; 4104 final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; 4105 final long NOW = getBatteryUptimeLocked(NOW_SYS); 4106 final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS); 4107 4108 out.writeInt(VERSION); 4109 4110 writeHistory(out); 4111 4112 out.writeInt(mStartCount); 4113 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED)); 4114 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT)); 4115 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED)); 4116 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT)); 4117 out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED)); 4118 out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT)); 4119 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED)); 4120 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT)); 4121 out.writeInt(mDischargeUnplugLevel); 4122 out.writeInt(mDischargeCurrentLevel); 4123 4124 4125 mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4126 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 4127 mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 4128 } 4129 mInputEventCounter.writeSummaryFromParcelLocked(out); 4130 mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4131 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 4132 mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 4133 } 4134 mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4135 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 4136 mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 4137 } 4138 mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4139 mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4140 mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4141 4142 out.writeInt(mKernelWakelockStats.size()); 4143 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 4144 Timer kwlt = ent.getValue(); 4145 if (kwlt != null) { 4146 out.writeInt(1); 4147 out.writeString(ent.getKey()); 4148 ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL); 4149 } else { 4150 out.writeInt(0); 4151 } 4152 } 4153 4154 out.writeInt(sNumSpeedSteps); 4155 final int NU = mUidStats.size(); 4156 out.writeInt(NU); 4157 for (int iu = 0; iu < NU; iu++) { 4158 out.writeInt(mUidStats.keyAt(iu)); 4159 Uid u = mUidStats.valueAt(iu); 4160 4161 if (u.mWifiTurnedOnTimer != null) { 4162 out.writeInt(1); 4163 u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4164 } else { 4165 out.writeInt(0); 4166 } 4167 if (u.mFullWifiLockTimer != null) { 4168 out.writeInt(1); 4169 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4170 } else { 4171 out.writeInt(0); 4172 } 4173 if (u.mScanWifiLockTimer != null) { 4174 out.writeInt(1); 4175 u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4176 } else { 4177 out.writeInt(0); 4178 } 4179 if (u.mWifiMulticastTimer != null) { 4180 out.writeInt(1); 4181 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4182 } else { 4183 out.writeInt(0); 4184 } 4185 if (u.mAudioTurnedOnTimer != null) { 4186 out.writeInt(1); 4187 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4188 } else { 4189 out.writeInt(0); 4190 } 4191 if (u.mVideoTurnedOnTimer != null) { 4192 out.writeInt(1); 4193 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4194 } else { 4195 out.writeInt(0); 4196 } 4197 4198 if (u.mUserActivityCounters == null) { 4199 out.writeInt(0); 4200 } else { 4201 out.writeInt(1); 4202 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 4203 u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out); 4204 } 4205 } 4206 4207 int NW = u.mWakelockStats.size(); 4208 out.writeInt(NW); 4209 if (NW > 0) { 4210 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent 4211 : u.mWakelockStats.entrySet()) { 4212 out.writeString(ent.getKey()); 4213 Uid.Wakelock wl = ent.getValue(); 4214 if (wl.mTimerFull != null) { 4215 out.writeInt(1); 4216 wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL); 4217 } else { 4218 out.writeInt(0); 4219 } 4220 if (wl.mTimerPartial != null) { 4221 out.writeInt(1); 4222 wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL); 4223 } else { 4224 out.writeInt(0); 4225 } 4226 if (wl.mTimerWindow != null) { 4227 out.writeInt(1); 4228 wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL); 4229 } else { 4230 out.writeInt(0); 4231 } 4232 } 4233 } 4234 4235 int NSE = u.mSensorStats.size(); 4236 out.writeInt(NSE); 4237 if (NSE > 0) { 4238 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent 4239 : u.mSensorStats.entrySet()) { 4240 out.writeInt(ent.getKey()); 4241 Uid.Sensor se = ent.getValue(); 4242 if (se.mTimer != null) { 4243 out.writeInt(1); 4244 se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4245 } else { 4246 out.writeInt(0); 4247 } 4248 } 4249 } 4250 4251 int NP = u.mProcessStats.size(); 4252 out.writeInt(NP); 4253 if (NP > 0) { 4254 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent 4255 : u.mProcessStats.entrySet()) { 4256 out.writeString(ent.getKey()); 4257 Uid.Proc ps = ent.getValue(); 4258 out.writeLong(ps.mUserTime); 4259 out.writeLong(ps.mUserTime - ps.mLoadedUserTime); 4260 out.writeLong(ps.mSystemTime); 4261 out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime); 4262 out.writeInt(ps.mStarts); 4263 out.writeInt(ps.mStarts - ps.mLoadedStarts); 4264 } 4265 } 4266 4267 NP = u.mPackageStats.size(); 4268 out.writeInt(NP); 4269 if (NP > 0) { 4270 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent 4271 : u.mPackageStats.entrySet()) { 4272 out.writeString(ent.getKey()); 4273 Uid.Pkg ps = ent.getValue(); 4274 out.writeInt(ps.mWakeups); 4275 out.writeInt(ps.mWakeups - ps.mLoadedWakeups); 4276 final int NS = ps.mServiceStats.size(); 4277 out.writeInt(NS); 4278 if (NS > 0) { 4279 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent 4280 : ps.mServiceStats.entrySet()) { 4281 out.writeString(sent.getKey()); 4282 BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue(); 4283 long time = ss.getStartTimeToNowLocked(NOW); 4284 out.writeLong(time); 4285 out.writeLong(time - ss.mLoadedStartTime); 4286 out.writeInt(ss.mStarts); 4287 out.writeInt(ss.mStarts - ss.mLoadedStarts); 4288 out.writeInt(ss.mLaunches); 4289 out.writeInt(ss.mLaunches - ss.mLoadedLaunches); 4290 } 4291 } 4292 } 4293 } 4294 4295 out.writeLong(u.getTcpBytesReceived(STATS_SINCE_CHARGED)); 4296 out.writeLong(u.getTcpBytesSent(STATS_SINCE_CHARGED)); 4297 } 4298 } 4299 4300 public void readFromParcel(Parcel in) { 4301 readFromParcelLocked(in); 4302 } 4303 4304 void readFromParcelLocked(Parcel in) { 4305 int magic = in.readInt(); 4306 if (magic != MAGIC) { 4307 throw new ParcelFormatException("Bad magic number"); 4308 } 4309 4310 readHistory(in); 4311 4312 mStartCount = in.readInt(); 4313 mBatteryUptime = in.readLong(); 4314 mBatteryLastUptime = in.readLong(); 4315 mBatteryRealtime = in.readLong(); 4316 mBatteryLastRealtime = in.readLong(); 4317 mScreenOn = false; 4318 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in); 4319 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 4320 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in); 4321 } 4322 mInputEventCounter = new Counter(mUnpluggables, in); 4323 mPhoneOn = false; 4324 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 4325 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 4326 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in); 4327 } 4328 mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables, in); 4329 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 4330 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in); 4331 } 4332 mWifiOn = false; 4333 mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 4334 mWifiRunning = false; 4335 mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 4336 mBluetoothOn = false; 4337 mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 4338 mUptime = in.readLong(); 4339 mUptimeStart = in.readLong(); 4340 mLastUptime = in.readLong(); 4341 mRealtime = in.readLong(); 4342 mRealtimeStart = in.readLong(); 4343 mLastRealtime = in.readLong(); 4344 mOnBattery = in.readInt() != 0; 4345 mOnBatteryInternal = false; // we are no longer really running. 4346 mTrackBatteryPastUptime = in.readLong(); 4347 mTrackBatteryUptimeStart = in.readLong(); 4348 mTrackBatteryPastRealtime = in.readLong(); 4349 mTrackBatteryRealtimeStart = in.readLong(); 4350 mUnpluggedBatteryUptime = in.readLong(); 4351 mUnpluggedBatteryRealtime = in.readLong(); 4352 mDischargeUnplugLevel = in.readInt(); 4353 mDischargeCurrentLevel = in.readInt(); 4354 mLastWriteTime = in.readLong(); 4355 4356 mMobileDataRx[STATS_LAST] = in.readLong(); 4357 mMobileDataRx[STATS_SINCE_UNPLUGGED] = -1; 4358 mMobileDataTx[STATS_LAST] = in.readLong(); 4359 mMobileDataTx[STATS_SINCE_UNPLUGGED] = -1; 4360 mTotalDataRx[STATS_LAST] = in.readLong(); 4361 mTotalDataRx[STATS_SINCE_UNPLUGGED] = -1; 4362 mTotalDataTx[STATS_LAST] = in.readLong(); 4363 mTotalDataTx[STATS_SINCE_UNPLUGGED] = -1; 4364 4365 mRadioDataUptime = in.readLong(); 4366 mRadioDataStart = -1; 4367 4368 mBluetoothPingCount = in.readInt(); 4369 mBluetoothPingStart = -1; 4370 4371 mKernelWakelockStats.clear(); 4372 int NKW = in.readInt(); 4373 for (int ikw = 0; ikw < NKW; ikw++) { 4374 if (in.readInt() != 0) { 4375 String wakelockName = in.readString(); 4376 in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel 4377 SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in); 4378 mKernelWakelockStats.put(wakelockName, kwlt); 4379 } 4380 } 4381 4382 mPartialTimers.clear(); 4383 mFullTimers.clear(); 4384 mWindowTimers.clear(); 4385 4386 sNumSpeedSteps = in.readInt(); 4387 4388 int numUids = in.readInt(); 4389 mUidStats.clear(); 4390 for (int i = 0; i < numUids; i++) { 4391 int uid = in.readInt(); 4392 Uid u = new Uid(uid); 4393 u.readFromParcelLocked(mUnpluggables, in); 4394 mUidStats.append(uid, u); 4395 } 4396 } 4397 4398 public void writeToParcel(Parcel out, int flags) { 4399 writeToParcelLocked(out, flags); 4400 } 4401 4402 @SuppressWarnings("unused") 4403 void writeToParcelLocked(Parcel out, int flags) { 4404 final long uSecUptime = SystemClock.uptimeMillis() * 1000; 4405 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 4406 final long batteryUptime = getBatteryUptimeLocked(uSecUptime); 4407 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 4408 4409 out.writeInt(MAGIC); 4410 4411 writeHistory(out); 4412 4413 out.writeInt(mStartCount); 4414 out.writeLong(mBatteryUptime); 4415 out.writeLong(mBatteryLastUptime); 4416 out.writeLong(mBatteryRealtime); 4417 out.writeLong(mBatteryLastRealtime); 4418 mScreenOnTimer.writeToParcel(out, batteryRealtime); 4419 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 4420 mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime); 4421 } 4422 mInputEventCounter.writeToParcel(out); 4423 mPhoneOnTimer.writeToParcel(out, batteryRealtime); 4424 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 4425 mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime); 4426 } 4427 mPhoneSignalScanningTimer.writeToParcel(out, batteryRealtime); 4428 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 4429 mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime); 4430 } 4431 mWifiOnTimer.writeToParcel(out, batteryRealtime); 4432 mWifiRunningTimer.writeToParcel(out, batteryRealtime); 4433 mBluetoothOnTimer.writeToParcel(out, batteryRealtime); 4434 out.writeLong(mUptime); 4435 out.writeLong(mUptimeStart); 4436 out.writeLong(mLastUptime); 4437 out.writeLong(mRealtime); 4438 out.writeLong(mRealtimeStart); 4439 out.writeLong(mLastRealtime); 4440 out.writeInt(mOnBattery ? 1 : 0); 4441 out.writeLong(batteryUptime); 4442 out.writeLong(mTrackBatteryUptimeStart); 4443 out.writeLong(batteryRealtime); 4444 out.writeLong(mTrackBatteryRealtimeStart); 4445 out.writeLong(mUnpluggedBatteryUptime); 4446 out.writeLong(mUnpluggedBatteryRealtime); 4447 out.writeInt(mDischargeUnplugLevel); 4448 out.writeInt(mDischargeCurrentLevel); 4449 out.writeLong(mLastWriteTime); 4450 4451 out.writeLong(getMobileTcpBytesReceived(STATS_SINCE_UNPLUGGED)); 4452 out.writeLong(getMobileTcpBytesSent(STATS_SINCE_UNPLUGGED)); 4453 out.writeLong(getTotalTcpBytesReceived(STATS_SINCE_UNPLUGGED)); 4454 out.writeLong(getTotalTcpBytesSent(STATS_SINCE_UNPLUGGED)); 4455 4456 // Write radio uptime for data 4457 out.writeLong(getRadioDataUptime()); 4458 4459 out.writeInt(getBluetoothPingCount()); 4460 4461 out.writeInt(mKernelWakelockStats.size()); 4462 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 4463 SamplingTimer kwlt = ent.getValue(); 4464 if (kwlt != null) { 4465 out.writeInt(1); 4466 out.writeString(ent.getKey()); 4467 Timer.writeTimerToParcel(out, kwlt, batteryRealtime); 4468 } else { 4469 out.writeInt(0); 4470 } 4471 } 4472 4473 out.writeInt(sNumSpeedSteps); 4474 4475 int size = mUidStats.size(); 4476 out.writeInt(size); 4477 for (int i = 0; i < size; i++) { 4478 out.writeInt(mUidStats.keyAt(i)); 4479 Uid uid = mUidStats.valueAt(i); 4480 4481 uid.writeToParcelLocked(out, batteryRealtime); 4482 } 4483 } 4484 4485 public static final Parcelable.Creator<BatteryStatsImpl> CREATOR = 4486 new Parcelable.Creator<BatteryStatsImpl>() { 4487 public BatteryStatsImpl createFromParcel(Parcel in) { 4488 return new BatteryStatsImpl(in); 4489 } 4490 4491 public BatteryStatsImpl[] newArray(int size) { 4492 return new BatteryStatsImpl[size]; 4493 } 4494 }; 4495 4496 public void dumpLocked(PrintWriter pw) { 4497 if (DEBUG) { 4498 Printer pr = new PrintWriterPrinter(pw); 4499 pr.println("*** Screen timer:"); 4500 mScreenOnTimer.logState(pr, " "); 4501 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 4502 pr.println("*** Screen brightness #" + i + ":"); 4503 mScreenBrightnessTimer[i].logState(pr, " "); 4504 } 4505 pr.println("*** Input event counter:"); 4506 mInputEventCounter.logState(pr, " "); 4507 pr.println("*** Phone timer:"); 4508 mPhoneOnTimer.logState(pr, " "); 4509 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 4510 pr.println("*** Signal strength #" + i + ":"); 4511 mPhoneSignalStrengthsTimer[i].logState(pr, " "); 4512 } 4513 pr.println("*** Signal scanning :"); 4514 mPhoneSignalScanningTimer.logState(pr, " "); 4515 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 4516 pr.println("*** Data connection type #" + i + ":"); 4517 mPhoneDataConnectionsTimer[i].logState(pr, " "); 4518 } 4519 pr.println("*** Wifi timer:"); 4520 mWifiOnTimer.logState(pr, " "); 4521 pr.println("*** WifiRunning timer:"); 4522 mWifiRunningTimer.logState(pr, " "); 4523 pr.println("*** Bluetooth timer:"); 4524 mBluetoothOnTimer.logState(pr, " "); 4525 } 4526 super.dumpLocked(pw); 4527 } 4528} 4529