BatteryStatsImpl.java revision 2e418428987132ea66533cbc05f9c526eb59519a
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 android.os.BatteryStats; 20import android.os.NetStat; 21import android.os.Parcel; 22import android.os.ParcelFormatException; 23import android.os.Parcelable; 24import android.os.Process; 25import android.os.SystemClock; 26import android.telephony.SignalStrength; 27import android.telephony.TelephonyManager; 28import android.util.Log; 29import android.util.PrintWriterPrinter; 30import android.util.Printer; 31import android.util.SparseArray; 32 33import java.io.BufferedReader; 34import java.io.File; 35import java.io.FileInputStream; 36import java.io.FileOutputStream; 37import java.io.FileReader; 38import java.io.IOException; 39import java.io.PrintWriter; 40import java.util.ArrayList; 41import java.util.HashMap; 42import java.util.Iterator; 43import java.util.Map; 44 45/** 46 * All information we are collecting about things that can happen that impact 47 * battery life. All times are represented in microseconds except where indicated 48 * otherwise. 49 */ 50public final class BatteryStatsImpl extends BatteryStats { 51 private static final String TAG = "BatteryStatsImpl"; 52 private static final boolean DEBUG = false; 53 54 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data 55 private static final int MAGIC = 0xBA757475; // 'BATSTATS' 56 57 // Current on-disk Parcel version 58 private static final int VERSION = 39; 59 60 private final File mFile; 61 private final File mBackupFile; 62 63 /** 64 * The statistics we have collected organized by uids. 65 */ 66 final SparseArray<BatteryStatsImpl.Uid> mUidStats = 67 new SparseArray<BatteryStatsImpl.Uid>(); 68 69 // A set of pools of currently active timers. When a timer is queried, we will divide the 70 // elapsed time by the number of active timers to arrive at that timer's share of the time. 71 // In order to do this, we must refresh each timer whenever the number of active timers 72 // changes. 73 final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>(); 74 final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>(); 75 final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>(); 76 final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers 77 = new SparseArray<ArrayList<StopwatchTimer>>(); 78 79 // These are the objects that will want to do something when the device 80 // is unplugged from power. 81 final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>(); 82 83 int mStartCount; 84 85 long mBatteryUptime; 86 long mBatteryLastUptime; 87 long mBatteryRealtime; 88 long mBatteryLastRealtime; 89 90 long mUptime; 91 long mUptimeStart; 92 long mLastUptime; 93 long mRealtime; 94 long mRealtimeStart; 95 long mLastRealtime; 96 97 boolean mScreenOn; 98 StopwatchTimer mScreenOnTimer; 99 100 int mScreenBrightnessBin = -1; 101 final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS]; 102 103 Counter mInputEventCounter; 104 105 boolean mPhoneOn; 106 StopwatchTimer mPhoneOnTimer; 107 108 boolean mAudioOn; 109 StopwatchTimer mAudioOnTimer; 110 111 boolean mVideoOn; 112 StopwatchTimer mVideoOnTimer; 113 114 int mPhoneSignalStrengthBin = -1; 115 final StopwatchTimer[] mPhoneSignalStrengthsTimer = 116 new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS]; 117 118 int mPhoneDataConnectionType = -1; 119 final StopwatchTimer[] mPhoneDataConnectionsTimer = 120 new StopwatchTimer[NUM_DATA_CONNECTION_TYPES]; 121 122 boolean mWifiOn; 123 StopwatchTimer mWifiOnTimer; 124 int mWifiOnUid = -1; 125 126 boolean mWifiRunning; 127 StopwatchTimer mWifiRunningTimer; 128 129 boolean mBluetoothOn; 130 StopwatchTimer mBluetoothOnTimer; 131 132 /** 133 * These provide time bases that discount the time the device is plugged 134 * in to power. 135 */ 136 boolean mOnBattery; 137 boolean mOnBatteryInternal; 138 long mTrackBatteryPastUptime; 139 long mTrackBatteryUptimeStart; 140 long mTrackBatteryPastRealtime; 141 long mTrackBatteryRealtimeStart; 142 143 long mUnpluggedBatteryUptime; 144 long mUnpluggedBatteryRealtime; 145 146 /* 147 * These keep track of battery levels (1-100) at the last plug event and the last unplug event. 148 */ 149 int mDischargeStartLevel; 150 int mDischargeCurrentLevel; 151 152 long mLastWriteTime = 0; // Milliseconds 153 154 // Mobile data transferred while on battery 155 private long[] mMobileDataTx = new long[4]; 156 private long[] mMobileDataRx = new long[4]; 157 private long[] mTotalDataTx = new long[4]; 158 private long[] mTotalDataRx = new long[4]; 159 160 private long mRadioDataUptime; 161 private long mRadioDataStart; 162 163 /* 164 * Holds a SamplingTimer associated with each kernel wakelock name being tracked. 165 */ 166 private final HashMap<String, SamplingTimer> mKernelWakelockStats = 167 new HashMap<String, SamplingTimer>(); 168 169 public Map<String, ? extends SamplingTimer> getKernelWakelockStats() { 170 return mKernelWakelockStats; 171 } 172 173 private static int sKernelWakelockUpdateVersion = 0; 174 175 private static final int[] PROC_WAKELOCKS_FORMAT = new int[] { 176 Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name 177 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count 178 Process.PROC_TAB_TERM, 179 Process.PROC_TAB_TERM, 180 Process.PROC_TAB_TERM, 181 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime 182 }; 183 184 private final String[] mProcWakelocksName = new String[3]; 185 private final long[] mProcWakelocksData = new long[3]; 186 187 /* 188 * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added 189 * to mKernelWakelockStats. 190 */ 191 private final Map<String, KernelWakelockStats> mProcWakelockFileStats = 192 new HashMap<String, KernelWakelockStats>(); 193 194 // For debugging 195 public BatteryStatsImpl() { 196 mFile = mBackupFile = null; 197 } 198 199 public static interface Unpluggable { 200 void unplug(long batteryUptime, long batteryRealtime); 201 void plug(long batteryUptime, long batteryRealtime); 202 } 203 204 /** 205 * State for keeping track of counting information. 206 */ 207 public static final class Counter extends BatteryStats.Counter implements Unpluggable { 208 int mCount; 209 int mLoadedCount; 210 int mLastCount; 211 int mUnpluggedCount; 212 int mPluggedCount; 213 214 Counter(ArrayList<Unpluggable> unpluggables, Parcel in) { 215 mPluggedCount = mCount = in.readInt(); 216 mLoadedCount = in.readInt(); 217 mLastCount = in.readInt(); 218 mUnpluggedCount = in.readInt(); 219 unpluggables.add(this); 220 } 221 222 Counter(ArrayList<Unpluggable> unpluggables) { 223 unpluggables.add(this); 224 } 225 226 public void writeToParcel(Parcel out) { 227 out.writeInt(mCount); 228 out.writeInt(mLoadedCount); 229 out.writeInt(mLastCount); 230 out.writeInt(mUnpluggedCount); 231 } 232 233 public void unplug(long batteryUptime, long batteryRealtime) { 234 mUnpluggedCount = mCount = mPluggedCount; 235 } 236 237 public void plug(long batteryUptime, long batteryRealtime) { 238 mPluggedCount = mCount; 239 } 240 241 /** 242 * Writes a possibly null Counter to a Parcel. 243 * 244 * @param out the Parcel to be written to. 245 * @param counter a Counter, or null. 246 */ 247 public static void writeCounterToParcel(Parcel out, Counter counter) { 248 if (counter == null) { 249 out.writeInt(0); // indicates null 250 return; 251 } 252 out.writeInt(1); // indicates non-null 253 254 counter.writeToParcel(out); 255 } 256 257 @Override 258 public int getCountLocked(int which) { 259 int val; 260 if (which == STATS_LAST) { 261 val = mLastCount; 262 } else { 263 val = mCount; 264 if (which == STATS_UNPLUGGED) { 265 val -= mUnpluggedCount; 266 } else if (which != STATS_TOTAL) { 267 val -= mLoadedCount; 268 } 269 } 270 271 return val; 272 } 273 274 public void logState(Printer pw, String prefix) { 275 pw.println(prefix + "mCount=" + mCount 276 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 277 + " mUnpluggedCount=" + mUnpluggedCount 278 + " mPluggedCount=" + mPluggedCount); 279 } 280 281 void stepLocked() { 282 mCount++; 283 } 284 285 void writeSummaryFromParcelLocked(Parcel out) { 286 out.writeInt(mCount); 287 out.writeInt(mCount - mLoadedCount); 288 } 289 290 void readSummaryFromParcelLocked(Parcel in) { 291 mCount = mLoadedCount = in.readInt(); 292 mLastCount = in.readInt(); 293 mUnpluggedCount = mPluggedCount = mCount; 294 } 295 } 296 297 /** 298 * State for keeping track of timing information. 299 */ 300 public static abstract class Timer extends BatteryStats.Timer implements Unpluggable { 301 final int mType; 302 303 304 int mCount; 305 int mLoadedCount; 306 int mLastCount; 307 int mUnpluggedCount; 308 309 // Times are in microseconds for better accuracy when dividing by the 310 // lock count, and are in "battery realtime" units. 311 312 /** 313 * The total time we have accumulated since the start of the original 314 * boot, to the last time something interesting happened in the 315 * current run. 316 */ 317 long mTotalTime; 318 319 /** 320 * The total time we loaded for the previous runs. Subtract this from 321 * mTotalTime to find the time for the current run of the system. 322 */ 323 long mLoadedTime; 324 325 /** 326 * The run time of the last run of the system, as loaded from the 327 * saved data. 328 */ 329 long mLastTime; 330 331 /** 332 * The value of mTotalTime when unplug() was last called. Subtract 333 * this from mTotalTime to find the time since the last unplug from 334 * power. 335 */ 336 long mUnpluggedTime; 337 338 /** 339 * Constructs from a parcel. 340 * @param type 341 * @param unpluggables 342 * @param powerType 343 * @param in 344 */ 345 Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) { 346 mType = type; 347 348 mCount = in.readInt(); 349 mLoadedCount = in.readInt(); 350 mLastCount = in.readInt(); 351 mUnpluggedCount = in.readInt(); 352 mTotalTime = in.readLong(); 353 mLoadedTime = in.readLong(); 354 mLastTime = in.readLong(); 355 mUnpluggedTime = in.readLong(); 356 unpluggables.add(this); 357 } 358 359 Timer(int type, ArrayList<Unpluggable> unpluggables) { 360 mType = type; 361 unpluggables.add(this); 362 } 363 364 protected abstract long computeRunTimeLocked(long curBatteryRealtime); 365 366 protected abstract int computeCurrentCountLocked(); 367 368 369 public void writeToParcel(Parcel out, long batteryRealtime) { 370 out.writeInt(mCount); 371 out.writeInt(mLoadedCount); 372 out.writeInt(mLastCount); 373 out.writeInt(mUnpluggedCount); 374 out.writeLong(computeRunTimeLocked(batteryRealtime)); 375 out.writeLong(mLoadedTime); 376 out.writeLong(mLastTime); 377 out.writeLong(mUnpluggedTime); 378 } 379 380 public void unplug(long batteryUptime, long batteryRealtime) { 381 if (DEBUG && mType < 0) { 382 Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime 383 + " old mUnpluggedTime=" + mUnpluggedTime 384 + " old mUnpluggedCount=" + mUnpluggedCount); 385 } 386 mUnpluggedTime = computeRunTimeLocked(batteryRealtime); 387 mUnpluggedCount = mCount; 388 if (DEBUG && mType < 0) { 389 Log.v(TAG, "unplug #" + mType 390 + ": new mUnpluggedTime=" + mUnpluggedTime 391 + " new mUnpluggedCount=" + mUnpluggedCount); 392 } 393 } 394 395 public void plug(long batteryUptime, long batteryRealtime) { 396 if (DEBUG && mType < 0) { 397 Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime 398 + " old mTotalTime=" + mTotalTime); 399 } 400 mTotalTime = computeRunTimeLocked(batteryRealtime); 401 mCount = computeCurrentCountLocked(); 402 if (DEBUG && mType < 0) { 403 Log.v(TAG, "plug #" + mType 404 + ": new mTotalTime=" + mTotalTime); 405 } 406 } 407 408 /** 409 * Writes a possibly null Timer to a Parcel. 410 * 411 * @param out the Parcel to be written to. 412 * @param timer a Timer, or null. 413 */ 414 public static void writeTimerToParcel(Parcel out, Timer timer, 415 long batteryRealtime) { 416 if (timer == null) { 417 out.writeInt(0); // indicates null 418 return; 419 } 420 out.writeInt(1); // indicates non-null 421 422 timer.writeToParcel(out, batteryRealtime); 423 } 424 425 @Override 426 public long getTotalTimeLocked(long batteryRealtime, int which) { 427 long val; 428 if (which == STATS_LAST) { 429 val = mLastTime; 430 } else { 431 val = computeRunTimeLocked(batteryRealtime); 432 if (which == STATS_UNPLUGGED) { 433 val -= mUnpluggedTime; 434 } else if (which != STATS_TOTAL) { 435 val -= mLoadedTime; 436 } 437 } 438 439 return val; 440 } 441 442 @Override 443 public int getCountLocked(int which) { 444 int val; 445 if (which == STATS_LAST) { 446 val = mLastCount; 447 } else { 448 val = computeCurrentCountLocked(); 449 if (which == STATS_UNPLUGGED) { 450 val -= mUnpluggedCount; 451 } else if (which != STATS_TOTAL) { 452 val -= mLoadedCount; 453 } 454 } 455 456 return val; 457 } 458 459 public void logState(Printer pw, String prefix) { 460 pw.println(prefix + " mCount=" + mCount 461 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 462 + " mUnpluggedCount=" + mUnpluggedCount); 463 pw.println(prefix + "mTotalTime=" + mTotalTime 464 + " mLoadedTime=" + mLoadedTime); 465 pw.println(prefix + "mLastTime=" + mLastTime 466 + " mUnpluggedTime=" + mUnpluggedTime); 467 } 468 469 470 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 471 long runTime = computeRunTimeLocked(batteryRealtime); 472 // Divide by 1000 for backwards compatibility 473 out.writeLong((runTime + 500) / 1000); 474 out.writeLong(((runTime - mLoadedTime) + 500) / 1000); 475 out.writeInt(mCount); 476 out.writeInt(mCount - mLoadedCount); 477 } 478 479 void readSummaryFromParcelLocked(Parcel in) { 480 // Multiply by 1000 for backwards compatibility 481 mTotalTime = mLoadedTime = in.readLong() * 1000; 482 mLastTime = in.readLong() * 1000; 483 mUnpluggedTime = mTotalTime; 484 mCount = mLoadedCount = in.readInt(); 485 mLastCount = in.readInt(); 486 mUnpluggedCount = mCount; 487 } 488 } 489 490 public static final class SamplingTimer extends Timer { 491 492 /** 493 * The most recent reported count from /proc/wakelocks. 494 */ 495 int mCurrentReportedCount; 496 497 /** 498 * The reported count from /proc/wakelocks when unplug() was last 499 * called. 500 */ 501 int mUnpluggedReportedCount; 502 503 /** 504 * The most recent reported total_time from /proc/wakelocks. 505 */ 506 long mCurrentReportedTotalTime; 507 508 509 /** 510 * The reported total_time from /proc/wakelocks when unplug() was last 511 * called. 512 */ 513 long mUnpluggedReportedTotalTime; 514 515 /** 516 * Whether we are currently in a discharge cycle. 517 */ 518 boolean mInDischarge; 519 520 /** 521 * Whether we are currently recording reported values. 522 */ 523 boolean mTrackingReportedValues; 524 525 /* 526 * A sequnce counter, incremented once for each update of the stats. 527 */ 528 int mUpdateVersion; 529 530 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) { 531 super(0, unpluggables, in); 532 mCurrentReportedCount = in.readInt(); 533 mUnpluggedReportedCount = in.readInt(); 534 mCurrentReportedTotalTime = in.readLong(); 535 mUnpluggedReportedTotalTime = in.readLong(); 536 mTrackingReportedValues = in.readInt() == 1; 537 mInDischarge = inDischarge; 538 } 539 540 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, 541 boolean trackReportedValues) { 542 super(0, unpluggables); 543 mTrackingReportedValues = trackReportedValues; 544 mInDischarge = inDischarge; 545 } 546 547 public void setStale() { 548 mTrackingReportedValues = false; 549 mUnpluggedReportedTotalTime = 0; 550 mUnpluggedReportedCount = 0; 551 } 552 553 public void setUpdateVersion(int version) { 554 mUpdateVersion = version; 555 } 556 557 public int getUpdateVersion() { 558 return mUpdateVersion; 559 } 560 561 public void updateCurrentReportedCount(int count) { 562 if (mInDischarge && mUnpluggedReportedCount == 0) { 563 // Updating the reported value for the first time. 564 mUnpluggedReportedCount = count; 565 // If we are receiving an update update mTrackingReportedValues; 566 mTrackingReportedValues = true; 567 } 568 mCurrentReportedCount = count; 569 } 570 571 public void updateCurrentReportedTotalTime(long totalTime) { 572 if (mInDischarge && mUnpluggedReportedTotalTime == 0) { 573 // Updating the reported value for the first time. 574 mUnpluggedReportedTotalTime = totalTime; 575 // If we are receiving an update update mTrackingReportedValues; 576 mTrackingReportedValues = true; 577 } 578 mCurrentReportedTotalTime = totalTime; 579 } 580 581 public void unplug(long batteryUptime, long batteryRealtime) { 582 super.unplug(batteryUptime, batteryRealtime); 583 if (mTrackingReportedValues) { 584 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime; 585 mUnpluggedReportedCount = mCurrentReportedCount; 586 } 587 mInDischarge = true; 588 } 589 590 public void plug(long batteryUptime, long batteryRealtime) { 591 super.plug(batteryUptime, batteryRealtime); 592 mInDischarge = false; 593 } 594 595 public void logState(Printer pw, String prefix) { 596 super.logState(pw, prefix); 597 pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount 598 + " mUnpluggedReportedCount=" + mUnpluggedReportedCount 599 + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime 600 + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime); 601 } 602 603 protected long computeRunTimeLocked(long curBatteryRealtime) { 604 return mTotalTime + (mInDischarge && mTrackingReportedValues 605 ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0); 606 } 607 608 protected int computeCurrentCountLocked() { 609 return mCount + (mInDischarge && mTrackingReportedValues 610 ? mCurrentReportedCount - mUnpluggedReportedCount : 0); 611 } 612 613 public void writeToParcel(Parcel out, long batteryRealtime) { 614 super.writeToParcel(out, batteryRealtime); 615 out.writeInt(mCurrentReportedCount); 616 out.writeInt(mUnpluggedReportedCount); 617 out.writeLong(mCurrentReportedTotalTime); 618 out.writeLong(mUnpluggedReportedTotalTime); 619 out.writeInt(mTrackingReportedValues ? 1 : 0); 620 } 621 622 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 623 super.writeSummaryFromParcelLocked(out, batteryRealtime); 624 out.writeLong(mCurrentReportedTotalTime); 625 out.writeInt(mCurrentReportedCount); 626 out.writeInt(mTrackingReportedValues ? 1 : 0); 627 } 628 629 void readSummaryFromParcelLocked(Parcel in) { 630 super.readSummaryFromParcelLocked(in); 631 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong(); 632 mUnpluggedReportedCount = mCurrentReportedCount = in.readInt(); 633 mTrackingReportedValues = in.readInt() == 1; 634 } 635 } 636 637 /** 638 * State for keeping track of timing information. 639 */ 640 public static final class StopwatchTimer extends Timer { 641 final ArrayList<StopwatchTimer> mTimerPool; 642 int mNesting; 643 644 645 /** 646 * The last time at which we updated the timer. If mNesting is > 0, 647 * subtract this from the current battery time to find the amount of 648 * time we have been running since we last computed an update. 649 */ 650 long mUpdateTime; 651 652 /** 653 * The total time at which the timer was acquired, to determine if 654 * was actually held for an interesting duration. 655 */ 656 long mAcquireTime; 657 658 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, 659 ArrayList<Unpluggable> unpluggables, Parcel in) { 660 super(type, unpluggables, in); 661 mTimerPool = timerPool; 662 mUpdateTime = in.readLong(); 663 } 664 665 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, 666 ArrayList<Unpluggable> unpluggables) { 667 super(type, unpluggables); 668 mTimerPool = timerPool; 669 } 670 671 public void writeToParcel(Parcel out, long batteryRealtime) { 672 super.writeToParcel(out, batteryRealtime); 673 out.writeLong(mUpdateTime); 674 } 675 676 public void plug(long batteryUptime, long batteryRealtime) { 677 if (mNesting > 0) { 678 if (DEBUG && mType < 0) { 679 Log.v(TAG, "old mUpdateTime=" + mUpdateTime); 680 } 681 super.plug(batteryUptime, batteryRealtime); 682 mUpdateTime = batteryRealtime; 683 if (DEBUG && mType < 0) { 684 Log.v(TAG, "new mUpdateTime=" + mUpdateTime); 685 } 686 } 687 } 688 689 public void logState(Printer pw, String prefix) { 690 super.logState(pw, prefix); 691 pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime 692 + " mAcquireTime=" + mAcquireTime); 693 } 694 695 void startRunningLocked(BatteryStatsImpl stats) { 696 if (mNesting++ == 0) { 697 mUpdateTime = stats.getBatteryRealtimeLocked( 698 SystemClock.elapsedRealtime() * 1000); 699 if (mTimerPool != null) { 700 // Accumulate time to all currently active timers before adding 701 // this new one to the pool. 702 refreshTimersLocked(stats, mTimerPool); 703 // Add this timer to the active pool 704 mTimerPool.add(this); 705 } 706 // Increment the count 707 mCount++; 708 mAcquireTime = mTotalTime; 709 if (DEBUG && mType < 0) { 710 Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime 711 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 712 + " mAcquireTime=" + mAcquireTime); 713 } 714 } 715 } 716 717 void stopRunningLocked(BatteryStatsImpl stats) { 718 // Ignore attempt to stop a timer that isn't running 719 if (mNesting == 0) { 720 return; 721 } 722 if (--mNesting == 0) { 723 if (mTimerPool != null) { 724 // Accumulate time to all active counters, scaled by the total 725 // active in the pool, before taking this one out of the pool. 726 refreshTimersLocked(stats, mTimerPool); 727 // Remove this timer from the active pool 728 mTimerPool.remove(this); 729 } else { 730 final long realtime = SystemClock.elapsedRealtime() * 1000; 731 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 732 mNesting = 1; 733 mTotalTime = computeRunTimeLocked(batteryRealtime); 734 mNesting = 0; 735 } 736 737 if (DEBUG && mType < 0) { 738 Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime 739 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 740 + " mAcquireTime=" + mAcquireTime); 741 } 742 743 if (mTotalTime == mAcquireTime) { 744 // If there was no change in the time, then discard this 745 // count. A somewhat cheezy strategy, but hey. 746 mCount--; 747 } 748 } 749 } 750 751 // Update the total time for all other running Timers with the same type as this Timer 752 // due to a change in timer count 753 private static void refreshTimersLocked(final BatteryStatsImpl stats, 754 final ArrayList<StopwatchTimer> pool) { 755 final long realtime = SystemClock.elapsedRealtime() * 1000; 756 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 757 final int N = pool.size(); 758 for (int i=N-1; i>= 0; i--) { 759 final StopwatchTimer t = pool.get(i); 760 long heldTime = batteryRealtime - t.mUpdateTime; 761 if (heldTime > 0) { 762 t.mTotalTime += heldTime / N; 763 } 764 t.mUpdateTime = batteryRealtime; 765 } 766 } 767 768 @Override 769 protected long computeRunTimeLocked(long curBatteryRealtime) { 770 return mTotalTime + (mNesting > 0 771 ? (curBatteryRealtime - mUpdateTime) 772 / (mTimerPool != null ? mTimerPool.size() : 1) 773 : 0); 774 } 775 776 @Override 777 protected int computeCurrentCountLocked() { 778 return mCount; 779 } 780 781 void readSummaryFromParcelLocked(Parcel in) { 782 super.readSummaryFromParcelLocked(in); 783 mNesting = 0; 784 } 785 } 786 787 private final Map<String, KernelWakelockStats> readKernelWakelockStats() { 788 789 byte[] buffer = new byte[4096]; 790 int len; 791 792 try { 793 FileInputStream is = new FileInputStream("/proc/wakelocks"); 794 len = is.read(buffer); 795 is.close(); 796 797 if (len > 0) { 798 int i; 799 for (i=0; i<len; i++) { 800 if (buffer[i] == '\0') { 801 len = i; 802 break; 803 } 804 } 805 } 806 } catch (java.io.FileNotFoundException e) { 807 return null; 808 } catch (java.io.IOException e) { 809 return null; 810 } 811 812 return parseProcWakelocks(buffer, len); 813 } 814 815 private final Map<String, KernelWakelockStats> parseProcWakelocks( 816 byte[] wlBuffer, int len) { 817 String name; 818 int count; 819 long totalTime; 820 int startIndex, endIndex; 821 int numUpdatedWlNames = 0; 822 823 // Advance past the first line. 824 int i; 825 for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++); 826 startIndex = endIndex = i + 1; 827 828 synchronized(this) { 829 Map<String, KernelWakelockStats> m = mProcWakelockFileStats; 830 831 sKernelWakelockUpdateVersion++; 832 while (endIndex < len) { 833 for (endIndex=startIndex; 834 endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0'; 835 endIndex++); 836 endIndex++; // endIndex is an exclusive upper bound. 837 838 String[] nameStringArray = mProcWakelocksName; 839 long[] wlData = mProcWakelocksData; 840 Process.parseProcLine(wlBuffer, startIndex, endIndex, PROC_WAKELOCKS_FORMAT, 841 nameStringArray, wlData, null); 842 843 name = nameStringArray[0]; 844 count = (int) wlData[1]; 845 // convert nanoseconds to microseconds with rounding. 846 totalTime = (wlData[2] + 500) / 1000; 847 848 if (name.length() > 0) { 849 if (!m.containsKey(name)) { 850 m.put(name, new KernelWakelockStats(count, totalTime, 851 sKernelWakelockUpdateVersion)); 852 numUpdatedWlNames++; 853 } else { 854 KernelWakelockStats kwlStats = m.get(name); 855 if (kwlStats.mVersion == sKernelWakelockUpdateVersion) { 856 kwlStats.mCount += count; 857 kwlStats.mTotalTime += totalTime; 858 } else { 859 kwlStats.mCount = count; 860 kwlStats.mTotalTime = totalTime; 861 kwlStats.mVersion = sKernelWakelockUpdateVersion; 862 numUpdatedWlNames++; 863 } 864 } 865 } 866 startIndex = endIndex; 867 } 868 869 if (m.size() != numUpdatedWlNames) { 870 // Don't report old data. 871 Iterator<KernelWakelockStats> itr = m.values().iterator(); 872 while (itr.hasNext()) { 873 if (itr.next().mVersion != sKernelWakelockUpdateVersion) { 874 itr.remove(); 875 } 876 } 877 } 878 return m; 879 } 880 } 881 882 private class KernelWakelockStats { 883 public int mCount; 884 public long mTotalTime; 885 public int mVersion; 886 887 KernelWakelockStats(int count, long totalTime, int version) { 888 mCount = count; 889 mTotalTime = totalTime; 890 mVersion = version; 891 } 892 } 893 894 /* 895 * Get the KernelWakelockTimer associated with name, and create a new one if one 896 * doesn't already exist. 897 */ 898 public SamplingTimer getKernelWakelockTimerLocked(String name) { 899 SamplingTimer kwlt = mKernelWakelockStats.get(name); 900 if (kwlt == null) { 901 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 902 true /* track reported values */); 903 mKernelWakelockStats.put(name, kwlt); 904 } 905 return kwlt; 906 } 907 908 private void doDataPlug(long[] dataTransfer, long currentBytes) { 909 dataTransfer[STATS_LAST] = dataTransfer[STATS_UNPLUGGED]; 910 dataTransfer[STATS_UNPLUGGED] = -1; 911 } 912 913 private void doDataUnplug(long[] dataTransfer, long currentBytes) { 914 dataTransfer[STATS_UNPLUGGED] = currentBytes; 915 } 916 917 private long getCurrentRadioDataUptimeMs() { 918 try { 919 File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms"); 920 if (!awakeTimeFile.exists()) return 0; 921 BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile)); 922 String line = br.readLine(); 923 br.close(); 924 return Long.parseLong(line); 925 } catch (NumberFormatException nfe) { 926 // Nothing 927 } catch (IOException ioe) { 928 // Nothing 929 } 930 return 0; 931 } 932 933 public long getRadioDataUptimeMs() { 934 if (mRadioDataStart == -1) { 935 return mRadioDataUptime; 936 } else { 937 return getCurrentRadioDataUptimeMs() - mRadioDataStart; 938 } 939 } 940 941 public void doUnplug(long batteryUptime, long batteryRealtime) { 942 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 943 Uid u = mUidStats.valueAt(iu); 944 u.mStartedTcpBytesReceived = NetStat.getUidRxBytes(u.mUid); 945 u.mStartedTcpBytesSent = NetStat.getUidTxBytes(u.mUid); 946 u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived; 947 u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent; 948 } 949 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 950 mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime); 951 } 952 // Track total mobile data 953 doDataUnplug(mMobileDataRx, NetStat.getMobileRxBytes()); 954 doDataUnplug(mMobileDataTx, NetStat.getMobileTxBytes()); 955 doDataUnplug(mTotalDataRx, NetStat.getTotalRxBytes()); 956 doDataUnplug(mTotalDataTx, NetStat.getTotalTxBytes()); 957 // Track radio awake time 958 mRadioDataStart = getCurrentRadioDataUptimeMs(); 959 mRadioDataUptime = 0; 960 } 961 962 public void doPlug(long batteryUptime, long batteryRealtime) { 963 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 964 Uid u = mUidStats.valueAt(iu); 965 if (u.mStartedTcpBytesReceived >= 0) { 966 u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived(); 967 u.mStartedTcpBytesReceived = -1; 968 } 969 if (u.mStartedTcpBytesSent >= 0) { 970 u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent(); 971 u.mStartedTcpBytesSent = -1; 972 } 973 } 974 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 975 mUnpluggables.get(i).plug(batteryUptime, batteryRealtime); 976 } 977 doDataPlug(mMobileDataRx, NetStat.getMobileRxBytes()); 978 doDataPlug(mMobileDataTx, NetStat.getMobileTxBytes()); 979 doDataPlug(mTotalDataRx, NetStat.getTotalRxBytes()); 980 doDataPlug(mTotalDataTx, NetStat.getTotalTxBytes()); 981 // Track radio awake time 982 mRadioDataUptime = getRadioDataUptimeMs(); 983 mRadioDataStart = -1; 984 } 985 986 public void noteStartGps(int uid) { 987 getUidStatsLocked(uid).noteStartGps(); 988 } 989 990 public void noteStopGps(int uid) { 991 getUidStatsLocked(uid).noteStopGps(); 992 } 993 994 public void noteScreenOnLocked() { 995 if (!mScreenOn) { 996 mScreenOn = true; 997 mScreenOnTimer.startRunningLocked(this); 998 if (mScreenBrightnessBin >= 0) { 999 mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this); 1000 } 1001 } 1002 } 1003 1004 public void noteScreenOffLocked() { 1005 if (mScreenOn) { 1006 mScreenOn = false; 1007 mScreenOnTimer.stopRunningLocked(this); 1008 if (mScreenBrightnessBin >= 0) { 1009 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this); 1010 } 1011 } 1012 } 1013 1014 public void noteScreenBrightnessLocked(int brightness) { 1015 // Bin the brightness. 1016 int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS); 1017 if (bin < 0) bin = 0; 1018 else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1; 1019 if (mScreenBrightnessBin != bin) { 1020 if (mScreenOn) { 1021 if (mScreenBrightnessBin >= 0) { 1022 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this); 1023 } 1024 mScreenBrightnessTimer[bin].startRunningLocked(this); 1025 } 1026 mScreenBrightnessBin = bin; 1027 } 1028 } 1029 1030 public void noteInputEventLocked() { 1031 mInputEventCounter.stepLocked(); 1032 } 1033 1034 public void noteUserActivityLocked(int uid, int event) { 1035 getUidStatsLocked(uid).noteUserActivityLocked(event); 1036 } 1037 1038 public void notePhoneOnLocked() { 1039 if (!mPhoneOn) { 1040 mPhoneOn = true; 1041 mPhoneOnTimer.startRunningLocked(this); 1042 } 1043 } 1044 1045 public void notePhoneOffLocked() { 1046 if (mPhoneOn) { 1047 mPhoneOn = false; 1048 mPhoneOnTimer.stopRunningLocked(this); 1049 } 1050 } 1051 1052 public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) { 1053 // Bin the strength. 1054 int bin; 1055 1056 if (!signalStrength.isGsm()) { 1057 int dBm = signalStrength.getCdmaDbm(); 1058 if (dBm >= -75) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1059 else if (dBm >= -85) bin = SIGNAL_STRENGTH_GREAT; 1060 else if (dBm >= -95) bin = SIGNAL_STRENGTH_GOOD; 1061 else if (dBm >= -100) bin = SIGNAL_STRENGTH_MODERATE; 1062 else bin = SIGNAL_STRENGTH_POOR; 1063 } else { 1064 int asu = signalStrength.getGsmSignalStrength(); 1065 if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1066 else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT; 1067 else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD; 1068 else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE; 1069 else bin = SIGNAL_STRENGTH_POOR; 1070 } 1071 if (mPhoneSignalStrengthBin != bin) { 1072 if (mPhoneSignalStrengthBin >= 0) { 1073 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this); 1074 } 1075 mPhoneSignalStrengthBin = bin; 1076 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this); 1077 } 1078 } 1079 1080 public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) { 1081 int bin = DATA_CONNECTION_NONE; 1082 if (hasData) { 1083 switch (dataType) { 1084 case TelephonyManager.NETWORK_TYPE_EDGE: 1085 bin = DATA_CONNECTION_EDGE; 1086 break; 1087 case TelephonyManager.NETWORK_TYPE_GPRS: 1088 bin = DATA_CONNECTION_GPRS; 1089 break; 1090 case TelephonyManager.NETWORK_TYPE_UMTS: 1091 bin = DATA_CONNECTION_UMTS; 1092 break; 1093 default: 1094 bin = DATA_CONNECTION_OTHER; 1095 break; 1096 } 1097 } 1098 if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData); 1099 if (mPhoneDataConnectionType != bin) { 1100 if (mPhoneDataConnectionType >= 0) { 1101 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this); 1102 } 1103 mPhoneDataConnectionType = bin; 1104 mPhoneDataConnectionsTimer[bin].startRunningLocked(this); 1105 } 1106 } 1107 1108 public void noteWifiOnLocked(int uid) { 1109 if (!mWifiOn) { 1110 mWifiOn = true; 1111 mWifiOnTimer.startRunningLocked(this); 1112 } 1113 if (mWifiOnUid != uid) { 1114 if (mWifiOnUid >= 0) { 1115 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked(); 1116 } 1117 mWifiOnUid = uid; 1118 getUidStatsLocked(uid).noteWifiTurnedOnLocked(); 1119 } 1120 } 1121 1122 public void noteWifiOffLocked(int uid) { 1123 if (mWifiOn) { 1124 mWifiOn = false; 1125 mWifiOnTimer.stopRunningLocked(this); 1126 } 1127 if (mWifiOnUid >= 0) { 1128 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked(); 1129 mWifiOnUid = -1; 1130 } 1131 } 1132 1133 public void noteAudioOnLocked(int uid) { 1134 if (!mAudioOn) { 1135 mAudioOn = true; 1136 mAudioOnTimer.startRunningLocked(this); 1137 } 1138 getUidStatsLocked(uid).noteAudioTurnedOnLocked(); 1139 } 1140 1141 public void noteAudioOffLocked(int uid) { 1142 if (mAudioOn) { 1143 mAudioOn = false; 1144 mAudioOnTimer.stopRunningLocked(this); 1145 } 1146 getUidStatsLocked(uid).noteAudioTurnedOffLocked(); 1147 } 1148 1149 public void noteVideoOnLocked(int uid) { 1150 if (!mVideoOn) { 1151 mVideoOn = true; 1152 mVideoOnTimer.startRunningLocked(this); 1153 } 1154 getUidStatsLocked(uid).noteVideoTurnedOnLocked(); 1155 } 1156 1157 public void noteVideoOffLocked(int uid) { 1158 if (mVideoOn) { 1159 mVideoOn = false; 1160 mVideoOnTimer.stopRunningLocked(this); 1161 } 1162 getUidStatsLocked(uid).noteVideoTurnedOffLocked(); 1163 } 1164 1165 public void noteWifiRunningLocked() { 1166 if (!mWifiRunning) { 1167 mWifiRunning = true; 1168 mWifiRunningTimer.startRunningLocked(this); 1169 } 1170 } 1171 1172 public void noteWifiStoppedLocked() { 1173 if (mWifiRunning) { 1174 mWifiRunning = false; 1175 mWifiRunningTimer.stopRunningLocked(this); 1176 } 1177 } 1178 1179 public void noteBluetoothOnLocked() { 1180 if (!mBluetoothOn) { 1181 mBluetoothOn = true; 1182 mBluetoothOnTimer.startRunningLocked(this); 1183 } 1184 } 1185 1186 public void noteBluetoothOffLocked() { 1187 if (mBluetoothOn) { 1188 mBluetoothOn = false; 1189 mBluetoothOnTimer.stopRunningLocked(this); 1190 } 1191 } 1192 1193 public void noteFullWifiLockAcquiredLocked(int uid) { 1194 getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(); 1195 } 1196 1197 public void noteFullWifiLockReleasedLocked(int uid) { 1198 getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(); 1199 } 1200 1201 public void noteScanWifiLockAcquiredLocked(int uid) { 1202 getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked(); 1203 } 1204 1205 public void noteScanWifiLockReleasedLocked(int uid) { 1206 getUidStatsLocked(uid).noteScanWifiLockReleasedLocked(); 1207 } 1208 1209 public void noteWifiMulticastEnabledLocked(int uid) { 1210 getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(); 1211 } 1212 1213 public void noteWifiMulticastDisabledLocked(int uid) { 1214 getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(); 1215 } 1216 1217 @Override public long getScreenOnTime(long batteryRealtime, int which) { 1218 return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which); 1219 } 1220 1221 @Override public long getScreenBrightnessTime(int brightnessBin, 1222 long batteryRealtime, int which) { 1223 return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked( 1224 batteryRealtime, which); 1225 } 1226 1227 @Override public int getInputEventCount(int which) { 1228 return mInputEventCounter.getCountLocked(which); 1229 } 1230 1231 @Override public long getPhoneOnTime(long batteryRealtime, int which) { 1232 return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which); 1233 } 1234 1235 @Override public long getPhoneSignalStrengthTime(int strengthBin, 1236 long batteryRealtime, int which) { 1237 return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked( 1238 batteryRealtime, which); 1239 } 1240 1241 @Override public int getPhoneSignalStrengthCount(int dataType, int which) { 1242 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1243 } 1244 1245 @Override public long getPhoneDataConnectionTime(int dataType, 1246 long batteryRealtime, int which) { 1247 return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked( 1248 batteryRealtime, which); 1249 } 1250 1251 @Override public int getPhoneDataConnectionCount(int dataType, int which) { 1252 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1253 } 1254 1255 @Override public long getWifiOnTime(long batteryRealtime, int which) { 1256 return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which); 1257 } 1258 1259 @Override public long getWifiRunningTime(long batteryRealtime, int which) { 1260 return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which); 1261 } 1262 1263 @Override public long getBluetoothOnTime(long batteryRealtime, int which) { 1264 return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which); 1265 } 1266 1267 @Override public boolean getIsOnBattery() { 1268 return mOnBattery; 1269 } 1270 1271 @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() { 1272 return mUidStats; 1273 } 1274 1275 /** 1276 * The statistics associated with a particular uid. 1277 */ 1278 public final class Uid extends BatteryStats.Uid { 1279 1280 final int mUid; 1281 long mLoadedTcpBytesReceived; 1282 long mLoadedTcpBytesSent; 1283 long mCurrentTcpBytesReceived; 1284 long mCurrentTcpBytesSent; 1285 long mTcpBytesReceivedAtLastUnplug; 1286 long mTcpBytesSentAtLastUnplug; 1287 1288 // These are not saved/restored when parcelling, since we want 1289 // to return from the parcel with a snapshot of the state. 1290 long mStartedTcpBytesReceived = -1; 1291 long mStartedTcpBytesSent = -1; 1292 1293 boolean mWifiTurnedOn; 1294 StopwatchTimer mWifiTurnedOnTimer; 1295 1296 boolean mFullWifiLockOut; 1297 StopwatchTimer mFullWifiLockTimer; 1298 1299 boolean mScanWifiLockOut; 1300 StopwatchTimer mScanWifiLockTimer; 1301 1302 boolean mWifiMulticastEnabled; 1303 StopwatchTimer mWifiMulticastTimer; 1304 1305 boolean mAudioTurnedOn; 1306 StopwatchTimer mAudioTurnedOnTimer; 1307 1308 boolean mVideoTurnedOn; 1309 StopwatchTimer mVideoTurnedOnTimer; 1310 1311 Counter[] mUserActivityCounters; 1312 1313 /** 1314 * The statistics we have collected for this uid's wake locks. 1315 */ 1316 final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>(); 1317 1318 /** 1319 * The statistics we have collected for this uid's sensor activations. 1320 */ 1321 final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>(); 1322 1323 /** 1324 * The statistics we have collected for this uid's processes. 1325 */ 1326 final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>(); 1327 1328 /** 1329 * The statistics we have collected for this uid's processes. 1330 */ 1331 final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>(); 1332 1333 public Uid(int uid) { 1334 mUid = uid; 1335 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables); 1336 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables); 1337 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables); 1338 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1339 null, mUnpluggables); 1340 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables); 1341 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables); 1342 } 1343 1344 @Override 1345 public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() { 1346 return mWakelockStats; 1347 } 1348 1349 @Override 1350 public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() { 1351 return mSensorStats; 1352 } 1353 1354 @Override 1355 public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() { 1356 return mProcessStats; 1357 } 1358 1359 @Override 1360 public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { 1361 return mPackageStats; 1362 } 1363 1364 @Override 1365 public int getUid() { 1366 return mUid; 1367 } 1368 1369 @Override 1370 public long getTcpBytesReceived(int which) { 1371 if (which == STATS_LAST) { 1372 return mLoadedTcpBytesReceived; 1373 } else { 1374 long current = computeCurrentTcpBytesReceived(); 1375 if (which == STATS_UNPLUGGED) { 1376 current -= mTcpBytesReceivedAtLastUnplug; 1377 } else if (which == STATS_TOTAL) { 1378 current += mLoadedTcpBytesReceived; 1379 } 1380 return current; 1381 } 1382 } 1383 1384 public long computeCurrentTcpBytesReceived() { 1385 return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0 1386 ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0); 1387 } 1388 1389 @Override 1390 public long getTcpBytesSent(int which) { 1391 if (which == STATS_LAST) { 1392 return mLoadedTcpBytesSent; 1393 } else { 1394 long current = computeCurrentTcpBytesSent(); 1395 if (which == STATS_UNPLUGGED) { 1396 current -= mTcpBytesSentAtLastUnplug; 1397 } else if (which == STATS_TOTAL) { 1398 current += mLoadedTcpBytesSent; 1399 } 1400 return current; 1401 } 1402 } 1403 1404 @Override 1405 public void noteWifiTurnedOnLocked() { 1406 if (!mWifiTurnedOn) { 1407 mWifiTurnedOn = true; 1408 mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1409 } 1410 } 1411 1412 @Override 1413 public void noteWifiTurnedOffLocked() { 1414 if (mWifiTurnedOn) { 1415 mWifiTurnedOn = false; 1416 mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1417 } 1418 } 1419 1420 @Override 1421 public void noteFullWifiLockAcquiredLocked() { 1422 if (!mFullWifiLockOut) { 1423 mFullWifiLockOut = true; 1424 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 1425 } 1426 } 1427 1428 @Override 1429 public void noteVideoTurnedOnLocked() { 1430 if (!mVideoTurnedOn) { 1431 mVideoTurnedOn = true; 1432 mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1433 } 1434 } 1435 1436 @Override 1437 public void noteVideoTurnedOffLocked() { 1438 if (mVideoTurnedOn) { 1439 mVideoTurnedOn = false; 1440 mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1441 } 1442 } 1443 1444 @Override 1445 public void noteAudioTurnedOnLocked() { 1446 if (!mAudioTurnedOn) { 1447 mAudioTurnedOn = true; 1448 mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1449 } 1450 } 1451 1452 @Override 1453 public void noteAudioTurnedOffLocked() { 1454 if (mAudioTurnedOn) { 1455 mAudioTurnedOn = false; 1456 mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1457 } 1458 } 1459 1460 @Override 1461 public void noteFullWifiLockReleasedLocked() { 1462 if (mFullWifiLockOut) { 1463 mFullWifiLockOut = false; 1464 mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 1465 } 1466 } 1467 1468 @Override 1469 public void noteScanWifiLockAcquiredLocked() { 1470 if (!mScanWifiLockOut) { 1471 mScanWifiLockOut = true; 1472 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 1473 } 1474 } 1475 1476 @Override 1477 public void noteScanWifiLockReleasedLocked() { 1478 if (mScanWifiLockOut) { 1479 mScanWifiLockOut = false; 1480 mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 1481 } 1482 } 1483 1484 @Override 1485 public void noteWifiMulticastEnabledLocked() { 1486 if (!mWifiMulticastEnabled) { 1487 mWifiMulticastEnabled = true; 1488 mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this); 1489 } 1490 } 1491 1492 @Override 1493 public void noteWifiMulticastDisabledLocked() { 1494 if (mWifiMulticastEnabled) { 1495 mWifiMulticastEnabled = false; 1496 mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this); 1497 } 1498 } 1499 1500 @Override 1501 public long getWifiTurnedOnTime(long batteryRealtime, int which) { 1502 return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1503 } 1504 1505 @Override 1506 public long getAudioTurnedOnTime(long batteryRealtime, int which) { 1507 return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1508 } 1509 1510 @Override 1511 public long getVideoTurnedOnTime(long batteryRealtime, int which) { 1512 return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1513 } 1514 1515 @Override 1516 public long getFullWifiLockTime(long batteryRealtime, int which) { 1517 return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 1518 } 1519 1520 @Override 1521 public long getScanWifiLockTime(long batteryRealtime, int which) { 1522 return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 1523 } 1524 1525 @Override 1526 public long getWifiMulticastTime(long batteryRealtime, int which) { 1527 return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime, 1528 which); 1529 } 1530 1531 @Override 1532 public void noteUserActivityLocked(int type) { 1533 if (mUserActivityCounters == null) { 1534 initUserActivityLocked(); 1535 } 1536 if (type < 0) type = 0; 1537 else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1; 1538 mUserActivityCounters[type].stepLocked(); 1539 } 1540 1541 @Override 1542 public boolean hasUserActivity() { 1543 return mUserActivityCounters != null; 1544 } 1545 1546 @Override 1547 public int getUserActivityCount(int type, int which) { 1548 if (mUserActivityCounters == null) { 1549 return 0; 1550 } 1551 return mUserActivityCounters[type].getCountLocked(which); 1552 } 1553 1554 void initUserActivityLocked() { 1555 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 1556 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1557 mUserActivityCounters[i] = new Counter(mUnpluggables); 1558 } 1559 } 1560 1561 public long computeCurrentTcpBytesSent() { 1562 return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0 1563 ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0); 1564 } 1565 1566 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1567 out.writeInt(mWakelockStats.size()); 1568 for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) { 1569 out.writeString(wakelockEntry.getKey()); 1570 Uid.Wakelock wakelock = wakelockEntry.getValue(); 1571 wakelock.writeToParcelLocked(out, batteryRealtime); 1572 } 1573 1574 out.writeInt(mSensorStats.size()); 1575 for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) { 1576 out.writeInt(sensorEntry.getKey()); 1577 Uid.Sensor sensor = sensorEntry.getValue(); 1578 sensor.writeToParcelLocked(out, batteryRealtime); 1579 } 1580 1581 out.writeInt(mProcessStats.size()); 1582 for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) { 1583 out.writeString(procEntry.getKey()); 1584 Uid.Proc proc = procEntry.getValue(); 1585 proc.writeToParcelLocked(out); 1586 } 1587 1588 out.writeInt(mPackageStats.size()); 1589 for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) { 1590 out.writeString(pkgEntry.getKey()); 1591 Uid.Pkg pkg = pkgEntry.getValue(); 1592 pkg.writeToParcelLocked(out); 1593 } 1594 1595 out.writeLong(mLoadedTcpBytesReceived); 1596 out.writeLong(mLoadedTcpBytesSent); 1597 out.writeLong(computeCurrentTcpBytesReceived()); 1598 out.writeLong(computeCurrentTcpBytesSent()); 1599 out.writeLong(mTcpBytesReceivedAtLastUnplug); 1600 out.writeLong(mTcpBytesSentAtLastUnplug); 1601 mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime); 1602 mFullWifiLockTimer.writeToParcel(out, batteryRealtime); 1603 mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime); 1604 mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime); 1605 mScanWifiLockTimer.writeToParcel(out, batteryRealtime); 1606 mWifiMulticastTimer.writeToParcel(out, batteryRealtime); 1607 if (mUserActivityCounters == null) { 1608 out.writeInt(0); 1609 } else { 1610 out.writeInt(1); 1611 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1612 mUserActivityCounters[i].writeToParcel(out); 1613 } 1614 } 1615 } 1616 1617 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1618 int numWakelocks = in.readInt(); 1619 mWakelockStats.clear(); 1620 for (int j = 0; j < numWakelocks; j++) { 1621 String wakelockName = in.readString(); 1622 Uid.Wakelock wakelock = new Wakelock(); 1623 wakelock.readFromParcelLocked(unpluggables, in); 1624 mWakelockStats.put(wakelockName, wakelock); 1625 } 1626 1627 int numSensors = in.readInt(); 1628 mSensorStats.clear(); 1629 for (int k = 0; k < numSensors; k++) { 1630 int sensorNumber = in.readInt(); 1631 Uid.Sensor sensor = new Sensor(sensorNumber); 1632 sensor.readFromParcelLocked(mUnpluggables, in); 1633 mSensorStats.put(sensorNumber, sensor); 1634 } 1635 1636 int numProcs = in.readInt(); 1637 mProcessStats.clear(); 1638 for (int k = 0; k < numProcs; k++) { 1639 String processName = in.readString(); 1640 Uid.Proc proc = new Proc(); 1641 proc.readFromParcelLocked(in); 1642 mProcessStats.put(processName, proc); 1643 } 1644 1645 int numPkgs = in.readInt(); 1646 mPackageStats.clear(); 1647 for (int l = 0; l < numPkgs; l++) { 1648 String packageName = in.readString(); 1649 Uid.Pkg pkg = new Pkg(); 1650 pkg.readFromParcelLocked(in); 1651 mPackageStats.put(packageName, pkg); 1652 } 1653 1654 mLoadedTcpBytesReceived = in.readLong(); 1655 mLoadedTcpBytesSent = in.readLong(); 1656 mCurrentTcpBytesReceived = in.readLong(); 1657 mCurrentTcpBytesSent = in.readLong(); 1658 mTcpBytesReceivedAtLastUnplug = in.readLong(); 1659 mTcpBytesSentAtLastUnplug = in.readLong(); 1660 mWifiTurnedOn = false; 1661 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables, in); 1662 mFullWifiLockOut = false; 1663 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in); 1664 mAudioTurnedOn = false; 1665 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables, in); 1666 mVideoTurnedOn = false; 1667 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables, in); 1668 mScanWifiLockOut = false; 1669 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in); 1670 mWifiMulticastEnabled = false; 1671 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1672 null, mUnpluggables, in); 1673 if (in.readInt() == 0) { 1674 mUserActivityCounters = null; 1675 } else { 1676 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 1677 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1678 mUserActivityCounters[i] = new Counter(mUnpluggables, in); 1679 } 1680 } 1681 } 1682 1683 /** 1684 * The statistics associated with a particular wake lock. 1685 */ 1686 public final class Wakelock extends BatteryStats.Uid.Wakelock { 1687 /** 1688 * How long (in ms) this uid has been keeping the device partially awake. 1689 */ 1690 StopwatchTimer mTimerPartial; 1691 1692 /** 1693 * How long (in ms) this uid has been keeping the device fully awake. 1694 */ 1695 StopwatchTimer mTimerFull; 1696 1697 /** 1698 * How long (in ms) this uid has had a window keeping the device awake. 1699 */ 1700 StopwatchTimer mTimerWindow; 1701 1702 /** 1703 * Reads a possibly null Timer from a Parcel. The timer is associated with the 1704 * proper timer pool from the given BatteryStatsImpl object. 1705 * 1706 * @param in the Parcel to be read from. 1707 * return a new Timer, or null. 1708 */ 1709 private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, 1710 ArrayList<Unpluggable> unpluggables, Parcel in) { 1711 if (in.readInt() == 0) { 1712 return null; 1713 } 1714 1715 return new StopwatchTimer(type, pool, unpluggables, in); 1716 } 1717 1718 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1719 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL, 1720 mPartialTimers, unpluggables, in); 1721 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, 1722 mFullTimers, unpluggables, in); 1723 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, 1724 mWindowTimers, unpluggables, in); 1725 } 1726 1727 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1728 Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime); 1729 Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime); 1730 Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime); 1731 } 1732 1733 @Override 1734 public Timer getWakeTime(int type) { 1735 switch (type) { 1736 case WAKE_TYPE_FULL: return mTimerFull; 1737 case WAKE_TYPE_PARTIAL: return mTimerPartial; 1738 case WAKE_TYPE_WINDOW: return mTimerWindow; 1739 default: throw new IllegalArgumentException("type = " + type); 1740 } 1741 } 1742 } 1743 1744 public final class Sensor extends BatteryStats.Uid.Sensor { 1745 final int mHandle; 1746 StopwatchTimer mTimer; 1747 1748 public Sensor(int handle) { 1749 mHandle = handle; 1750 } 1751 1752 private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables, 1753 Parcel in) { 1754 if (in.readInt() == 0) { 1755 return null; 1756 } 1757 1758 ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle); 1759 if (pool == null) { 1760 pool = new ArrayList<StopwatchTimer>(); 1761 mSensorTimers.put(mHandle, pool); 1762 } 1763 return new StopwatchTimer(0, pool, unpluggables, in); 1764 } 1765 1766 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1767 mTimer = readTimerFromParcel(unpluggables, in); 1768 } 1769 1770 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1771 Timer.writeTimerToParcel(out, mTimer, batteryRealtime); 1772 } 1773 1774 @Override 1775 public Timer getSensorTime() { 1776 return mTimer; 1777 } 1778 1779 @Override 1780 public int getHandle() { 1781 return mHandle; 1782 } 1783 } 1784 1785 /** 1786 * The statistics associated with a particular process. 1787 */ 1788 public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable { 1789 /** 1790 * Total time (in 1/100 sec) spent executing in user code. 1791 */ 1792 long mUserTime; 1793 1794 /** 1795 * Total time (in 1/100 sec) spent executing in kernel code. 1796 */ 1797 long mSystemTime; 1798 1799 /** 1800 * Number of times the process has been started. 1801 */ 1802 int mStarts; 1803 1804 /** 1805 * Amount of time the process was running in the foreground. 1806 */ 1807 long mForegroundTime; 1808 1809 /** 1810 * The amount of user time loaded from a previous save. 1811 */ 1812 long mLoadedUserTime; 1813 1814 /** 1815 * The amount of system time loaded from a previous save. 1816 */ 1817 long mLoadedSystemTime; 1818 1819 /** 1820 * The number of times the process has started from a previous save. 1821 */ 1822 int mLoadedStarts; 1823 1824 /** 1825 * The amount of foreground time loaded from a previous save. 1826 */ 1827 long mLoadedForegroundTime; 1828 1829 /** 1830 * The amount of user time loaded from the previous run. 1831 */ 1832 long mLastUserTime; 1833 1834 /** 1835 * The amount of system time loaded from the previous run. 1836 */ 1837 long mLastSystemTime; 1838 1839 /** 1840 * The number of times the process has started from the previous run. 1841 */ 1842 int mLastStarts; 1843 1844 /** 1845 * The amount of foreground time loaded from the previous run 1846 */ 1847 long mLastForegroundTime; 1848 1849 /** 1850 * The amount of user time when last unplugged. 1851 */ 1852 long mUnpluggedUserTime; 1853 1854 /** 1855 * The amount of system time when last unplugged. 1856 */ 1857 long mUnpluggedSystemTime; 1858 1859 /** 1860 * The number of times the process has started before unplugged. 1861 */ 1862 int mUnpluggedStarts; 1863 1864 /** 1865 * The amount of foreground time since unplugged. 1866 */ 1867 long mUnpluggedForegroundTime; 1868 1869 Proc() { 1870 mUnpluggables.add(this); 1871 } 1872 1873 public void unplug(long batteryUptime, long batteryRealtime) { 1874 mUnpluggedUserTime = mUserTime; 1875 mUnpluggedSystemTime = mSystemTime; 1876 mUnpluggedStarts = mStarts; 1877 mUnpluggedForegroundTime = mForegroundTime; 1878 } 1879 1880 public void plug(long batteryUptime, long batteryRealtime) { 1881 } 1882 1883 void writeToParcelLocked(Parcel out) { 1884 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 1885 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 1886 1887 out.writeLong(mUserTime); 1888 out.writeLong(mSystemTime); 1889 out.writeLong(mForegroundTime); 1890 out.writeInt(mStarts); 1891 out.writeLong(mLoadedUserTime); 1892 out.writeLong(mLoadedSystemTime); 1893 out.writeLong(mLoadedForegroundTime); 1894 out.writeInt(mLoadedStarts); 1895 out.writeLong(mLastUserTime); 1896 out.writeLong(mLastSystemTime); 1897 out.writeLong(mLastForegroundTime); 1898 out.writeInt(mLastStarts); 1899 out.writeLong(mUnpluggedUserTime); 1900 out.writeLong(mUnpluggedSystemTime); 1901 out.writeLong(mUnpluggedForegroundTime); 1902 out.writeInt(mUnpluggedStarts); 1903 } 1904 1905 void readFromParcelLocked(Parcel in) { 1906 mUserTime = in.readLong(); 1907 mSystemTime = in.readLong(); 1908 mForegroundTime = in.readLong(); 1909 mStarts = in.readInt(); 1910 mLoadedUserTime = in.readLong(); 1911 mLoadedSystemTime = in.readLong(); 1912 mLoadedForegroundTime = in.readLong(); 1913 mLoadedStarts = in.readInt(); 1914 mLastUserTime = in.readLong(); 1915 mLastSystemTime = in.readLong(); 1916 mLastForegroundTime = in.readLong(); 1917 mLastStarts = in.readInt(); 1918 mUnpluggedUserTime = in.readLong(); 1919 mUnpluggedSystemTime = in.readLong(); 1920 mUnpluggedForegroundTime = in.readLong(); 1921 mUnpluggedStarts = in.readInt(); 1922 } 1923 1924 public BatteryStatsImpl getBatteryStats() { 1925 return BatteryStatsImpl.this; 1926 } 1927 1928 public void addCpuTimeLocked(int utime, int stime) { 1929 mUserTime += utime; 1930 mSystemTime += stime; 1931 } 1932 1933 public void addForegroundTimeLocked(long ttime) { 1934 mForegroundTime += ttime; 1935 } 1936 1937 public void incStartsLocked() { 1938 mStarts++; 1939 } 1940 1941 @Override 1942 public long getUserTime(int which) { 1943 long val; 1944 if (which == STATS_LAST) { 1945 val = mLastUserTime; 1946 } else { 1947 val = mUserTime; 1948 if (which == STATS_CURRENT) { 1949 val -= mLoadedUserTime; 1950 } else if (which == STATS_UNPLUGGED) { 1951 val -= mUnpluggedUserTime; 1952 } 1953 } 1954 return val; 1955 } 1956 1957 @Override 1958 public long getSystemTime(int which) { 1959 long val; 1960 if (which == STATS_LAST) { 1961 val = mLastSystemTime; 1962 } else { 1963 val = mSystemTime; 1964 if (which == STATS_CURRENT) { 1965 val -= mLoadedSystemTime; 1966 } else if (which == STATS_UNPLUGGED) { 1967 val -= mUnpluggedSystemTime; 1968 } 1969 } 1970 return val; 1971 } 1972 1973 @Override 1974 public long getForegroundTime(int which) { 1975 long val; 1976 if (which == STATS_LAST) { 1977 val = mLastForegroundTime; 1978 } else { 1979 val = mForegroundTime; 1980 if (which == STATS_CURRENT) { 1981 val -= mLoadedForegroundTime; 1982 } else if (which == STATS_UNPLUGGED) { 1983 val -= mUnpluggedForegroundTime; 1984 } 1985 } 1986 return val; 1987 } 1988 1989 @Override 1990 public int getStarts(int which) { 1991 int val; 1992 if (which == STATS_LAST) { 1993 val = mLastStarts; 1994 } else { 1995 val = mStarts; 1996 if (which == STATS_CURRENT) { 1997 val -= mLoadedStarts; 1998 } else if (which == STATS_UNPLUGGED) { 1999 val -= mUnpluggedStarts; 2000 } 2001 } 2002 return val; 2003 } 2004 } 2005 2006 /** 2007 * The statistics associated with a particular package. 2008 */ 2009 public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable { 2010 /** 2011 * Number of times this package has done something that could wake up the 2012 * device from sleep. 2013 */ 2014 int mWakeups; 2015 2016 /** 2017 * Number of things that could wake up the device loaded from a 2018 * previous save. 2019 */ 2020 int mLoadedWakeups; 2021 2022 /** 2023 * Number of things that could wake up the device as of the 2024 * last run. 2025 */ 2026 int mLastWakeups; 2027 2028 /** 2029 * Number of things that could wake up the device as of the 2030 * last run. 2031 */ 2032 int mUnpluggedWakeups; 2033 2034 /** 2035 * The statics we have collected for this package's services. 2036 */ 2037 final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>(); 2038 2039 Pkg() { 2040 mUnpluggables.add(this); 2041 } 2042 2043 public void unplug(long batteryUptime, long batteryRealtime) { 2044 mUnpluggedWakeups = mWakeups; 2045 } 2046 2047 public void plug(long batteryUptime, long batteryRealtime) { 2048 } 2049 2050 void readFromParcelLocked(Parcel in) { 2051 mWakeups = in.readInt(); 2052 mLoadedWakeups = in.readInt(); 2053 mLastWakeups = in.readInt(); 2054 mUnpluggedWakeups = in.readInt(); 2055 2056 int numServs = in.readInt(); 2057 mServiceStats.clear(); 2058 for (int m = 0; m < numServs; m++) { 2059 String serviceName = in.readString(); 2060 Uid.Pkg.Serv serv = new Serv(); 2061 mServiceStats.put(serviceName, serv); 2062 2063 serv.readFromParcelLocked(in); 2064 } 2065 } 2066 2067 void writeToParcelLocked(Parcel out) { 2068 out.writeInt(mWakeups); 2069 out.writeInt(mLoadedWakeups); 2070 out.writeInt(mLastWakeups); 2071 out.writeInt(mUnpluggedWakeups); 2072 2073 out.writeInt(mServiceStats.size()); 2074 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) { 2075 out.writeString(servEntry.getKey()); 2076 Uid.Pkg.Serv serv = servEntry.getValue(); 2077 2078 serv.writeToParcelLocked(out); 2079 } 2080 } 2081 2082 @Override 2083 public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() { 2084 return mServiceStats; 2085 } 2086 2087 @Override 2088 public int getWakeups(int which) { 2089 int val; 2090 if (which == STATS_LAST) { 2091 val = mLastWakeups; 2092 } else { 2093 val = mWakeups; 2094 if (which == STATS_CURRENT) { 2095 val -= mLoadedWakeups; 2096 } else if (which == STATS_UNPLUGGED) { 2097 val -= mUnpluggedWakeups; 2098 } 2099 } 2100 2101 return val; 2102 } 2103 2104 /** 2105 * The statistics associated with a particular service. 2106 */ 2107 public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable { 2108 /** 2109 * Total time (ms in battery uptime) the service has been left started. 2110 */ 2111 long mStartTime; 2112 2113 /** 2114 * If service has been started and not yet stopped, this is 2115 * when it was started. 2116 */ 2117 long mRunningSince; 2118 2119 /** 2120 * True if we are currently running. 2121 */ 2122 boolean mRunning; 2123 2124 /** 2125 * Total number of times startService() has been called. 2126 */ 2127 int mStarts; 2128 2129 /** 2130 * Total time (ms in battery uptime) the service has been left launched. 2131 */ 2132 long mLaunchedTime; 2133 2134 /** 2135 * If service has been launched and not yet exited, this is 2136 * when it was launched (ms in battery uptime). 2137 */ 2138 long mLaunchedSince; 2139 2140 /** 2141 * True if we are currently launched. 2142 */ 2143 boolean mLaunched; 2144 2145 /** 2146 * Total number times the service has been launched. 2147 */ 2148 int mLaunches; 2149 2150 /** 2151 * The amount of time spent started loaded from a previous save 2152 * (ms in battery uptime). 2153 */ 2154 long mLoadedStartTime; 2155 2156 /** 2157 * The number of starts loaded from a previous save. 2158 */ 2159 int mLoadedStarts; 2160 2161 /** 2162 * The number of launches loaded from a previous save. 2163 */ 2164 int mLoadedLaunches; 2165 2166 /** 2167 * The amount of time spent started as of the last run (ms 2168 * in battery uptime). 2169 */ 2170 long mLastStartTime; 2171 2172 /** 2173 * The number of starts as of the last run. 2174 */ 2175 int mLastStarts; 2176 2177 /** 2178 * The number of launches as of the last run. 2179 */ 2180 int mLastLaunches; 2181 2182 /** 2183 * The amount of time spent started when last unplugged (ms 2184 * in battery uptime). 2185 */ 2186 long mUnpluggedStartTime; 2187 2188 /** 2189 * The number of starts when last unplugged. 2190 */ 2191 int mUnpluggedStarts; 2192 2193 /** 2194 * The number of launches when last unplugged. 2195 */ 2196 int mUnpluggedLaunches; 2197 2198 Serv() { 2199 mUnpluggables.add(this); 2200 } 2201 2202 public void unplug(long batteryUptime, long batteryRealtime) { 2203 mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime); 2204 mUnpluggedStarts = mStarts; 2205 mUnpluggedLaunches = mLaunches; 2206 } 2207 2208 public void plug(long batteryUptime, long batteryRealtime) { 2209 } 2210 2211 void readFromParcelLocked(Parcel in) { 2212 mStartTime = in.readLong(); 2213 mRunningSince = in.readLong(); 2214 mRunning = in.readInt() != 0; 2215 mStarts = in.readInt(); 2216 mLaunchedTime = in.readLong(); 2217 mLaunchedSince = in.readLong(); 2218 mLaunched = in.readInt() != 0; 2219 mLaunches = in.readInt(); 2220 mLoadedStartTime = in.readLong(); 2221 mLoadedStarts = in.readInt(); 2222 mLoadedLaunches = in.readInt(); 2223 mLastStartTime = in.readLong(); 2224 mLastStarts = in.readInt(); 2225 mLastLaunches = in.readInt(); 2226 mUnpluggedStartTime = in.readLong(); 2227 mUnpluggedStarts = in.readInt(); 2228 mUnpluggedLaunches = in.readInt(); 2229 } 2230 2231 void writeToParcelLocked(Parcel out) { 2232 out.writeLong(mStartTime); 2233 out.writeLong(mRunningSince); 2234 out.writeInt(mRunning ? 1 : 0); 2235 out.writeInt(mStarts); 2236 out.writeLong(mLaunchedTime); 2237 out.writeLong(mLaunchedSince); 2238 out.writeInt(mLaunched ? 1 : 0); 2239 out.writeInt(mLaunches); 2240 out.writeLong(mLoadedStartTime); 2241 out.writeInt(mLoadedStarts); 2242 out.writeInt(mLoadedLaunches); 2243 out.writeLong(mLastStartTime); 2244 out.writeInt(mLastStarts); 2245 out.writeInt(mLastLaunches); 2246 out.writeLong(mUnpluggedStartTime); 2247 out.writeInt(mUnpluggedStarts); 2248 out.writeInt(mUnpluggedLaunches); 2249 } 2250 2251 long getLaunchTimeToNowLocked(long batteryUptime) { 2252 if (!mLaunched) return mLaunchedTime; 2253 return mLaunchedTime + batteryUptime - mLaunchedSince; 2254 } 2255 2256 long getStartTimeToNowLocked(long batteryUptime) { 2257 if (!mRunning) return mStartTime; 2258 return mStartTime + batteryUptime - mRunningSince; 2259 } 2260 2261 public void startLaunchedLocked() { 2262 if (!mLaunched) { 2263 mLaunches++; 2264 mLaunchedSince = getBatteryUptimeLocked(); 2265 mLaunched = true; 2266 } 2267 } 2268 2269 public void stopLaunchedLocked() { 2270 if (mLaunched) { 2271 long time = getBatteryUptimeLocked() - mLaunchedSince; 2272 if (time > 0) { 2273 mLaunchedTime += time; 2274 } else { 2275 mLaunches--; 2276 } 2277 mLaunched = false; 2278 } 2279 } 2280 2281 public void startRunningLocked() { 2282 if (!mRunning) { 2283 mStarts++; 2284 mRunningSince = getBatteryUptimeLocked(); 2285 mRunning = true; 2286 } 2287 } 2288 2289 public void stopRunningLocked() { 2290 if (mRunning) { 2291 long time = getBatteryUptimeLocked() - mRunningSince; 2292 if (time > 0) { 2293 mStartTime += time; 2294 } else { 2295 mStarts--; 2296 } 2297 mRunning = false; 2298 } 2299 } 2300 2301 public BatteryStatsImpl getBatteryStats() { 2302 return BatteryStatsImpl.this; 2303 } 2304 2305 @Override 2306 public int getLaunches(int which) { 2307 int val; 2308 2309 if (which == STATS_LAST) { 2310 val = mLastLaunches; 2311 } else { 2312 val = mLaunches; 2313 if (which == STATS_CURRENT) { 2314 val -= mLoadedLaunches; 2315 } else if (which == STATS_UNPLUGGED) { 2316 val -= mUnpluggedLaunches; 2317 } 2318 } 2319 2320 return val; 2321 } 2322 2323 @Override 2324 public long getStartTime(long now, int which) { 2325 long val; 2326 if (which == STATS_LAST) { 2327 val = mLastStartTime; 2328 } else { 2329 val = getStartTimeToNowLocked(now); 2330 if (which == STATS_CURRENT) { 2331 val -= mLoadedStartTime; 2332 } else if (which == STATS_UNPLUGGED) { 2333 val -= mUnpluggedStartTime; 2334 } 2335 } 2336 2337 return val; 2338 } 2339 2340 @Override 2341 public int getStarts(int which) { 2342 int val; 2343 if (which == STATS_LAST) { 2344 val = mLastStarts; 2345 } else { 2346 val = mStarts; 2347 if (which == STATS_CURRENT) { 2348 val -= mLoadedStarts; 2349 } else if (which == STATS_UNPLUGGED) { 2350 val -= mUnpluggedStarts; 2351 } 2352 } 2353 2354 return val; 2355 } 2356 } 2357 2358 public BatteryStatsImpl getBatteryStats() { 2359 return BatteryStatsImpl.this; 2360 } 2361 2362 public void incWakeupsLocked() { 2363 mWakeups++; 2364 } 2365 2366 final Serv newServiceStatsLocked() { 2367 return new Serv(); 2368 } 2369 } 2370 2371 /** 2372 * Retrieve the statistics object for a particular process, creating 2373 * if needed. 2374 */ 2375 public Proc getProcessStatsLocked(String name) { 2376 Proc ps = mProcessStats.get(name); 2377 if (ps == null) { 2378 ps = new Proc(); 2379 mProcessStats.put(name, ps); 2380 } 2381 2382 return ps; 2383 } 2384 2385 /** 2386 * Retrieve the statistics object for a particular service, creating 2387 * if needed. 2388 */ 2389 public Pkg getPackageStatsLocked(String name) { 2390 Pkg ps = mPackageStats.get(name); 2391 if (ps == null) { 2392 ps = new Pkg(); 2393 mPackageStats.put(name, ps); 2394 } 2395 2396 return ps; 2397 } 2398 2399 /** 2400 * Retrieve the statistics object for a particular service, creating 2401 * if needed. 2402 */ 2403 public Pkg.Serv getServiceStatsLocked(String pkg, String serv) { 2404 Pkg ps = getPackageStatsLocked(pkg); 2405 Pkg.Serv ss = ps.mServiceStats.get(serv); 2406 if (ss == null) { 2407 ss = ps.newServiceStatsLocked(); 2408 ps.mServiceStats.put(serv, ss); 2409 } 2410 2411 return ss; 2412 } 2413 2414 public StopwatchTimer getWakeTimerLocked(String name, int type) { 2415 Wakelock wl = mWakelockStats.get(name); 2416 if (wl == null) { 2417 wl = new Wakelock(); 2418 mWakelockStats.put(name, wl); 2419 } 2420 StopwatchTimer t = null; 2421 switch (type) { 2422 case WAKE_TYPE_PARTIAL: 2423 t = wl.mTimerPartial; 2424 if (t == null) { 2425 t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables); 2426 wl.mTimerPartial = t; 2427 } 2428 return t; 2429 case WAKE_TYPE_FULL: 2430 t = wl.mTimerFull; 2431 if (t == null) { 2432 t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables); 2433 wl.mTimerFull = t; 2434 } 2435 return t; 2436 case WAKE_TYPE_WINDOW: 2437 t = wl.mTimerWindow; 2438 if (t == null) { 2439 t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables); 2440 wl.mTimerWindow = t; 2441 } 2442 return t; 2443 default: 2444 throw new IllegalArgumentException("type=" + type); 2445 } 2446 } 2447 2448 public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) { 2449 Sensor se = mSensorStats.get(sensor); 2450 if (se == null) { 2451 if (!create) { 2452 return null; 2453 } 2454 se = new Sensor(sensor); 2455 mSensorStats.put(sensor, se); 2456 } 2457 StopwatchTimer t = se.mTimer; 2458 if (t != null) { 2459 return t; 2460 } 2461 ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor); 2462 if (timers == null) { 2463 timers = new ArrayList<StopwatchTimer>(); 2464 mSensorTimers.put(sensor, timers); 2465 } 2466 t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables); 2467 se.mTimer = t; 2468 return t; 2469 } 2470 2471 public void noteStartWakeLocked(String name, int type) { 2472 StopwatchTimer t = getWakeTimerLocked(name, type); 2473 if (t != null) { 2474 t.startRunningLocked(BatteryStatsImpl.this); 2475 } 2476 } 2477 2478 public void noteStopWakeLocked(String name, int type) { 2479 StopwatchTimer t = getWakeTimerLocked(name, type); 2480 if (t != null) { 2481 t.stopRunningLocked(BatteryStatsImpl.this); 2482 } 2483 } 2484 2485 public void noteStartSensor(int sensor) { 2486 StopwatchTimer t = getSensorTimerLocked(sensor, true); 2487 if (t != null) { 2488 t.startRunningLocked(BatteryStatsImpl.this); 2489 } 2490 } 2491 2492 public void noteStopSensor(int sensor) { 2493 // Don't create a timer if one doesn't already exist 2494 StopwatchTimer t = getSensorTimerLocked(sensor, false); 2495 if (t != null) { 2496 t.stopRunningLocked(BatteryStatsImpl.this); 2497 } 2498 } 2499 2500 public void noteStartGps() { 2501 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true); 2502 if (t != null) { 2503 t.startRunningLocked(BatteryStatsImpl.this); 2504 } 2505 } 2506 2507 public void noteStopGps() { 2508 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false); 2509 if (t != null) { 2510 t.stopRunningLocked(BatteryStatsImpl.this); 2511 } 2512 } 2513 2514 public BatteryStatsImpl getBatteryStats() { 2515 return BatteryStatsImpl.this; 2516 } 2517 } 2518 2519 public BatteryStatsImpl(String filename) { 2520 mFile = new File(filename); 2521 mBackupFile = new File(filename + ".bak"); 2522 mStartCount++; 2523 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables); 2524 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 2525 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables); 2526 } 2527 mInputEventCounter = new Counter(mUnpluggables); 2528 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables); 2529 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 2530 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables); 2531 } 2532 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 2533 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables); 2534 } 2535 mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables); 2536 mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables); 2537 mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables); 2538 mOnBattery = mOnBatteryInternal = false; 2539 mTrackBatteryPastUptime = 0; 2540 mTrackBatteryPastRealtime = 0; 2541 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; 2542 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; 2543 mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); 2544 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); 2545 mDischargeStartLevel = 0; 2546 mDischargeCurrentLevel = 0; 2547 } 2548 2549 public BatteryStatsImpl(Parcel p) { 2550 mFile = mBackupFile = null; 2551 readFromParcel(p); 2552 } 2553 2554 @Override 2555 public int getStartCount() { 2556 return mStartCount; 2557 } 2558 2559 public boolean isOnBattery() { 2560 return mOnBattery; 2561 } 2562 2563 public void setOnBattery(boolean onBattery, int level) { 2564 synchronized(this) { 2565 updateKernelWakelocksLocked(); 2566 if (mOnBattery != onBattery) { 2567 mOnBattery = mOnBatteryInternal = onBattery; 2568 2569 long uptime = SystemClock.uptimeMillis() * 1000; 2570 long mSecRealtime = SystemClock.elapsedRealtime(); 2571 long realtime = mSecRealtime * 1000; 2572 if (onBattery) { 2573 mTrackBatteryUptimeStart = uptime; 2574 mTrackBatteryRealtimeStart = realtime; 2575 mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); 2576 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); 2577 mDischargeCurrentLevel = mDischargeStartLevel = level; 2578 doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); 2579 } else { 2580 mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; 2581 mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; 2582 mDischargeCurrentLevel = level; 2583 doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); 2584 } 2585 if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) { 2586 if (mFile != null) { 2587 writeLocked(); 2588 } 2589 } 2590 } 2591 } 2592 } 2593 2594 public void recordCurrentLevel(int level) { 2595 mDischargeCurrentLevel = level; 2596 } 2597 2598 public void updateKernelWakelocksLocked() { 2599 Map<String, KernelWakelockStats> m = readKernelWakelockStats(); 2600 2601 if (m == null) { 2602 // Not crashing might make board bringup easier. 2603 Log.w(TAG, "Couldn't get kernel wake lock stats"); 2604 return; 2605 } 2606 2607 for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) { 2608 String name = ent.getKey(); 2609 KernelWakelockStats kws = ent.getValue(); 2610 2611 SamplingTimer kwlt = mKernelWakelockStats.get(name); 2612 if (kwlt == null) { 2613 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 2614 true /* track reported values */); 2615 mKernelWakelockStats.put(name, kwlt); 2616 } 2617 kwlt.updateCurrentReportedCount(kws.mCount); 2618 kwlt.updateCurrentReportedTotalTime(kws.mTotalTime); 2619 kwlt.setUpdateVersion(sKernelWakelockUpdateVersion); 2620 } 2621 2622 if (m.size() != mKernelWakelockStats.size()) { 2623 // Set timers to stale if they didn't appear in /proc/wakelocks this time. 2624 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 2625 SamplingTimer st = ent.getValue(); 2626 if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) { 2627 st.setStale(); 2628 } 2629 } 2630 } 2631 } 2632 2633 public long getAwakeTimeBattery() { 2634 return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT); 2635 } 2636 2637 public long getAwakeTimePlugged() { 2638 return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery(); 2639 } 2640 2641 @Override 2642 public long computeUptime(long curTime, int which) { 2643 switch (which) { 2644 case STATS_TOTAL: return mUptime + (curTime-mUptimeStart); 2645 case STATS_LAST: return mLastUptime; 2646 case STATS_CURRENT: return (curTime-mUptimeStart); 2647 case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart); 2648 } 2649 return 0; 2650 } 2651 2652 @Override 2653 public long computeRealtime(long curTime, int which) { 2654 switch (which) { 2655 case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart); 2656 case STATS_LAST: return mLastRealtime; 2657 case STATS_CURRENT: return (curTime-mRealtimeStart); 2658 case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart); 2659 } 2660 return 0; 2661 } 2662 2663 @Override 2664 public long computeBatteryUptime(long curTime, int which) { 2665 switch (which) { 2666 case STATS_TOTAL: 2667 return mBatteryUptime + getBatteryUptime(curTime); 2668 case STATS_LAST: 2669 return mBatteryLastUptime; 2670 case STATS_CURRENT: 2671 return getBatteryUptime(curTime); 2672 case STATS_UNPLUGGED: 2673 return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime; 2674 } 2675 return 0; 2676 } 2677 2678 @Override 2679 public long computeBatteryRealtime(long curTime, int which) { 2680 switch (which) { 2681 case STATS_TOTAL: 2682 return mBatteryRealtime + getBatteryRealtimeLocked(curTime); 2683 case STATS_LAST: 2684 return mBatteryLastRealtime; 2685 case STATS_CURRENT: 2686 return getBatteryRealtimeLocked(curTime); 2687 case STATS_UNPLUGGED: 2688 return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime; 2689 } 2690 return 0; 2691 } 2692 2693 long getBatteryUptimeLocked(long curTime) { 2694 long time = mTrackBatteryPastUptime; 2695 if (mOnBatteryInternal) { 2696 time += curTime - mTrackBatteryUptimeStart; 2697 } 2698 return time; 2699 } 2700 2701 long getBatteryUptimeLocked() { 2702 return getBatteryUptime(SystemClock.uptimeMillis() * 1000); 2703 } 2704 2705 @Override 2706 public long getBatteryUptime(long curTime) { 2707 return getBatteryUptimeLocked(curTime); 2708 } 2709 2710 long getBatteryRealtimeLocked(long curTime) { 2711 long time = mTrackBatteryPastRealtime; 2712 if (mOnBatteryInternal) { 2713 time += curTime - mTrackBatteryRealtimeStart; 2714 } 2715 return time; 2716 } 2717 2718 @Override 2719 public long getBatteryRealtime(long curTime) { 2720 return getBatteryRealtimeLocked(curTime); 2721 } 2722 2723 private long getTcpBytes(long current, long[] dataBytes, int which) { 2724 if (which == STATS_LAST) { 2725 return dataBytes[STATS_LAST]; 2726 } else { 2727 if (which == STATS_UNPLUGGED) { 2728 if (dataBytes[STATS_UNPLUGGED] < 0) { 2729 return dataBytes[STATS_LAST]; 2730 } else { 2731 return current - dataBytes[STATS_UNPLUGGED]; 2732 } 2733 } else if (which == STATS_TOTAL) { 2734 return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_TOTAL]; 2735 } 2736 return current - dataBytes[STATS_CURRENT]; 2737 } 2738 } 2739 2740 /** Only STATS_UNPLUGGED works properly */ 2741 public long getMobileTcpBytesSent(int which) { 2742 return getTcpBytes(NetStat.getMobileTxBytes(), mMobileDataTx, which); 2743 } 2744 2745 /** Only STATS_UNPLUGGED works properly */ 2746 public long getMobileTcpBytesReceived(int which) { 2747 return getTcpBytes(NetStat.getMobileRxBytes(), mMobileDataRx, which); 2748 } 2749 2750 /** Only STATS_UNPLUGGED works properly */ 2751 public long getTotalTcpBytesSent(int which) { 2752 return getTcpBytes(NetStat.getTotalTxBytes(), mTotalDataTx, which); 2753 } 2754 2755 /** Only STATS_UNPLUGGED works properly */ 2756 public long getTotalTcpBytesReceived(int which) { 2757 return getTcpBytes(NetStat.getTotalRxBytes(), mTotalDataRx, which); 2758 } 2759 2760 @Override 2761 public int getDischargeStartLevel() { 2762 synchronized(this) { 2763 return getDischargeStartLevelLocked(); 2764 } 2765 } 2766 2767 public int getDischargeStartLevelLocked() { 2768 return mDischargeStartLevel; 2769 } 2770 2771 @Override 2772 public int getDischargeCurrentLevel() { 2773 synchronized(this) { 2774 return getDischargeCurrentLevelLocked(); 2775 } 2776 } 2777 2778 public int getDischargeCurrentLevelLocked() { 2779 return mDischargeCurrentLevel; 2780 } 2781 2782 /** 2783 * Retrieve the statistics object for a particular uid, creating if needed. 2784 */ 2785 public Uid getUidStatsLocked(int uid) { 2786 Uid u = mUidStats.get(uid); 2787 if (u == null) { 2788 u = new Uid(uid); 2789 mUidStats.put(uid, u); 2790 } 2791 return u; 2792 } 2793 2794 /** 2795 * Remove the statistics object for a particular uid. 2796 */ 2797 public void removeUidStatsLocked(int uid) { 2798 mUidStats.remove(uid); 2799 } 2800 2801 /** 2802 * Retrieve the statistics object for a particular process, creating 2803 * if needed. 2804 */ 2805 public Uid.Proc getProcessStatsLocked(int uid, String name) { 2806 Uid u = getUidStatsLocked(uid); 2807 return u.getProcessStatsLocked(name); 2808 } 2809 2810 /** 2811 * Retrieve the statistics object for a particular process, creating 2812 * if needed. 2813 */ 2814 public Uid.Pkg getPackageStatsLocked(int uid, String pkg) { 2815 Uid u = getUidStatsLocked(uid); 2816 return u.getPackageStatsLocked(pkg); 2817 } 2818 2819 /** 2820 * Retrieve the statistics object for a particular service, creating 2821 * if needed. 2822 */ 2823 public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) { 2824 Uid u = getUidStatsLocked(uid); 2825 return u.getServiceStatsLocked(pkg, name); 2826 } 2827 2828 public void writeLocked() { 2829 if ((mFile == null) || (mBackupFile == null)) { 2830 Log.w("BatteryStats", "writeLocked: no file associated with this instance"); 2831 return; 2832 } 2833 2834 // Keep the old file around until we know the new one has 2835 // been successfully written. 2836 if (mFile.exists()) { 2837 if (mBackupFile.exists()) { 2838 mBackupFile.delete(); 2839 } 2840 mFile.renameTo(mBackupFile); 2841 } 2842 2843 try { 2844 FileOutputStream stream = new FileOutputStream(mFile); 2845 Parcel out = Parcel.obtain(); 2846 writeSummaryToParcel(out); 2847 stream.write(out.marshall()); 2848 out.recycle(); 2849 2850 stream.flush(); 2851 stream.close(); 2852 mBackupFile.delete(); 2853 2854 mLastWriteTime = SystemClock.elapsedRealtime(); 2855 } catch (IOException e) { 2856 Log.e("BatteryStats", "Error writing battery statistics", e); 2857 } 2858 } 2859 2860 static byte[] readFully(FileInputStream stream) throws java.io.IOException { 2861 int pos = 0; 2862 int avail = stream.available(); 2863 byte[] data = new byte[avail]; 2864 while (true) { 2865 int amt = stream.read(data, pos, data.length-pos); 2866 //Log.i("foo", "Read " + amt + " bytes at " + pos 2867 // + " of avail " + data.length); 2868 if (amt <= 0) { 2869 //Log.i("foo", "**** FINISHED READING: pos=" + pos 2870 // + " len=" + data.length); 2871 return data; 2872 } 2873 pos += amt; 2874 avail = stream.available(); 2875 if (avail > data.length-pos) { 2876 byte[] newData = new byte[pos+avail]; 2877 System.arraycopy(data, 0, newData, 0, pos); 2878 data = newData; 2879 } 2880 } 2881 } 2882 2883 public void readLocked() { 2884 if ((mFile == null) || (mBackupFile == null)) { 2885 Log.w("BatteryStats", "readLocked: no file associated with this instance"); 2886 return; 2887 } 2888 2889 mUidStats.clear(); 2890 2891 FileInputStream stream = null; 2892 if (mBackupFile.exists()) { 2893 try { 2894 stream = new FileInputStream(mBackupFile); 2895 } catch (java.io.IOException e) { 2896 // We'll try for the normal settings file. 2897 } 2898 } 2899 2900 try { 2901 if (stream == null) { 2902 if (!mFile.exists()) { 2903 return; 2904 } 2905 stream = new FileInputStream(mFile); 2906 } 2907 2908 byte[] raw = readFully(stream); 2909 Parcel in = Parcel.obtain(); 2910 in.unmarshall(raw, 0, raw.length); 2911 in.setDataPosition(0); 2912 stream.close(); 2913 2914 readSummaryFromParcel(in); 2915 } catch(java.io.IOException e) { 2916 Log.e("BatteryStats", "Error reading battery statistics", e); 2917 } 2918 } 2919 2920 public int describeContents() { 2921 return 0; 2922 } 2923 2924 private void readSummaryFromParcel(Parcel in) { 2925 final int version = in.readInt(); 2926 if (version != VERSION) { 2927 Log.w("BatteryStats", "readFromParcel: version got " + version 2928 + ", expected " + VERSION + "; erasing old stats"); 2929 return; 2930 } 2931 2932 mStartCount = in.readInt(); 2933 mBatteryUptime = in.readLong(); 2934 mBatteryLastUptime = in.readLong(); 2935 mBatteryRealtime = in.readLong(); 2936 mBatteryLastRealtime = in.readLong(); 2937 mUptime = in.readLong(); 2938 mLastUptime = in.readLong(); 2939 mRealtime = in.readLong(); 2940 mLastRealtime = in.readLong(); 2941 mDischargeStartLevel = in.readInt(); 2942 mDischargeCurrentLevel = in.readInt(); 2943 2944 mStartCount++; 2945 2946 mScreenOn = false; 2947 mScreenOnTimer.readSummaryFromParcelLocked(in); 2948 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 2949 mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in); 2950 } 2951 mInputEventCounter.readSummaryFromParcelLocked(in); 2952 mPhoneOn = false; 2953 mPhoneOnTimer.readSummaryFromParcelLocked(in); 2954 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 2955 mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in); 2956 } 2957 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 2958 mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in); 2959 } 2960 mWifiOn = false; 2961 mWifiOnTimer.readSummaryFromParcelLocked(in); 2962 mWifiRunning = false; 2963 mWifiRunningTimer.readSummaryFromParcelLocked(in); 2964 mBluetoothOn = false; 2965 mBluetoothOnTimer.readSummaryFromParcelLocked(in); 2966 2967 int NKW = in.readInt(); 2968 for (int ikw = 0; ikw < NKW; ikw++) { 2969 if (in.readInt() != 0) { 2970 String kwltName = in.readString(); 2971 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in); 2972 } 2973 } 2974 2975 final int NU = in.readInt(); 2976 for (int iu = 0; iu < NU; iu++) { 2977 int uid = in.readInt(); 2978 Uid u = new Uid(uid); 2979 mUidStats.put(uid, u); 2980 2981 u.mWifiTurnedOn = false; 2982 u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in); 2983 u.mFullWifiLockOut = false; 2984 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); 2985 u.mAudioTurnedOn = false; 2986 u.mAudioTurnedOnTimer.readSummaryFromParcelLocked(in); 2987 u.mVideoTurnedOn = false; 2988 u.mVideoTurnedOnTimer.readSummaryFromParcelLocked(in); 2989 u.mScanWifiLockOut = false; 2990 u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); 2991 u.mWifiMulticastEnabled = false; 2992 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in); 2993 2994 if (in.readInt() != 0) { 2995 if (u.mUserActivityCounters == null) { 2996 u.initUserActivityLocked(); 2997 } 2998 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 2999 u.mUserActivityCounters[i].readSummaryFromParcelLocked(in); 3000 } 3001 } 3002 3003 int NW = in.readInt(); 3004 for (int iw = 0; iw < NW; iw++) { 3005 String wlName = in.readString(); 3006 if (in.readInt() != 0) { 3007 u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in); 3008 } 3009 if (in.readInt() != 0) { 3010 u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in); 3011 } 3012 if (in.readInt() != 0) { 3013 u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in); 3014 } 3015 } 3016 3017 int NP = in.readInt(); 3018 for (int is = 0; is < NP; is++) { 3019 int seNumber = in.readInt(); 3020 if (in.readInt() != 0) { 3021 u.getSensorTimerLocked(seNumber, true) 3022 .readSummaryFromParcelLocked(in); 3023 } 3024 } 3025 3026 NP = in.readInt(); 3027 for (int ip = 0; ip < NP; ip++) { 3028 String procName = in.readString(); 3029 Uid.Proc p = u.getProcessStatsLocked(procName); 3030 p.mUserTime = p.mLoadedUserTime = in.readLong(); 3031 p.mLastUserTime = in.readLong(); 3032 p.mSystemTime = p.mLoadedSystemTime = in.readLong(); 3033 p.mLastSystemTime = in.readLong(); 3034 p.mStarts = p.mLoadedStarts = in.readInt(); 3035 p.mLastStarts = in.readInt(); 3036 } 3037 3038 NP = in.readInt(); 3039 for (int ip = 0; ip < NP; ip++) { 3040 String pkgName = in.readString(); 3041 Uid.Pkg p = u.getPackageStatsLocked(pkgName); 3042 p.mWakeups = p.mLoadedWakeups = in.readInt(); 3043 p.mLastWakeups = in.readInt(); 3044 final int NS = in.readInt(); 3045 for (int is = 0; is < NS; is++) { 3046 String servName = in.readString(); 3047 Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName); 3048 s.mStartTime = s.mLoadedStartTime = in.readLong(); 3049 s.mLastStartTime = in.readLong(); 3050 s.mStarts = s.mLoadedStarts = in.readInt(); 3051 s.mLastStarts = in.readInt(); 3052 s.mLaunches = s.mLoadedLaunches = in.readInt(); 3053 s.mLastLaunches = in.readInt(); 3054 } 3055 } 3056 3057 u.mLoadedTcpBytesReceived = in.readLong(); 3058 u.mLoadedTcpBytesSent = in.readLong(); 3059 } 3060 } 3061 3062 /** 3063 * Writes a summary of the statistics to a Parcel, in a format suitable to be written to 3064 * disk. This format does not allow a lossless round-trip. 3065 * 3066 * @param out the Parcel to be written to. 3067 */ 3068 public void writeSummaryToParcel(Parcel out) { 3069 final long NOW_SYS = SystemClock.uptimeMillis() * 1000; 3070 final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; 3071 final long NOW = getBatteryUptimeLocked(NOW_SYS); 3072 final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS); 3073 3074 out.writeInt(VERSION); 3075 3076 out.writeInt(mStartCount); 3077 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_TOTAL)); 3078 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT)); 3079 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_TOTAL)); 3080 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT)); 3081 out.writeLong(computeUptime(NOW_SYS, STATS_TOTAL)); 3082 out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT)); 3083 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL)); 3084 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT)); 3085 out.writeInt(mDischargeStartLevel); 3086 out.writeInt(mDischargeCurrentLevel); 3087 3088 3089 mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3090 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3091 mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 3092 } 3093 mInputEventCounter.writeSummaryFromParcelLocked(out); 3094 mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3095 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3096 mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 3097 } 3098 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3099 mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 3100 } 3101 mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3102 mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3103 mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3104 3105 out.writeInt(mKernelWakelockStats.size()); 3106 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 3107 Timer kwlt = ent.getValue(); 3108 if (kwlt != null) { 3109 out.writeInt(1); 3110 out.writeString(ent.getKey()); 3111 ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL); 3112 } else { 3113 out.writeInt(0); 3114 } 3115 } 3116 3117 final int NU = mUidStats.size(); 3118 out.writeInt(NU); 3119 for (int iu = 0; iu < NU; iu++) { 3120 out.writeInt(mUidStats.keyAt(iu)); 3121 Uid u = mUidStats.valueAt(iu); 3122 3123 u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3124 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3125 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3126 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3127 u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3128 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3129 3130 if (u.mUserActivityCounters == null) { 3131 out.writeInt(0); 3132 } else { 3133 out.writeInt(1); 3134 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 3135 u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out); 3136 } 3137 } 3138 3139 int NW = u.mWakelockStats.size(); 3140 out.writeInt(NW); 3141 if (NW > 0) { 3142 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent 3143 : u.mWakelockStats.entrySet()) { 3144 out.writeString(ent.getKey()); 3145 Uid.Wakelock wl = ent.getValue(); 3146 if (wl.mTimerFull != null) { 3147 out.writeInt(1); 3148 wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL); 3149 } else { 3150 out.writeInt(0); 3151 } 3152 if (wl.mTimerPartial != null) { 3153 out.writeInt(1); 3154 wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL); 3155 } else { 3156 out.writeInt(0); 3157 } 3158 if (wl.mTimerWindow != null) { 3159 out.writeInt(1); 3160 wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL); 3161 } else { 3162 out.writeInt(0); 3163 } 3164 } 3165 } 3166 3167 int NSE = u.mSensorStats.size(); 3168 out.writeInt(NSE); 3169 if (NSE > 0) { 3170 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent 3171 : u.mSensorStats.entrySet()) { 3172 out.writeInt(ent.getKey()); 3173 Uid.Sensor se = ent.getValue(); 3174 if (se.mTimer != null) { 3175 out.writeInt(1); 3176 se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3177 } else { 3178 out.writeInt(0); 3179 } 3180 } 3181 } 3182 3183 int NP = u.mProcessStats.size(); 3184 out.writeInt(NP); 3185 if (NP > 0) { 3186 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent 3187 : u.mProcessStats.entrySet()) { 3188 out.writeString(ent.getKey()); 3189 Uid.Proc ps = ent.getValue(); 3190 out.writeLong(ps.mUserTime); 3191 out.writeLong(ps.mUserTime - ps.mLoadedUserTime); 3192 out.writeLong(ps.mSystemTime); 3193 out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime); 3194 out.writeInt(ps.mStarts); 3195 out.writeInt(ps.mStarts - ps.mLoadedStarts); 3196 } 3197 } 3198 3199 NP = u.mPackageStats.size(); 3200 out.writeInt(NP); 3201 if (NP > 0) { 3202 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent 3203 : u.mPackageStats.entrySet()) { 3204 out.writeString(ent.getKey()); 3205 Uid.Pkg ps = ent.getValue(); 3206 out.writeInt(ps.mWakeups); 3207 out.writeInt(ps.mWakeups - ps.mLoadedWakeups); 3208 final int NS = ps.mServiceStats.size(); 3209 out.writeInt(NS); 3210 if (NS > 0) { 3211 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent 3212 : ps.mServiceStats.entrySet()) { 3213 out.writeString(sent.getKey()); 3214 BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue(); 3215 long time = ss.getStartTimeToNowLocked(NOW); 3216 out.writeLong(time); 3217 out.writeLong(time - ss.mLoadedStartTime); 3218 out.writeInt(ss.mStarts); 3219 out.writeInt(ss.mStarts - ss.mLoadedStarts); 3220 out.writeInt(ss.mLaunches); 3221 out.writeInt(ss.mLaunches - ss.mLoadedLaunches); 3222 } 3223 } 3224 } 3225 } 3226 3227 out.writeLong(u.getTcpBytesReceived(STATS_TOTAL)); 3228 out.writeLong(u.getTcpBytesSent(STATS_TOTAL)); 3229 } 3230 } 3231 3232 public void readFromParcel(Parcel in) { 3233 readFromParcelLocked(in); 3234 } 3235 3236 void readFromParcelLocked(Parcel in) { 3237 int magic = in.readInt(); 3238 if (magic != MAGIC) { 3239 throw new ParcelFormatException("Bad magic number"); 3240 } 3241 3242 mStartCount = in.readInt(); 3243 mBatteryUptime = in.readLong(); 3244 mBatteryLastUptime = in.readLong(); 3245 mBatteryRealtime = in.readLong(); 3246 mBatteryLastRealtime = in.readLong(); 3247 mScreenOn = false; 3248 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in); 3249 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3250 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in); 3251 } 3252 mInputEventCounter = new Counter(mUnpluggables, in); 3253 mPhoneOn = false; 3254 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3255 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3256 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in); 3257 } 3258 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3259 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in); 3260 } 3261 mWifiOn = false; 3262 mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3263 mWifiRunning = false; 3264 mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3265 mBluetoothOn = false; 3266 mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3267 mUptime = in.readLong(); 3268 mUptimeStart = in.readLong(); 3269 mLastUptime = in.readLong(); 3270 mRealtime = in.readLong(); 3271 mRealtimeStart = in.readLong(); 3272 mLastRealtime = in.readLong(); 3273 mOnBattery = in.readInt() != 0; 3274 mOnBatteryInternal = false; // we are no longer really running. 3275 mTrackBatteryPastUptime = in.readLong(); 3276 mTrackBatteryUptimeStart = in.readLong(); 3277 mTrackBatteryPastRealtime = in.readLong(); 3278 mTrackBatteryRealtimeStart = in.readLong(); 3279 mUnpluggedBatteryUptime = in.readLong(); 3280 mUnpluggedBatteryRealtime = in.readLong(); 3281 mDischargeStartLevel = in.readInt(); 3282 mDischargeCurrentLevel = in.readInt(); 3283 mLastWriteTime = in.readLong(); 3284 3285 mMobileDataRx[STATS_LAST] = in.readLong(); 3286 mMobileDataRx[STATS_UNPLUGGED] = -1; 3287 mMobileDataTx[STATS_LAST] = in.readLong(); 3288 mMobileDataTx[STATS_UNPLUGGED] = -1; 3289 mTotalDataRx[STATS_LAST] = in.readLong(); 3290 mTotalDataRx[STATS_UNPLUGGED] = -1; 3291 mTotalDataTx[STATS_LAST] = in.readLong(); 3292 mTotalDataTx[STATS_UNPLUGGED] = -1; 3293 3294 mRadioDataUptime = in.readLong(); 3295 mRadioDataStart = -1; 3296 3297 mKernelWakelockStats.clear(); 3298 int NKW = in.readInt(); 3299 for (int ikw = 0; ikw < NKW; ikw++) { 3300 if (in.readInt() != 0) { 3301 String wakelockName = in.readString(); 3302 in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel 3303 SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in); 3304 mKernelWakelockStats.put(wakelockName, kwlt); 3305 } 3306 } 3307 3308 mPartialTimers.clear(); 3309 mFullTimers.clear(); 3310 mWindowTimers.clear(); 3311 3312 int numUids = in.readInt(); 3313 mUidStats.clear(); 3314 for (int i = 0; i < numUids; i++) { 3315 int uid = in.readInt(); 3316 Uid u = new Uid(uid); 3317 u.readFromParcelLocked(mUnpluggables, in); 3318 mUidStats.append(uid, u); 3319 } 3320 } 3321 3322 public void writeToParcel(Parcel out, int flags) { 3323 writeToParcelLocked(out, flags); 3324 } 3325 3326 @SuppressWarnings("unused") 3327 void writeToParcelLocked(Parcel out, int flags) { 3328 final long uSecUptime = SystemClock.uptimeMillis() * 1000; 3329 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 3330 final long batteryUptime = getBatteryUptimeLocked(uSecUptime); 3331 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 3332 3333 out.writeInt(MAGIC); 3334 out.writeInt(mStartCount); 3335 out.writeLong(mBatteryUptime); 3336 out.writeLong(mBatteryLastUptime); 3337 out.writeLong(mBatteryRealtime); 3338 out.writeLong(mBatteryLastRealtime); 3339 mScreenOnTimer.writeToParcel(out, batteryRealtime); 3340 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3341 mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime); 3342 } 3343 mInputEventCounter.writeToParcel(out); 3344 mPhoneOnTimer.writeToParcel(out, batteryRealtime); 3345 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3346 mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime); 3347 } 3348 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3349 mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime); 3350 } 3351 mWifiOnTimer.writeToParcel(out, batteryRealtime); 3352 mWifiRunningTimer.writeToParcel(out, batteryRealtime); 3353 mBluetoothOnTimer.writeToParcel(out, batteryRealtime); 3354 out.writeLong(mUptime); 3355 out.writeLong(mUptimeStart); 3356 out.writeLong(mLastUptime); 3357 out.writeLong(mRealtime); 3358 out.writeLong(mRealtimeStart); 3359 out.writeLong(mLastRealtime); 3360 out.writeInt(mOnBattery ? 1 : 0); 3361 out.writeLong(batteryUptime); 3362 out.writeLong(mTrackBatteryUptimeStart); 3363 out.writeLong(batteryRealtime); 3364 out.writeLong(mTrackBatteryRealtimeStart); 3365 out.writeLong(mUnpluggedBatteryUptime); 3366 out.writeLong(mUnpluggedBatteryRealtime); 3367 out.writeInt(mDischargeStartLevel); 3368 out.writeInt(mDischargeCurrentLevel); 3369 out.writeLong(mLastWriteTime); 3370 3371 out.writeLong(getMobileTcpBytesReceived(STATS_UNPLUGGED)); 3372 out.writeLong(getMobileTcpBytesSent(STATS_UNPLUGGED)); 3373 out.writeLong(getTotalTcpBytesReceived(STATS_UNPLUGGED)); 3374 out.writeLong(getTotalTcpBytesSent(STATS_UNPLUGGED)); 3375 3376 // Write radio uptime for data 3377 out.writeLong(getRadioDataUptimeMs()); 3378 3379 out.writeInt(mKernelWakelockStats.size()); 3380 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 3381 SamplingTimer kwlt = ent.getValue(); 3382 if (kwlt != null) { 3383 out.writeInt(1); 3384 out.writeString(ent.getKey()); 3385 Timer.writeTimerToParcel(out, kwlt, batteryRealtime); 3386 } else { 3387 out.writeInt(0); 3388 } 3389 } 3390 3391 int size = mUidStats.size(); 3392 out.writeInt(size); 3393 for (int i = 0; i < size; i++) { 3394 out.writeInt(mUidStats.keyAt(i)); 3395 Uid uid = mUidStats.valueAt(i); 3396 3397 uid.writeToParcelLocked(out, batteryRealtime); 3398 } 3399 } 3400 3401 public static final Parcelable.Creator<BatteryStatsImpl> CREATOR = 3402 new Parcelable.Creator<BatteryStatsImpl>() { 3403 public BatteryStatsImpl createFromParcel(Parcel in) { 3404 return new BatteryStatsImpl(in); 3405 } 3406 3407 public BatteryStatsImpl[] newArray(int size) { 3408 return new BatteryStatsImpl[size]; 3409 } 3410 }; 3411 3412 public void dumpLocked(PrintWriter pw) { 3413 if (DEBUG) { 3414 Printer pr = new PrintWriterPrinter(pw); 3415 pr.println("*** Screen timer:"); 3416 mScreenOnTimer.logState(pr, " "); 3417 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3418 pr.println("*** Screen brightness #" + i + ":"); 3419 mScreenBrightnessTimer[i].logState(pr, " "); 3420 } 3421 pr.println("*** Input event counter:"); 3422 mInputEventCounter.logState(pr, " "); 3423 pr.println("*** Phone timer:"); 3424 mPhoneOnTimer.logState(pr, " "); 3425 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3426 pr.println("*** Signal strength #" + i + ":"); 3427 mPhoneSignalStrengthsTimer[i].logState(pr, " "); 3428 } 3429 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3430 pr.println("*** Data connection type #" + i + ":"); 3431 mPhoneDataConnectionsTimer[i].logState(pr, " "); 3432 } 3433 pr.println("*** Wifi timer:"); 3434 mWifiOnTimer.logState(pr, " "); 3435 pr.println("*** WifiRunning timer:"); 3436 mWifiRunningTimer.logState(pr, " "); 3437 pr.println("*** Bluetooth timer:"); 3438 mBluetoothOnTimer.logState(pr, " "); 3439 } 3440 super.dumpLocked(pw); 3441 } 3442} 3443