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