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