BatteryStatsImpl.java revision 5347bd4cda2b6afc18f8acab48e52131f35ed13c
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 public void noteWifiMulticastEnabledLocked(int uid) { 1120 Uid u = mUidStats.get(uid); 1121 if (u != null) { 1122 u.noteWifiMulticastEnabledLocked(); 1123 } 1124 } 1125 1126 public void noteWifiMulticastDisabledLocked(int uid) { 1127 Uid u = mUidStats.get(uid); 1128 if (u != null) { 1129 u.noteWifiMulticastDisabledLocked(); 1130 } 1131 } 1132 1133 @Override public long getScreenOnTime(long batteryRealtime, int which) { 1134 return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which); 1135 } 1136 1137 @Override public long getScreenBrightnessTime(int brightnessBin, 1138 long batteryRealtime, int which) { 1139 return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked( 1140 batteryRealtime, which); 1141 } 1142 1143 @Override public int getInputEventCount(int which) { 1144 return mInputEventCounter.getCountLocked(which); 1145 } 1146 1147 @Override public long getPhoneOnTime(long batteryRealtime, int which) { 1148 return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which); 1149 } 1150 1151 @Override public long getPhoneSignalStrengthTime(int strengthBin, 1152 long batteryRealtime, int which) { 1153 return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked( 1154 batteryRealtime, which); 1155 } 1156 1157 @Override public int getPhoneSignalStrengthCount(int dataType, int which) { 1158 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1159 } 1160 1161 @Override public long getPhoneDataConnectionTime(int dataType, 1162 long batteryRealtime, int which) { 1163 return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked( 1164 batteryRealtime, which); 1165 } 1166 1167 @Override public int getPhoneDataConnectionCount(int dataType, int which) { 1168 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1169 } 1170 1171 @Override public long getWifiOnTime(long batteryRealtime, int which) { 1172 return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which); 1173 } 1174 1175 @Override public long getWifiRunningTime(long batteryRealtime, int which) { 1176 return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which); 1177 } 1178 1179 @Override public long getBluetoothOnTime(long batteryRealtime, int which) { 1180 return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which); 1181 } 1182 1183 @Override public boolean getIsOnBattery() { 1184 return mOnBattery; 1185 } 1186 1187 @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() { 1188 return mUidStats; 1189 } 1190 1191 /** 1192 * The statistics associated with a particular uid. 1193 */ 1194 public final class Uid extends BatteryStats.Uid { 1195 1196 final int mUid; 1197 long mLoadedTcpBytesReceived; 1198 long mLoadedTcpBytesSent; 1199 long mCurrentTcpBytesReceived; 1200 long mCurrentTcpBytesSent; 1201 long mTcpBytesReceivedAtLastUnplug; 1202 long mTcpBytesSentAtLastUnplug; 1203 1204 // These are not saved/restored when parcelling, since we want 1205 // to return from the parcel with a snapshot of the state. 1206 long mStartedTcpBytesReceived = -1; 1207 long mStartedTcpBytesSent = -1; 1208 1209 boolean mWifiTurnedOn; 1210 StopwatchTimer mWifiTurnedOnTimer; 1211 1212 boolean mFullWifiLockOut; 1213 StopwatchTimer mFullWifiLockTimer; 1214 1215 boolean mScanWifiLockOut; 1216 StopwatchTimer mScanWifiLockTimer; 1217 1218 boolean mWifiMulticastEnabled; 1219 StopwatchTimer mWifiMulticastTimer; 1220 1221 Counter[] mUserActivityCounters; 1222 1223 /** 1224 * The statistics we have collected for this uid's wake locks. 1225 */ 1226 final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>(); 1227 1228 /** 1229 * The statistics we have collected for this uid's sensor activations. 1230 */ 1231 final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>(); 1232 1233 /** 1234 * The statistics we have collected for this uid's processes. 1235 */ 1236 final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>(); 1237 1238 /** 1239 * The statistics we have collected for this uid's processes. 1240 */ 1241 final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>(); 1242 1243 public Uid(int uid) { 1244 mUid = uid; 1245 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables); 1246 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables); 1247 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables); 1248 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1249 null, mUnpluggables); 1250 } 1251 1252 @Override 1253 public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() { 1254 return mWakelockStats; 1255 } 1256 1257 @Override 1258 public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() { 1259 return mSensorStats; 1260 } 1261 1262 @Override 1263 public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() { 1264 return mProcessStats; 1265 } 1266 1267 @Override 1268 public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { 1269 return mPackageStats; 1270 } 1271 1272 public int getUid() { 1273 return mUid; 1274 } 1275 1276 public long getTcpBytesReceived(int which) { 1277 if (which == STATS_LAST) { 1278 return mLoadedTcpBytesReceived; 1279 } else { 1280 long current = computeCurrentTcpBytesReceived(); 1281 if (which == STATS_UNPLUGGED) { 1282 current -= mTcpBytesReceivedAtLastUnplug; 1283 } else if (which == STATS_TOTAL) { 1284 current += mLoadedTcpBytesReceived; 1285 } 1286 return current; 1287 } 1288 } 1289 1290 public long computeCurrentTcpBytesReceived() { 1291 return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0 1292 ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0); 1293 } 1294 1295 public long getTcpBytesSent(int which) { 1296 if (which == STATS_LAST) { 1297 return mLoadedTcpBytesSent; 1298 } else { 1299 long current = computeCurrentTcpBytesSent(); 1300 if (which == STATS_UNPLUGGED) { 1301 current -= mTcpBytesSentAtLastUnplug; 1302 } else if (which == STATS_TOTAL) { 1303 current += mLoadedTcpBytesSent; 1304 } 1305 return current; 1306 } 1307 } 1308 1309 @Override 1310 public void noteWifiTurnedOnLocked() { 1311 if (!mWifiTurnedOn) { 1312 mWifiTurnedOn = true; 1313 mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1314 } 1315 } 1316 1317 @Override 1318 public void noteWifiTurnedOffLocked() { 1319 if (mWifiTurnedOn) { 1320 mWifiTurnedOn = false; 1321 mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1322 } 1323 } 1324 1325 @Override 1326 public void noteFullWifiLockAcquiredLocked() { 1327 if (!mFullWifiLockOut) { 1328 mFullWifiLockOut = true; 1329 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 1330 } 1331 } 1332 1333 @Override 1334 public void noteFullWifiLockReleasedLocked() { 1335 if (mFullWifiLockOut) { 1336 mFullWifiLockOut = false; 1337 mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 1338 } 1339 } 1340 1341 @Override 1342 public void noteScanWifiLockAcquiredLocked() { 1343 if (!mScanWifiLockOut) { 1344 mScanWifiLockOut = true; 1345 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 1346 } 1347 } 1348 1349 @Override 1350 public void noteScanWifiLockReleasedLocked() { 1351 if (mScanWifiLockOut) { 1352 mScanWifiLockOut = false; 1353 mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 1354 } 1355 } 1356 1357 @Override 1358 public void noteWifiMulticastEnabledLocked() { 1359 if (!mWifiMulticastEnabled) { 1360 mWifiMulticastEnabled = true; 1361 mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this); 1362 } 1363 } 1364 1365 @Override 1366 public void noteWifiMulticastDisabledLocked() { 1367 if (mWifiMulticastEnabled) { 1368 mWifiMulticastEnabled = false; 1369 mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this); 1370 } 1371 } 1372 1373 @Override 1374 public long getWifiTurnedOnTime(long batteryRealtime, int which) { 1375 return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1376 } 1377 1378 @Override 1379 public long getFullWifiLockTime(long batteryRealtime, int which) { 1380 return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 1381 } 1382 1383 @Override 1384 public long getScanWifiLockTime(long batteryRealtime, int which) { 1385 return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 1386 } 1387 1388 @Override 1389 public long getWifiMulticastTime(long batteryRealtime, int which) { 1390 return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime, 1391 which); 1392 } 1393 1394 @Override 1395 public void noteUserActivityLocked(int type) { 1396 if (mUserActivityCounters == null) { 1397 initUserActivityLocked(); 1398 } 1399 if (type < 0) type = 0; 1400 else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1; 1401 mUserActivityCounters[type].stepLocked(); 1402 } 1403 1404 @Override 1405 public boolean hasUserActivity() { 1406 return mUserActivityCounters != null; 1407 } 1408 1409 @Override 1410 public int getUserActivityCount(int type, int which) { 1411 if (mUserActivityCounters == null) { 1412 return 0; 1413 } 1414 return mUserActivityCounters[type].getCountLocked(which); 1415 } 1416 1417 void initUserActivityLocked() { 1418 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 1419 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1420 mUserActivityCounters[i] = new Counter(mUnpluggables); 1421 } 1422 } 1423 1424 public long computeCurrentTcpBytesSent() { 1425 return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0 1426 ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0); 1427 } 1428 1429 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1430 out.writeInt(mWakelockStats.size()); 1431 for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) { 1432 out.writeString(wakelockEntry.getKey()); 1433 Uid.Wakelock wakelock = wakelockEntry.getValue(); 1434 wakelock.writeToParcelLocked(out, batteryRealtime); 1435 } 1436 1437 out.writeInt(mSensorStats.size()); 1438 for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) { 1439 out.writeInt(sensorEntry.getKey()); 1440 Uid.Sensor sensor = sensorEntry.getValue(); 1441 sensor.writeToParcelLocked(out, batteryRealtime); 1442 } 1443 1444 out.writeInt(mProcessStats.size()); 1445 for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) { 1446 out.writeString(procEntry.getKey()); 1447 Uid.Proc proc = procEntry.getValue(); 1448 proc.writeToParcelLocked(out); 1449 } 1450 1451 out.writeInt(mPackageStats.size()); 1452 for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) { 1453 out.writeString(pkgEntry.getKey()); 1454 Uid.Pkg pkg = pkgEntry.getValue(); 1455 pkg.writeToParcelLocked(out); 1456 } 1457 1458 out.writeLong(mLoadedTcpBytesReceived); 1459 out.writeLong(mLoadedTcpBytesSent); 1460 out.writeLong(computeCurrentTcpBytesReceived()); 1461 out.writeLong(computeCurrentTcpBytesSent()); 1462 out.writeLong(mTcpBytesReceivedAtLastUnplug); 1463 out.writeLong(mTcpBytesSentAtLastUnplug); 1464 mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime); 1465 mFullWifiLockTimer.writeToParcel(out, batteryRealtime); 1466 mScanWifiLockTimer.writeToParcel(out, batteryRealtime); 1467 mWifiMulticastTimer.writeToParcel(out, batteryRealtime); 1468 if (mUserActivityCounters == null) { 1469 out.writeInt(0); 1470 } else { 1471 out.writeInt(1); 1472 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1473 mUserActivityCounters[i].writeToParcel(out); 1474 } 1475 } 1476 } 1477 1478 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1479 int numWakelocks = in.readInt(); 1480 mWakelockStats.clear(); 1481 for (int j = 0; j < numWakelocks; j++) { 1482 String wakelockName = in.readString(); 1483 Uid.Wakelock wakelock = new Wakelock(); 1484 wakelock.readFromParcelLocked(unpluggables, in); 1485 mWakelockStats.put(wakelockName, wakelock); 1486 } 1487 1488 int numSensors = in.readInt(); 1489 mSensorStats.clear(); 1490 for (int k = 0; k < numSensors; k++) { 1491 int sensorNumber = in.readInt(); 1492 Uid.Sensor sensor = new Sensor(sensorNumber); 1493 sensor.readFromParcelLocked(mUnpluggables, in); 1494 mSensorStats.put(sensorNumber, sensor); 1495 } 1496 1497 int numProcs = in.readInt(); 1498 mProcessStats.clear(); 1499 for (int k = 0; k < numProcs; k++) { 1500 String processName = in.readString(); 1501 Uid.Proc proc = new Proc(); 1502 proc.readFromParcelLocked(in); 1503 mProcessStats.put(processName, proc); 1504 } 1505 1506 int numPkgs = in.readInt(); 1507 mPackageStats.clear(); 1508 for (int l = 0; l < numPkgs; l++) { 1509 String packageName = in.readString(); 1510 Uid.Pkg pkg = new Pkg(); 1511 pkg.readFromParcelLocked(in); 1512 mPackageStats.put(packageName, pkg); 1513 } 1514 1515 mLoadedTcpBytesReceived = in.readLong(); 1516 mLoadedTcpBytesSent = in.readLong(); 1517 mCurrentTcpBytesReceived = in.readLong(); 1518 mCurrentTcpBytesSent = in.readLong(); 1519 mTcpBytesReceivedAtLastUnplug = in.readLong(); 1520 mTcpBytesSentAtLastUnplug = in.readLong(); 1521 mWifiTurnedOn = false; 1522 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables, in); 1523 mFullWifiLockOut = false; 1524 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in); 1525 mScanWifiLockOut = false; 1526 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in); 1527 mWifiMulticastEnabled = false; 1528 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1529 null, mUnpluggables, in); 1530 if (in.readInt() == 0) { 1531 mUserActivityCounters = null; 1532 } else { 1533 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 1534 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1535 mUserActivityCounters[i] = new Counter(mUnpluggables, in); 1536 } 1537 } 1538 } 1539 1540 /** 1541 * The statistics associated with a particular wake lock. 1542 */ 1543 public final class Wakelock extends BatteryStats.Uid.Wakelock { 1544 /** 1545 * How long (in ms) this uid has been keeping the device partially awake. 1546 */ 1547 StopwatchTimer mTimerPartial; 1548 1549 /** 1550 * How long (in ms) this uid has been keeping the device fully awake. 1551 */ 1552 StopwatchTimer mTimerFull; 1553 1554 /** 1555 * How long (in ms) this uid has had a window keeping the device awake. 1556 */ 1557 StopwatchTimer mTimerWindow; 1558 1559 /** 1560 * Reads a possibly null Timer from a Parcel. The timer is associated with the 1561 * proper timer pool from the given BatteryStatsImpl object. 1562 * 1563 * @param in the Parcel to be read from. 1564 * return a new Timer, or null. 1565 */ 1566 private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, 1567 ArrayList<Unpluggable> unpluggables, Parcel in) { 1568 if (in.readInt() == 0) { 1569 return null; 1570 } 1571 1572 return new StopwatchTimer(type, pool, unpluggables, in); 1573 } 1574 1575 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1576 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL, 1577 mPartialTimers, unpluggables, in); 1578 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, 1579 mFullTimers, unpluggables, in); 1580 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, 1581 mWindowTimers, unpluggables, in); 1582 } 1583 1584 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1585 Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime); 1586 Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime); 1587 Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime); 1588 } 1589 1590 @Override 1591 public Timer getWakeTime(int type) { 1592 switch (type) { 1593 case WAKE_TYPE_FULL: return mTimerFull; 1594 case WAKE_TYPE_PARTIAL: return mTimerPartial; 1595 case WAKE_TYPE_WINDOW: return mTimerWindow; 1596 default: throw new IllegalArgumentException("type = " + type); 1597 } 1598 } 1599 } 1600 1601 public final class Sensor extends BatteryStats.Uid.Sensor { 1602 final int mHandle; 1603 StopwatchTimer mTimer; 1604 1605 public Sensor(int handle) { 1606 mHandle = handle; 1607 } 1608 1609 private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables, 1610 Parcel in) { 1611 if (in.readInt() == 0) { 1612 return null; 1613 } 1614 1615 ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle); 1616 if (pool == null) { 1617 pool = new ArrayList<StopwatchTimer>(); 1618 mSensorTimers.put(mHandle, pool); 1619 } 1620 return new StopwatchTimer(0, pool, unpluggables, in); 1621 } 1622 1623 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1624 mTimer = readTimerFromParcel(unpluggables, in); 1625 } 1626 1627 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1628 Timer.writeTimerToParcel(out, mTimer, batteryRealtime); 1629 } 1630 1631 @Override 1632 public Timer getSensorTime() { 1633 return mTimer; 1634 } 1635 1636 public int getHandle() { 1637 return mHandle; 1638 } 1639 } 1640 1641 /** 1642 * The statistics associated with a particular process. 1643 */ 1644 public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable { 1645 /** 1646 * Total time (in 1/100 sec) spent executing in user code. 1647 */ 1648 long mUserTime; 1649 1650 /** 1651 * Total time (in 1/100 sec) spent executing in kernel code. 1652 */ 1653 long mSystemTime; 1654 1655 /** 1656 * Number of times the process has been started. 1657 */ 1658 int mStarts; 1659 1660 /** 1661 * The amount of user time loaded from a previous save. 1662 */ 1663 long mLoadedUserTime; 1664 1665 /** 1666 * The amount of system time loaded from a previous save. 1667 */ 1668 long mLoadedSystemTime; 1669 1670 /** 1671 * The number of times the process has started from a previous save. 1672 */ 1673 int mLoadedStarts; 1674 1675 /** 1676 * The amount of user time loaded from the previous run. 1677 */ 1678 long mLastUserTime; 1679 1680 /** 1681 * The amount of system time loaded from the previous run. 1682 */ 1683 long mLastSystemTime; 1684 1685 /** 1686 * The number of times the process has started from the previous run. 1687 */ 1688 int mLastStarts; 1689 1690 /** 1691 * The amount of user time when last unplugged. 1692 */ 1693 long mUnpluggedUserTime; 1694 1695 /** 1696 * The amount of system time when last unplugged. 1697 */ 1698 long mUnpluggedSystemTime; 1699 1700 /** 1701 * The number of times the process has started before unplugged. 1702 */ 1703 int mUnpluggedStarts; 1704 1705 Proc() { 1706 mUnpluggables.add(this); 1707 } 1708 1709 public void unplug(long batteryUptime, long batteryRealtime) { 1710 mUnpluggedUserTime = mUserTime; 1711 mUnpluggedSystemTime = mSystemTime; 1712 mUnpluggedStarts = mStarts; 1713 } 1714 1715 public void plug(long batteryUptime, long batteryRealtime) { 1716 } 1717 1718 void writeToParcelLocked(Parcel out) { 1719 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 1720 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 1721 1722 out.writeLong(mUserTime); 1723 out.writeLong(mSystemTime); 1724 out.writeInt(mStarts); 1725 out.writeLong(mLoadedUserTime); 1726 out.writeLong(mLoadedSystemTime); 1727 out.writeInt(mLoadedStarts); 1728 out.writeLong(mLastUserTime); 1729 out.writeLong(mLastSystemTime); 1730 out.writeInt(mLastStarts); 1731 out.writeLong(mUnpluggedUserTime); 1732 out.writeLong(mUnpluggedSystemTime); 1733 out.writeInt(mUnpluggedStarts); 1734 } 1735 1736 void readFromParcelLocked(Parcel in) { 1737 mUserTime = in.readLong(); 1738 mSystemTime = in.readLong(); 1739 mStarts = in.readInt(); 1740 mLoadedUserTime = in.readLong(); 1741 mLoadedSystemTime = in.readLong(); 1742 mLoadedStarts = in.readInt(); 1743 mLastUserTime = in.readLong(); 1744 mLastSystemTime = in.readLong(); 1745 mLastStarts = in.readInt(); 1746 mUnpluggedUserTime = in.readLong(); 1747 mUnpluggedSystemTime = in.readLong(); 1748 mUnpluggedStarts = in.readInt(); 1749 } 1750 1751 public BatteryStatsImpl getBatteryStats() { 1752 return BatteryStatsImpl.this; 1753 } 1754 1755 public void addCpuTimeLocked(int utime, int stime) { 1756 mUserTime += utime; 1757 mSystemTime += stime; 1758 } 1759 1760 public void incStartsLocked() { 1761 mStarts++; 1762 } 1763 1764 @Override 1765 public long getUserTime(int which) { 1766 long val; 1767 if (which == STATS_LAST) { 1768 val = mLastUserTime; 1769 } else { 1770 val = mUserTime; 1771 if (which == STATS_CURRENT) { 1772 val -= mLoadedUserTime; 1773 } else if (which == STATS_UNPLUGGED) { 1774 val -= mUnpluggedUserTime; 1775 } 1776 } 1777 return val; 1778 } 1779 1780 @Override 1781 public long getSystemTime(int which) { 1782 long val; 1783 if (which == STATS_LAST) { 1784 val = mLastSystemTime; 1785 } else { 1786 val = mSystemTime; 1787 if (which == STATS_CURRENT) { 1788 val -= mLoadedSystemTime; 1789 } else if (which == STATS_UNPLUGGED) { 1790 val -= mUnpluggedSystemTime; 1791 } 1792 } 1793 return val; 1794 } 1795 1796 @Override 1797 public int getStarts(int which) { 1798 int val; 1799 if (which == STATS_LAST) { 1800 val = mLastStarts; 1801 } else { 1802 val = mStarts; 1803 if (which == STATS_CURRENT) { 1804 val -= mLoadedStarts; 1805 } else if (which == STATS_UNPLUGGED) { 1806 val -= mUnpluggedStarts; 1807 } 1808 } 1809 return val; 1810 } 1811 } 1812 1813 /** 1814 * The statistics associated with a particular package. 1815 */ 1816 public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable { 1817 /** 1818 * Number of times this package has done something that could wake up the 1819 * device from sleep. 1820 */ 1821 int mWakeups; 1822 1823 /** 1824 * Number of things that could wake up the device loaded from a 1825 * previous save. 1826 */ 1827 int mLoadedWakeups; 1828 1829 /** 1830 * Number of things that could wake up the device as of the 1831 * last run. 1832 */ 1833 int mLastWakeups; 1834 1835 /** 1836 * Number of things that could wake up the device as of the 1837 * last run. 1838 */ 1839 int mUnpluggedWakeups; 1840 1841 /** 1842 * The statics we have collected for this package's services. 1843 */ 1844 final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>(); 1845 1846 Pkg() { 1847 mUnpluggables.add(this); 1848 } 1849 1850 public void unplug(long batteryUptime, long batteryRealtime) { 1851 mUnpluggedWakeups = mWakeups; 1852 } 1853 1854 public void plug(long batteryUptime, long batteryRealtime) { 1855 } 1856 1857 void readFromParcelLocked(Parcel in) { 1858 mWakeups = in.readInt(); 1859 mLoadedWakeups = in.readInt(); 1860 mLastWakeups = in.readInt(); 1861 mUnpluggedWakeups = in.readInt(); 1862 1863 int numServs = in.readInt(); 1864 mServiceStats.clear(); 1865 for (int m = 0; m < numServs; m++) { 1866 String serviceName = in.readString(); 1867 Uid.Pkg.Serv serv = new Serv(); 1868 mServiceStats.put(serviceName, serv); 1869 1870 serv.readFromParcelLocked(in); 1871 } 1872 } 1873 1874 void writeToParcelLocked(Parcel out) { 1875 out.writeInt(mWakeups); 1876 out.writeInt(mLoadedWakeups); 1877 out.writeInt(mLastWakeups); 1878 out.writeInt(mUnpluggedWakeups); 1879 1880 out.writeInt(mServiceStats.size()); 1881 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) { 1882 out.writeString(servEntry.getKey()); 1883 Uid.Pkg.Serv serv = servEntry.getValue(); 1884 1885 serv.writeToParcelLocked(out); 1886 } 1887 } 1888 1889 @Override 1890 public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() { 1891 return mServiceStats; 1892 } 1893 1894 @Override 1895 public int getWakeups(int which) { 1896 int val; 1897 if (which == STATS_LAST) { 1898 val = mLastWakeups; 1899 } else { 1900 val = mWakeups; 1901 if (which == STATS_CURRENT) { 1902 val -= mLoadedWakeups; 1903 } else if (which == STATS_UNPLUGGED) { 1904 val -= mUnpluggedWakeups; 1905 } 1906 } 1907 1908 return val; 1909 } 1910 1911 /** 1912 * The statistics associated with a particular service. 1913 */ 1914 public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable { 1915 /** 1916 * Total time (ms in battery uptime) the service has been left started. 1917 */ 1918 long mStartTime; 1919 1920 /** 1921 * If service has been started and not yet stopped, this is 1922 * when it was started. 1923 */ 1924 long mRunningSince; 1925 1926 /** 1927 * True if we are currently running. 1928 */ 1929 boolean mRunning; 1930 1931 /** 1932 * Total number of times startService() has been called. 1933 */ 1934 int mStarts; 1935 1936 /** 1937 * Total time (ms in battery uptime) the service has been left launched. 1938 */ 1939 long mLaunchedTime; 1940 1941 /** 1942 * If service has been launched and not yet exited, this is 1943 * when it was launched (ms in battery uptime). 1944 */ 1945 long mLaunchedSince; 1946 1947 /** 1948 * True if we are currently launched. 1949 */ 1950 boolean mLaunched; 1951 1952 /** 1953 * Total number times the service has been launched. 1954 */ 1955 int mLaunches; 1956 1957 /** 1958 * The amount of time spent started loaded from a previous save 1959 * (ms in battery uptime). 1960 */ 1961 long mLoadedStartTime; 1962 1963 /** 1964 * The number of starts loaded from a previous save. 1965 */ 1966 int mLoadedStarts; 1967 1968 /** 1969 * The number of launches loaded from a previous save. 1970 */ 1971 int mLoadedLaunches; 1972 1973 /** 1974 * The amount of time spent started as of the last run (ms 1975 * in battery uptime). 1976 */ 1977 long mLastStartTime; 1978 1979 /** 1980 * The number of starts as of the last run. 1981 */ 1982 int mLastStarts; 1983 1984 /** 1985 * The number of launches as of the last run. 1986 */ 1987 int mLastLaunches; 1988 1989 /** 1990 * The amount of time spent started when last unplugged (ms 1991 * in battery uptime). 1992 */ 1993 long mUnpluggedStartTime; 1994 1995 /** 1996 * The number of starts when last unplugged. 1997 */ 1998 int mUnpluggedStarts; 1999 2000 /** 2001 * The number of launches when last unplugged. 2002 */ 2003 int mUnpluggedLaunches; 2004 2005 Serv() { 2006 mUnpluggables.add(this); 2007 } 2008 2009 public void unplug(long batteryUptime, long batteryRealtime) { 2010 mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime); 2011 mUnpluggedStarts = mStarts; 2012 mUnpluggedLaunches = mLaunches; 2013 } 2014 2015 public void plug(long batteryUptime, long batteryRealtime) { 2016 } 2017 2018 void readFromParcelLocked(Parcel in) { 2019 mStartTime = in.readLong(); 2020 mRunningSince = in.readLong(); 2021 mRunning = in.readInt() != 0; 2022 mStarts = in.readInt(); 2023 mLaunchedTime = in.readLong(); 2024 mLaunchedSince = in.readLong(); 2025 mLaunched = in.readInt() != 0; 2026 mLaunches = in.readInt(); 2027 mLoadedStartTime = in.readLong(); 2028 mLoadedStarts = in.readInt(); 2029 mLoadedLaunches = in.readInt(); 2030 mLastStartTime = in.readLong(); 2031 mLastStarts = in.readInt(); 2032 mLastLaunches = in.readInt(); 2033 mUnpluggedStartTime = in.readLong(); 2034 mUnpluggedStarts = in.readInt(); 2035 mUnpluggedLaunches = in.readInt(); 2036 } 2037 2038 void writeToParcelLocked(Parcel out) { 2039 out.writeLong(mStartTime); 2040 out.writeLong(mRunningSince); 2041 out.writeInt(mRunning ? 1 : 0); 2042 out.writeInt(mStarts); 2043 out.writeLong(mLaunchedTime); 2044 out.writeLong(mLaunchedSince); 2045 out.writeInt(mLaunched ? 1 : 0); 2046 out.writeInt(mLaunches); 2047 out.writeLong(mLoadedStartTime); 2048 out.writeInt(mLoadedStarts); 2049 out.writeInt(mLoadedLaunches); 2050 out.writeLong(mLastStartTime); 2051 out.writeInt(mLastStarts); 2052 out.writeInt(mLastLaunches); 2053 out.writeLong(mUnpluggedStartTime); 2054 out.writeInt(mUnpluggedStarts); 2055 out.writeInt(mUnpluggedLaunches); 2056 } 2057 2058 long getLaunchTimeToNowLocked(long batteryUptime) { 2059 if (!mLaunched) return mLaunchedTime; 2060 return mLaunchedTime + batteryUptime - mLaunchedSince; 2061 } 2062 2063 long getStartTimeToNowLocked(long batteryUptime) { 2064 if (!mRunning) return mStartTime; 2065 return mStartTime + batteryUptime - mRunningSince; 2066 } 2067 2068 public void startLaunchedLocked() { 2069 if (!mLaunched) { 2070 mLaunches++; 2071 mLaunchedSince = getBatteryUptimeLocked(); 2072 mLaunched = true; 2073 } 2074 } 2075 2076 public void stopLaunchedLocked() { 2077 if (mLaunched) { 2078 long time = getBatteryUptimeLocked() - mLaunchedSince; 2079 if (time > 0) { 2080 mLaunchedTime += time; 2081 } else { 2082 mLaunches--; 2083 } 2084 mLaunched = false; 2085 } 2086 } 2087 2088 public void startRunningLocked() { 2089 if (!mRunning) { 2090 mStarts++; 2091 mRunningSince = getBatteryUptimeLocked(); 2092 mRunning = true; 2093 } 2094 } 2095 2096 public void stopRunningLocked() { 2097 if (mRunning) { 2098 long time = getBatteryUptimeLocked() - mRunningSince; 2099 if (time > 0) { 2100 mStartTime += time; 2101 } else { 2102 mStarts--; 2103 } 2104 mRunning = false; 2105 } 2106 } 2107 2108 public BatteryStatsImpl getBatteryStats() { 2109 return BatteryStatsImpl.this; 2110 } 2111 2112 @Override 2113 public int getLaunches(int which) { 2114 int val; 2115 2116 if (which == STATS_LAST) { 2117 val = mLastLaunches; 2118 } else { 2119 val = mLaunches; 2120 if (which == STATS_CURRENT) { 2121 val -= mLoadedLaunches; 2122 } else if (which == STATS_UNPLUGGED) { 2123 val -= mUnpluggedLaunches; 2124 } 2125 } 2126 2127 return val; 2128 } 2129 2130 @Override 2131 public long getStartTime(long now, int which) { 2132 long val; 2133 if (which == STATS_LAST) { 2134 val = mLastStartTime; 2135 } else { 2136 val = getStartTimeToNowLocked(now); 2137 if (which == STATS_CURRENT) { 2138 val -= mLoadedStartTime; 2139 } else if (which == STATS_UNPLUGGED) { 2140 val -= mUnpluggedStartTime; 2141 } 2142 } 2143 2144 return val; 2145 } 2146 2147 @Override 2148 public int getStarts(int which) { 2149 int val; 2150 if (which == STATS_LAST) { 2151 val = mLastStarts; 2152 } else { 2153 val = mStarts; 2154 if (which == STATS_CURRENT) { 2155 val -= mLoadedStarts; 2156 } else if (which == STATS_UNPLUGGED) { 2157 val -= mUnpluggedStarts; 2158 } 2159 } 2160 2161 return val; 2162 } 2163 } 2164 2165 public BatteryStatsImpl getBatteryStats() { 2166 return BatteryStatsImpl.this; 2167 } 2168 2169 public void incWakeupsLocked() { 2170 mWakeups++; 2171 } 2172 2173 final Serv newServiceStatsLocked() { 2174 return new Serv(); 2175 } 2176 } 2177 2178 /** 2179 * Retrieve the statistics object for a particular process, creating 2180 * if needed. 2181 */ 2182 public Proc getProcessStatsLocked(String name) { 2183 Proc ps = mProcessStats.get(name); 2184 if (ps == null) { 2185 ps = new Proc(); 2186 mProcessStats.put(name, ps); 2187 } 2188 2189 return ps; 2190 } 2191 2192 /** 2193 * Retrieve the statistics object for a particular service, creating 2194 * if needed. 2195 */ 2196 public Pkg getPackageStatsLocked(String name) { 2197 Pkg ps = mPackageStats.get(name); 2198 if (ps == null) { 2199 ps = new Pkg(); 2200 mPackageStats.put(name, ps); 2201 } 2202 2203 return ps; 2204 } 2205 2206 /** 2207 * Retrieve the statistics object for a particular service, creating 2208 * if needed. 2209 */ 2210 public Pkg.Serv getServiceStatsLocked(String pkg, String serv) { 2211 Pkg ps = getPackageStatsLocked(pkg); 2212 Pkg.Serv ss = ps.mServiceStats.get(serv); 2213 if (ss == null) { 2214 ss = ps.newServiceStatsLocked(); 2215 ps.mServiceStats.put(serv, ss); 2216 } 2217 2218 return ss; 2219 } 2220 2221 public StopwatchTimer getWakeTimerLocked(String name, int type) { 2222 Wakelock wl = mWakelockStats.get(name); 2223 if (wl == null) { 2224 wl = new Wakelock(); 2225 mWakelockStats.put(name, wl); 2226 } 2227 StopwatchTimer t = null; 2228 switch (type) { 2229 case WAKE_TYPE_PARTIAL: 2230 t = wl.mTimerPartial; 2231 if (t == null) { 2232 t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables); 2233 wl.mTimerPartial = t; 2234 } 2235 return t; 2236 case WAKE_TYPE_FULL: 2237 t = wl.mTimerFull; 2238 if (t == null) { 2239 t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables); 2240 wl.mTimerFull = t; 2241 } 2242 return t; 2243 case WAKE_TYPE_WINDOW: 2244 t = wl.mTimerWindow; 2245 if (t == null) { 2246 t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables); 2247 wl.mTimerWindow = t; 2248 } 2249 return t; 2250 default: 2251 throw new IllegalArgumentException("type=" + type); 2252 } 2253 } 2254 2255 public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) { 2256 Sensor se = mSensorStats.get(sensor); 2257 if (se == null) { 2258 if (!create) { 2259 return null; 2260 } 2261 se = new Sensor(sensor); 2262 mSensorStats.put(sensor, se); 2263 } 2264 StopwatchTimer t = se.mTimer; 2265 if (t != null) { 2266 return t; 2267 } 2268 ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor); 2269 if (timers == null) { 2270 timers = new ArrayList<StopwatchTimer>(); 2271 mSensorTimers.put(sensor, timers); 2272 } 2273 t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables); 2274 se.mTimer = t; 2275 return t; 2276 } 2277 2278 public void noteStartWakeLocked(String name, int type) { 2279 StopwatchTimer t = getWakeTimerLocked(name, type); 2280 if (t != null) { 2281 t.startRunningLocked(BatteryStatsImpl.this); 2282 } 2283 } 2284 2285 public void noteStopWakeLocked(String name, int type) { 2286 StopwatchTimer t = getWakeTimerLocked(name, type); 2287 if (t != null) { 2288 t.stopRunningLocked(BatteryStatsImpl.this); 2289 } 2290 } 2291 2292 public void noteStartSensor(int sensor) { 2293 StopwatchTimer t = getSensorTimerLocked(sensor, true); 2294 if (t != null) { 2295 t.startRunningLocked(BatteryStatsImpl.this); 2296 } 2297 } 2298 2299 public void noteStopSensor(int sensor) { 2300 // Don't create a timer if one doesn't already exist 2301 StopwatchTimer t = getSensorTimerLocked(sensor, false); 2302 if (t != null) { 2303 t.stopRunningLocked(BatteryStatsImpl.this); 2304 } 2305 } 2306 2307 public void noteStartGps() { 2308 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true); 2309 if (t != null) { 2310 t.startRunningLocked(BatteryStatsImpl.this); 2311 } 2312 } 2313 2314 public void noteStopGps() { 2315 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false); 2316 if (t != null) { 2317 t.stopRunningLocked(BatteryStatsImpl.this); 2318 } 2319 } 2320 2321 public BatteryStatsImpl getBatteryStats() { 2322 return BatteryStatsImpl.this; 2323 } 2324 } 2325 2326 public BatteryStatsImpl(String filename) { 2327 mFile = new File(filename); 2328 mBackupFile = new File(filename + ".bak"); 2329 mStartCount++; 2330 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables); 2331 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 2332 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables); 2333 } 2334 mInputEventCounter = new Counter(mUnpluggables); 2335 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables); 2336 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 2337 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables); 2338 } 2339 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 2340 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables); 2341 } 2342 mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables); 2343 mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables); 2344 mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables); 2345 mOnBattery = mOnBatteryInternal = false; 2346 mTrackBatteryPastUptime = 0; 2347 mTrackBatteryPastRealtime = 0; 2348 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; 2349 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; 2350 mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); 2351 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); 2352 mDischargeStartLevel = 0; 2353 mDischargeCurrentLevel = 0; 2354 } 2355 2356 public BatteryStatsImpl(Parcel p) { 2357 mFile = mBackupFile = null; 2358 readFromParcel(p); 2359 } 2360 2361 @Override 2362 public int getStartCount() { 2363 return mStartCount; 2364 } 2365 2366 public boolean isOnBattery() { 2367 return mOnBattery; 2368 } 2369 2370 public void setOnBattery(boolean onBattery, int level) { 2371 synchronized(this) { 2372 updateKernelWakelocksLocked(); 2373 if (mOnBattery != onBattery) { 2374 mOnBattery = mOnBatteryInternal = onBattery; 2375 2376 long uptime = SystemClock.uptimeMillis() * 1000; 2377 long mSecRealtime = SystemClock.elapsedRealtime(); 2378 long realtime = mSecRealtime * 1000; 2379 if (onBattery) { 2380 mTrackBatteryUptimeStart = uptime; 2381 mTrackBatteryRealtimeStart = realtime; 2382 mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); 2383 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); 2384 mDischargeCurrentLevel = mDischargeStartLevel = level; 2385 doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); 2386 } else { 2387 mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; 2388 mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; 2389 mDischargeCurrentLevel = level; 2390 doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); 2391 } 2392 if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) { 2393 if (mFile != null) { 2394 writeLocked(); 2395 } 2396 } 2397 } 2398 } 2399 } 2400 2401 public void recordCurrentLevel(int level) { 2402 mDischargeCurrentLevel = level; 2403 } 2404 2405 public void updateKernelWakelocksLocked() { 2406 Map<String, KernelWakelockStats> m = readKernelWakelockStats(); 2407 2408 if (m == null) { 2409 // Not crashing might make board bringup easier. 2410 Log.w(TAG, "Couldn't get kernel wake lock stats"); 2411 return; 2412 } 2413 2414 for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) { 2415 String name = ent.getKey(); 2416 KernelWakelockStats kws = ent.getValue(); 2417 2418 SamplingTimer kwlt = mKernelWakelockStats.get(name); 2419 if (kwlt == null) { 2420 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 2421 true /* track reported values */); 2422 mKernelWakelockStats.put(name, kwlt); 2423 } 2424 kwlt.updateCurrentReportedCount(kws.mCount); 2425 kwlt.updateCurrentReportedTotalTime(kws.mTotalTime); 2426 kwlt.setUpdateVersion(sKernelWakelockUpdateVersion); 2427 } 2428 2429 if (m.size() != mKernelWakelockStats.size()) { 2430 // Set timers to stale if they didn't appear in /proc/wakelocks this time. 2431 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 2432 SamplingTimer st = ent.getValue(); 2433 if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) { 2434 st.setStale(); 2435 } 2436 } 2437 } 2438 } 2439 2440 public long getAwakeTimeBattery() { 2441 return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT); 2442 } 2443 2444 public long getAwakeTimePlugged() { 2445 return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery(); 2446 } 2447 2448 @Override 2449 public long computeUptime(long curTime, int which) { 2450 switch (which) { 2451 case STATS_TOTAL: return mUptime + (curTime-mUptimeStart); 2452 case STATS_LAST: return mLastUptime; 2453 case STATS_CURRENT: return (curTime-mUptimeStart); 2454 case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart); 2455 } 2456 return 0; 2457 } 2458 2459 @Override 2460 public long computeRealtime(long curTime, int which) { 2461 switch (which) { 2462 case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart); 2463 case STATS_LAST: return mLastRealtime; 2464 case STATS_CURRENT: return (curTime-mRealtimeStart); 2465 case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart); 2466 } 2467 return 0; 2468 } 2469 2470 @Override 2471 public long computeBatteryUptime(long curTime, int which) { 2472 switch (which) { 2473 case STATS_TOTAL: 2474 return mBatteryUptime + getBatteryUptime(curTime); 2475 case STATS_LAST: 2476 return mBatteryLastUptime; 2477 case STATS_CURRENT: 2478 return getBatteryUptime(curTime); 2479 case STATS_UNPLUGGED: 2480 return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime; 2481 } 2482 return 0; 2483 } 2484 2485 @Override 2486 public long computeBatteryRealtime(long curTime, int which) { 2487 switch (which) { 2488 case STATS_TOTAL: 2489 return mBatteryRealtime + getBatteryRealtimeLocked(curTime); 2490 case STATS_LAST: 2491 return mBatteryLastRealtime; 2492 case STATS_CURRENT: 2493 return getBatteryRealtimeLocked(curTime); 2494 case STATS_UNPLUGGED: 2495 return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime; 2496 } 2497 return 0; 2498 } 2499 2500 long getBatteryUptimeLocked(long curTime) { 2501 long time = mTrackBatteryPastUptime; 2502 if (mOnBatteryInternal) { 2503 time += curTime - mTrackBatteryUptimeStart; 2504 } 2505 return time; 2506 } 2507 2508 long getBatteryUptimeLocked() { 2509 return getBatteryUptime(SystemClock.uptimeMillis() * 1000); 2510 } 2511 2512 @Override 2513 public long getBatteryUptime(long curTime) { 2514 return getBatteryUptimeLocked(curTime); 2515 } 2516 2517 long getBatteryRealtimeLocked(long curTime) { 2518 long time = mTrackBatteryPastRealtime; 2519 if (mOnBatteryInternal) { 2520 time += curTime - mTrackBatteryRealtimeStart; 2521 } 2522 return time; 2523 } 2524 2525 @Override 2526 public long getBatteryRealtime(long curTime) { 2527 return getBatteryRealtimeLocked(curTime); 2528 } 2529 2530 @Override 2531 public int getDischargeStartLevel() { 2532 synchronized(this) { 2533 return getDischargeStartLevelLocked(); 2534 } 2535 } 2536 2537 public int getDischargeStartLevelLocked() { 2538 return mDischargeStartLevel; 2539 } 2540 2541 @Override 2542 public int getDischargeCurrentLevel() { 2543 synchronized(this) { 2544 return getDischargeCurrentLevelLocked(); 2545 } 2546 } 2547 2548 public int getDischargeCurrentLevelLocked() { 2549 return mDischargeCurrentLevel; 2550 } 2551 2552 /** 2553 * Retrieve the statistics object for a particular uid, creating if needed. 2554 */ 2555 public Uid getUidStatsLocked(int uid) { 2556 Uid u = mUidStats.get(uid); 2557 if (u == null) { 2558 u = new Uid(uid); 2559 mUidStats.put(uid, u); 2560 } 2561 return u; 2562 } 2563 2564 /** 2565 * Remove the statistics object for a particular uid. 2566 */ 2567 public void removeUidStatsLocked(int uid) { 2568 mUidStats.remove(uid); 2569 } 2570 2571 /** 2572 * Retrieve the statistics object for a particular process, creating 2573 * if needed. 2574 */ 2575 public Uid.Proc getProcessStatsLocked(int uid, String name) { 2576 Uid u = getUidStatsLocked(uid); 2577 return u.getProcessStatsLocked(name); 2578 } 2579 2580 /** 2581 * Retrieve the statistics object for a particular process, creating 2582 * if needed. 2583 */ 2584 public Uid.Pkg getPackageStatsLocked(int uid, String pkg) { 2585 Uid u = getUidStatsLocked(uid); 2586 return u.getPackageStatsLocked(pkg); 2587 } 2588 2589 /** 2590 * Retrieve the statistics object for a particular service, creating 2591 * if needed. 2592 */ 2593 public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) { 2594 Uid u = getUidStatsLocked(uid); 2595 return u.getServiceStatsLocked(pkg, name); 2596 } 2597 2598 public void writeLocked() { 2599 if ((mFile == null) || (mBackupFile == null)) { 2600 Log.w("BatteryStats", "writeLocked: no file associated with this instance"); 2601 return; 2602 } 2603 2604 // Keep the old file around until we know the new one has 2605 // been successfully written. 2606 if (mFile.exists()) { 2607 if (mBackupFile.exists()) { 2608 mBackupFile.delete(); 2609 } 2610 mFile.renameTo(mBackupFile); 2611 } 2612 2613 try { 2614 FileOutputStream stream = new FileOutputStream(mFile); 2615 Parcel out = Parcel.obtain(); 2616 writeSummaryToParcel(out); 2617 stream.write(out.marshall()); 2618 out.recycle(); 2619 2620 stream.flush(); 2621 stream.close(); 2622 mBackupFile.delete(); 2623 2624 mLastWriteTime = SystemClock.elapsedRealtime(); 2625 } catch (IOException e) { 2626 Log.e("BatteryStats", "Error writing battery statistics", e); 2627 } 2628 } 2629 2630 static byte[] readFully(FileInputStream stream) throws java.io.IOException { 2631 int pos = 0; 2632 int avail = stream.available(); 2633 byte[] data = new byte[avail]; 2634 while (true) { 2635 int amt = stream.read(data, pos, data.length-pos); 2636 //Log.i("foo", "Read " + amt + " bytes at " + pos 2637 // + " of avail " + data.length); 2638 if (amt <= 0) { 2639 //Log.i("foo", "**** FINISHED READING: pos=" + pos 2640 // + " len=" + data.length); 2641 return data; 2642 } 2643 pos += amt; 2644 avail = stream.available(); 2645 if (avail > data.length-pos) { 2646 byte[] newData = new byte[pos+avail]; 2647 System.arraycopy(data, 0, newData, 0, pos); 2648 data = newData; 2649 } 2650 } 2651 } 2652 2653 public void readLocked() { 2654 if ((mFile == null) || (mBackupFile == null)) { 2655 Log.w("BatteryStats", "readLocked: no file associated with this instance"); 2656 return; 2657 } 2658 2659 mUidStats.clear(); 2660 2661 FileInputStream stream = null; 2662 if (mBackupFile.exists()) { 2663 try { 2664 stream = new FileInputStream(mBackupFile); 2665 } catch (java.io.IOException e) { 2666 // We'll try for the normal settings file. 2667 } 2668 } 2669 2670 try { 2671 if (stream == null) { 2672 if (!mFile.exists()) { 2673 return; 2674 } 2675 stream = new FileInputStream(mFile); 2676 } 2677 2678 byte[] raw = readFully(stream); 2679 Parcel in = Parcel.obtain(); 2680 in.unmarshall(raw, 0, raw.length); 2681 in.setDataPosition(0); 2682 stream.close(); 2683 2684 readSummaryFromParcel(in); 2685 } catch(java.io.IOException e) { 2686 Log.e("BatteryStats", "Error reading battery statistics", e); 2687 } 2688 } 2689 2690 public int describeContents() { 2691 return 0; 2692 } 2693 2694 private void readSummaryFromParcel(Parcel in) { 2695 final int version = in.readInt(); 2696 if (version != VERSION) { 2697 Log.w("BatteryStats", "readFromParcel: version got " + version 2698 + ", expected " + VERSION + "; erasing old stats"); 2699 return; 2700 } 2701 2702 mStartCount = in.readInt(); 2703 mBatteryUptime = in.readLong(); 2704 mBatteryLastUptime = in.readLong(); 2705 mBatteryRealtime = in.readLong(); 2706 mBatteryLastRealtime = in.readLong(); 2707 mUptime = in.readLong(); 2708 mLastUptime = in.readLong(); 2709 mRealtime = in.readLong(); 2710 mLastRealtime = in.readLong(); 2711 mDischargeStartLevel = in.readInt(); 2712 mDischargeCurrentLevel = in.readInt(); 2713 2714 mStartCount++; 2715 2716 mScreenOn = false; 2717 mScreenOnTimer.readSummaryFromParcelLocked(in); 2718 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 2719 mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in); 2720 } 2721 mInputEventCounter.readSummaryFromParcelLocked(in); 2722 mPhoneOn = false; 2723 mPhoneOnTimer.readSummaryFromParcelLocked(in); 2724 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 2725 mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in); 2726 } 2727 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 2728 mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in); 2729 } 2730 mWifiOn = false; 2731 mWifiOnTimer.readSummaryFromParcelLocked(in); 2732 mWifiRunning = false; 2733 mWifiRunningTimer.readSummaryFromParcelLocked(in); 2734 mBluetoothOn = false; 2735 mBluetoothOnTimer.readSummaryFromParcelLocked(in); 2736 2737 int NKW = in.readInt(); 2738 for (int ikw = 0; ikw < NKW; ikw++) { 2739 if (in.readInt() != 0) { 2740 String kwltName = in.readString(); 2741 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in); 2742 } 2743 } 2744 2745 final int NU = in.readInt(); 2746 for (int iu = 0; iu < NU; iu++) { 2747 int uid = in.readInt(); 2748 Uid u = new Uid(uid); 2749 mUidStats.put(uid, u); 2750 2751 u.mWifiTurnedOn = false; 2752 u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in); 2753 u.mFullWifiLockOut = false; 2754 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); 2755 u.mScanWifiLockOut = false; 2756 u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); 2757 u.mWifiMulticastEnabled = false; 2758 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in); 2759 2760 if (in.readInt() != 0) { 2761 if (u.mUserActivityCounters == null) { 2762 u.initUserActivityLocked(); 2763 } 2764 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 2765 u.mUserActivityCounters[i].readSummaryFromParcelLocked(in); 2766 } 2767 } 2768 2769 int NW = in.readInt(); 2770 for (int iw = 0; iw < NW; iw++) { 2771 String wlName = in.readString(); 2772 if (in.readInt() != 0) { 2773 u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in); 2774 } 2775 if (in.readInt() != 0) { 2776 u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in); 2777 } 2778 if (in.readInt() != 0) { 2779 u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in); 2780 } 2781 } 2782 2783 int NP = in.readInt(); 2784 for (int is = 0; is < NP; is++) { 2785 int seNumber = in.readInt(); 2786 if (in.readInt() != 0) { 2787 u.getSensorTimerLocked(seNumber, true) 2788 .readSummaryFromParcelLocked(in); 2789 } 2790 } 2791 2792 NP = in.readInt(); 2793 for (int ip = 0; ip < NP; ip++) { 2794 String procName = in.readString(); 2795 Uid.Proc p = u.getProcessStatsLocked(procName); 2796 p.mUserTime = p.mLoadedUserTime = in.readLong(); 2797 p.mLastUserTime = in.readLong(); 2798 p.mSystemTime = p.mLoadedSystemTime = in.readLong(); 2799 p.mLastSystemTime = in.readLong(); 2800 p.mStarts = p.mLoadedStarts = in.readInt(); 2801 p.mLastStarts = in.readInt(); 2802 } 2803 2804 NP = in.readInt(); 2805 for (int ip = 0; ip < NP; ip++) { 2806 String pkgName = in.readString(); 2807 Uid.Pkg p = u.getPackageStatsLocked(pkgName); 2808 p.mWakeups = p.mLoadedWakeups = in.readInt(); 2809 p.mLastWakeups = in.readInt(); 2810 final int NS = in.readInt(); 2811 for (int is = 0; is < NS; is++) { 2812 String servName = in.readString(); 2813 Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName); 2814 s.mStartTime = s.mLoadedStartTime = in.readLong(); 2815 s.mLastStartTime = in.readLong(); 2816 s.mStarts = s.mLoadedStarts = in.readInt(); 2817 s.mLastStarts = in.readInt(); 2818 s.mLaunches = s.mLoadedLaunches = in.readInt(); 2819 s.mLastLaunches = in.readInt(); 2820 } 2821 } 2822 2823 u.mLoadedTcpBytesReceived = in.readLong(); 2824 u.mLoadedTcpBytesSent = in.readLong(); 2825 } 2826 } 2827 2828 /** 2829 * Writes a summary of the statistics to a Parcel, in a format suitable to be written to 2830 * disk. This format does not allow a lossless round-trip. 2831 * 2832 * @param out the Parcel to be written to. 2833 */ 2834 public void writeSummaryToParcel(Parcel out) { 2835 final long NOW_SYS = SystemClock.uptimeMillis() * 1000; 2836 final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; 2837 final long NOW = getBatteryUptimeLocked(NOW_SYS); 2838 final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS); 2839 2840 out.writeInt(VERSION); 2841 2842 out.writeInt(mStartCount); 2843 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_TOTAL)); 2844 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT)); 2845 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_TOTAL)); 2846 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT)); 2847 out.writeLong(computeUptime(NOW_SYS, STATS_TOTAL)); 2848 out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT)); 2849 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL)); 2850 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT)); 2851 out.writeInt(mDischargeStartLevel); 2852 out.writeInt(mDischargeCurrentLevel); 2853 2854 2855 mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2856 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 2857 mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 2858 } 2859 mInputEventCounter.writeSummaryFromParcelLocked(out); 2860 mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2861 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 2862 mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 2863 } 2864 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 2865 mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 2866 } 2867 mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2868 mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2869 mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2870 2871 out.writeInt(mKernelWakelockStats.size()); 2872 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 2873 Timer kwlt = ent.getValue(); 2874 if (kwlt != null) { 2875 out.writeInt(1); 2876 out.writeString(ent.getKey()); 2877 ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL); 2878 } else { 2879 out.writeInt(0); 2880 } 2881 } 2882 2883 final int NU = mUidStats.size(); 2884 out.writeInt(NU); 2885 for (int iu = 0; iu < NU; iu++) { 2886 out.writeInt(mUidStats.keyAt(iu)); 2887 Uid u = mUidStats.valueAt(iu); 2888 2889 u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2890 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2891 u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2892 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2893 2894 if (u.mUserActivityCounters == null) { 2895 out.writeInt(0); 2896 } else { 2897 out.writeInt(1); 2898 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 2899 u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out); 2900 } 2901 } 2902 2903 int NW = u.mWakelockStats.size(); 2904 out.writeInt(NW); 2905 if (NW > 0) { 2906 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent 2907 : u.mWakelockStats.entrySet()) { 2908 out.writeString(ent.getKey()); 2909 Uid.Wakelock wl = ent.getValue(); 2910 if (wl.mTimerFull != null) { 2911 out.writeInt(1); 2912 wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL); 2913 } else { 2914 out.writeInt(0); 2915 } 2916 if (wl.mTimerPartial != null) { 2917 out.writeInt(1); 2918 wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL); 2919 } else { 2920 out.writeInt(0); 2921 } 2922 if (wl.mTimerWindow != null) { 2923 out.writeInt(1); 2924 wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL); 2925 } else { 2926 out.writeInt(0); 2927 } 2928 } 2929 } 2930 2931 int NSE = u.mSensorStats.size(); 2932 out.writeInt(NSE); 2933 if (NSE > 0) { 2934 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent 2935 : u.mSensorStats.entrySet()) { 2936 out.writeInt(ent.getKey()); 2937 Uid.Sensor se = ent.getValue(); 2938 if (se.mTimer != null) { 2939 out.writeInt(1); 2940 se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2941 } else { 2942 out.writeInt(0); 2943 } 2944 } 2945 } 2946 2947 int NP = u.mProcessStats.size(); 2948 out.writeInt(NP); 2949 if (NP > 0) { 2950 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent 2951 : u.mProcessStats.entrySet()) { 2952 out.writeString(ent.getKey()); 2953 Uid.Proc ps = ent.getValue(); 2954 out.writeLong(ps.mUserTime); 2955 out.writeLong(ps.mUserTime - ps.mLoadedUserTime); 2956 out.writeLong(ps.mSystemTime); 2957 out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime); 2958 out.writeInt(ps.mStarts); 2959 out.writeInt(ps.mStarts - ps.mLoadedStarts); 2960 } 2961 } 2962 2963 NP = u.mPackageStats.size(); 2964 out.writeInt(NP); 2965 if (NP > 0) { 2966 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent 2967 : u.mPackageStats.entrySet()) { 2968 out.writeString(ent.getKey()); 2969 Uid.Pkg ps = ent.getValue(); 2970 out.writeInt(ps.mWakeups); 2971 out.writeInt(ps.mWakeups - ps.mLoadedWakeups); 2972 final int NS = ps.mServiceStats.size(); 2973 out.writeInt(NS); 2974 if (NS > 0) { 2975 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent 2976 : ps.mServiceStats.entrySet()) { 2977 out.writeString(sent.getKey()); 2978 BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue(); 2979 long time = ss.getStartTimeToNowLocked(NOW); 2980 out.writeLong(time); 2981 out.writeLong(time - ss.mLoadedStartTime); 2982 out.writeInt(ss.mStarts); 2983 out.writeInt(ss.mStarts - ss.mLoadedStarts); 2984 out.writeInt(ss.mLaunches); 2985 out.writeInt(ss.mLaunches - ss.mLoadedLaunches); 2986 } 2987 } 2988 } 2989 } 2990 2991 out.writeLong(u.getTcpBytesReceived(STATS_TOTAL)); 2992 out.writeLong(u.getTcpBytesSent(STATS_TOTAL)); 2993 } 2994 } 2995 2996 public void readFromParcel(Parcel in) { 2997 readFromParcelLocked(in); 2998 } 2999 3000 void readFromParcelLocked(Parcel in) { 3001 int magic = in.readInt(); 3002 if (magic != MAGIC) { 3003 throw new ParcelFormatException("Bad magic number"); 3004 } 3005 3006 mStartCount = in.readInt(); 3007 mBatteryUptime = in.readLong(); 3008 mBatteryLastUptime = in.readLong(); 3009 mBatteryRealtime = in.readLong(); 3010 mBatteryLastRealtime = in.readLong(); 3011 mScreenOn = false; 3012 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in); 3013 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3014 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in); 3015 } 3016 mInputEventCounter = new Counter(mUnpluggables, in); 3017 mPhoneOn = false; 3018 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3019 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3020 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in); 3021 } 3022 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3023 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in); 3024 } 3025 mWifiOn = false; 3026 mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3027 mWifiRunning = false; 3028 mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3029 mBluetoothOn = false; 3030 mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3031 mUptime = in.readLong(); 3032 mUptimeStart = in.readLong(); 3033 mLastUptime = in.readLong(); 3034 mRealtime = in.readLong(); 3035 mRealtimeStart = in.readLong(); 3036 mLastRealtime = in.readLong(); 3037 mOnBattery = in.readInt() != 0; 3038 mOnBatteryInternal = false; // we are no longer really running. 3039 mTrackBatteryPastUptime = in.readLong(); 3040 mTrackBatteryUptimeStart = in.readLong(); 3041 mTrackBatteryPastRealtime = in.readLong(); 3042 mTrackBatteryRealtimeStart = in.readLong(); 3043 mUnpluggedBatteryUptime = in.readLong(); 3044 mUnpluggedBatteryRealtime = in.readLong(); 3045 mDischargeStartLevel = in.readInt(); 3046 mDischargeCurrentLevel = in.readInt(); 3047 mLastWriteTime = in.readLong(); 3048 3049 mKernelWakelockStats.clear(); 3050 int NKW = in.readInt(); 3051 for (int ikw = 0; ikw < NKW; ikw++) { 3052 if (in.readInt() != 0) { 3053 String wakelockName = in.readString(); 3054 SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in); 3055 mKernelWakelockStats.put(wakelockName, kwlt); 3056 } 3057 } 3058 3059 mPartialTimers.clear(); 3060 mFullTimers.clear(); 3061 mWindowTimers.clear(); 3062 3063 int numUids = in.readInt(); 3064 mUidStats.clear(); 3065 for (int i = 0; i < numUids; i++) { 3066 int uid = in.readInt(); 3067 Uid u = new Uid(uid); 3068 u.readFromParcelLocked(mUnpluggables, in); 3069 mUidStats.append(uid, u); 3070 } 3071 } 3072 3073 public void writeToParcel(Parcel out, int flags) { 3074 writeToParcelLocked(out, flags); 3075 } 3076 3077 @SuppressWarnings("unused") 3078 void writeToParcelLocked(Parcel out, int flags) { 3079 final long uSecUptime = SystemClock.uptimeMillis() * 1000; 3080 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 3081 final long batteryUptime = getBatteryUptimeLocked(uSecUptime); 3082 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 3083 3084 out.writeInt(MAGIC); 3085 out.writeInt(mStartCount); 3086 out.writeLong(mBatteryUptime); 3087 out.writeLong(mBatteryLastUptime); 3088 out.writeLong(mBatteryRealtime); 3089 out.writeLong(mBatteryLastRealtime); 3090 mScreenOnTimer.writeToParcel(out, batteryRealtime); 3091 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3092 mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime); 3093 } 3094 mInputEventCounter.writeToParcel(out); 3095 mPhoneOnTimer.writeToParcel(out, batteryRealtime); 3096 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3097 mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime); 3098 } 3099 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3100 mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime); 3101 } 3102 mWifiOnTimer.writeToParcel(out, batteryRealtime); 3103 mWifiRunningTimer.writeToParcel(out, batteryRealtime); 3104 mBluetoothOnTimer.writeToParcel(out, batteryRealtime); 3105 out.writeLong(mUptime); 3106 out.writeLong(mUptimeStart); 3107 out.writeLong(mLastUptime); 3108 out.writeLong(mRealtime); 3109 out.writeLong(mRealtimeStart); 3110 out.writeLong(mLastRealtime); 3111 out.writeInt(mOnBattery ? 1 : 0); 3112 out.writeLong(batteryUptime); 3113 out.writeLong(mTrackBatteryUptimeStart); 3114 out.writeLong(batteryRealtime); 3115 out.writeLong(mTrackBatteryRealtimeStart); 3116 out.writeLong(mUnpluggedBatteryUptime); 3117 out.writeLong(mUnpluggedBatteryRealtime); 3118 out.writeInt(mDischargeStartLevel); 3119 out.writeInt(mDischargeCurrentLevel); 3120 out.writeLong(mLastWriteTime); 3121 3122 out.writeInt(mKernelWakelockStats.size()); 3123 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 3124 SamplingTimer kwlt = ent.getValue(); 3125 if (kwlt != null) { 3126 out.writeInt(1); 3127 out.writeString(ent.getKey()); 3128 Timer.writeTimerToParcel(out, kwlt, batteryRealtime); 3129 } else { 3130 out.writeInt(0); 3131 } 3132 } 3133 3134 int size = mUidStats.size(); 3135 out.writeInt(size); 3136 for (int i = 0; i < size; i++) { 3137 out.writeInt(mUidStats.keyAt(i)); 3138 Uid uid = mUidStats.valueAt(i); 3139 3140 uid.writeToParcelLocked(out, batteryRealtime); 3141 } 3142 } 3143 3144 public static final Parcelable.Creator<BatteryStatsImpl> CREATOR = 3145 new Parcelable.Creator<BatteryStatsImpl>() { 3146 public BatteryStatsImpl createFromParcel(Parcel in) { 3147 return new BatteryStatsImpl(in); 3148 } 3149 3150 public BatteryStatsImpl[] newArray(int size) { 3151 return new BatteryStatsImpl[size]; 3152 } 3153 }; 3154 3155 public void dumpLocked(PrintWriter pw) { 3156 if (DEBUG) { 3157 Printer pr = new PrintWriterPrinter(pw); 3158 pr.println("*** Screen timer:"); 3159 mScreenOnTimer.logState(pr, " "); 3160 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3161 pr.println("*** Screen brightness #" + i + ":"); 3162 mScreenBrightnessTimer[i].logState(pr, " "); 3163 } 3164 pr.println("*** Input event counter:"); 3165 mInputEventCounter.logState(pr, " "); 3166 pr.println("*** Phone timer:"); 3167 mPhoneOnTimer.logState(pr, " "); 3168 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3169 pr.println("*** Signal strength #" + i + ":"); 3170 mPhoneSignalStrengthsTimer[i].logState(pr, " "); 3171 } 3172 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3173 pr.println("*** Data connection type #" + i + ":"); 3174 mPhoneDataConnectionsTimer[i].logState(pr, " "); 3175 } 3176 pr.println("*** Wifi timer:"); 3177 mWifiOnTimer.logState(pr, " "); 3178 pr.println("*** WifiRunning timer:"); 3179 mWifiRunningTimer.logState(pr, " "); 3180 pr.println("*** Bluetooth timer:"); 3181 mBluetoothOnTimer.logState(pr, " "); 3182 } 3183 super.dumpLocked(pw); 3184 } 3185} 3186