BatteryStatsImpl.java revision 105925376f8d0f6b318c9938c7b83ef7fef094da
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.SystemClock; 25import android.util.Log; 26import android.util.Printer; 27import android.util.SparseArray; 28 29import java.io.File; 30import java.io.FileInputStream; 31import java.io.FileOutputStream; 32import java.io.IOException; 33import java.util.ArrayList; 34import java.util.HashMap; 35import java.util.Map; 36 37/** 38 * All information we are collecting about things that can happen that impact 39 * battery life. All times are represented in microseconds except where indicated 40 * otherwise. 41 */ 42public final class BatteryStatsImpl extends BatteryStats { 43 private static final String TAG = "BatteryStatsImpl"; 44 private static final boolean DEBUG = false; 45 46 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data 47 private static final int MAGIC = 0xBA757475; // 'BATSTATS' 48 49 // Current on-disk Parcel version 50 private static final int VERSION = 27; 51 52 private final File mFile; 53 private final File mBackupFile; 54 55 /** 56 * The statistics we have collected organized by uids. 57 */ 58 final SparseArray<BatteryStatsImpl.Uid> mUidStats = 59 new SparseArray<BatteryStatsImpl.Uid>(); 60 61 // A set of pools of currently active timers. When a timer is queried, we will divide the 62 // elapsed time by the number of active timers to arrive at that timer's share of the time. 63 // In order to do this, we must refresh each timer whenever the number of active timers 64 // changes. 65 final ArrayList<Timer> mPartialTimers = new ArrayList<Timer>(); 66 final ArrayList<Timer> mFullTimers = new ArrayList<Timer>(); 67 final ArrayList<Timer> mWindowTimers = new ArrayList<Timer>(); 68 final SparseArray<ArrayList<Timer>> mSensorTimers 69 = new SparseArray<ArrayList<Timer>>(); 70 71 // These are the objects that will want to do something when the device 72 // is unplugged from power. 73 final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>(); 74 75 int mStartCount; 76 77 long mBatteryUptime; 78 long mBatteryLastUptime; 79 long mBatteryRealtime; 80 long mBatteryLastRealtime; 81 82 long mUptime; 83 long mUptimeStart; 84 long mLastUptime; 85 long mRealtime; 86 long mRealtimeStart; 87 long mLastRealtime; 88 89 boolean mScreenOn; 90 Timer mScreenOnTimer; 91 92 boolean mPhoneOn; 93 Timer mPhoneOnTimer; 94 95 boolean mWifiOn; 96 Timer mWifiOnTimer; 97 98 boolean mBluetoothOn; 99 Timer mBluetoothOnTimer; 100 101 /** 102 * These provide time bases that discount the time the device is plugged 103 * in to power. 104 */ 105 boolean mOnBattery; 106 boolean mOnBatteryInternal; 107 long mTrackBatteryPastUptime; 108 long mTrackBatteryUptimeStart; 109 long mTrackBatteryPastRealtime; 110 long mTrackBatteryRealtimeStart; 111 112 long mUnpluggedBatteryUptime; 113 long mUnpluggedBatteryRealtime; 114 115 /* 116 * These keep track of battery levels (1-100) at the last plug event and the last unplug event. 117 */ 118 int mUnpluggedStartLevel; 119 int mPluggedStartLevel; 120 121 long mLastWriteTime = 0; // Milliseconds 122 123 // For debugging 124 public BatteryStatsImpl() { 125 mFile = mBackupFile = null; 126 } 127 128 public static interface Unpluggable { 129 void unplug(long batteryUptime, long batteryRealtime); 130 void plug(long batteryUptime, long batteryRealtime); 131 } 132 133 /** 134 * State for keeping track of timing information. 135 */ 136 public static final class Timer extends BatteryStats.Timer implements Unpluggable { 137 final int mType; 138 final ArrayList<Timer> mTimerPool; 139 140 int mNesting; 141 142 int mCount; 143 int mLoadedCount; 144 int mLastCount; 145 int mUnpluggedCount; 146 147 // Times are in microseconds for better accuracy when dividing by the 148 // lock count, and are in "battery realtime" units. 149 150 /** 151 * The total time we have accumulated since the start of the original 152 * boot, to the last time something interesting happened in the 153 * current run. 154 */ 155 long mTotalTime; 156 157 /** 158 * The total time we loaded for the previous runs. Subtract this from 159 * mTotalTime to find the time for the current run of the system. 160 */ 161 long mLoadedTime; 162 163 /** 164 * The run time of the last run of the system, as loaded from the 165 * saved data. 166 */ 167 long mLastTime; 168 169 /** 170 * The value of mTotalTime when unplug() was last called. Subtract 171 * this from mTotalTime to find the time since the last unplug from 172 * power. 173 */ 174 long mUnpluggedTime; 175 176 /** 177 * The last time at which we updated the timer. If mNesting is > 0, 178 * subtract this from the current battery time to find the amount of 179 * time we have been running since we last computed an update. 180 */ 181 long mUpdateTime; 182 183 /** 184 * The total time at which the timer was acquired, to determine if 185 * was actually held for an interesting duration. 186 */ 187 long mAcquireTime; 188 189 Timer(int type, ArrayList<Timer> timerPool, 190 ArrayList<Unpluggable> unpluggables, Parcel in) { 191 mType = type; 192 mTimerPool = timerPool; 193 mCount = in.readInt(); 194 mLoadedCount = in.readInt(); 195 mLastCount = in.readInt(); 196 mUnpluggedCount = in.readInt(); 197 mTotalTime = in.readLong(); 198 mLoadedTime = in.readLong(); 199 mLastTime = in.readLong(); 200 mUpdateTime = in.readLong(); 201 mUnpluggedTime = in.readLong(); 202 unpluggables.add(this); 203 } 204 205 Timer(int type, ArrayList<Timer> timerPool, 206 ArrayList<Unpluggable> unpluggables) { 207 mType = type; 208 mTimerPool = timerPool; 209 unpluggables.add(this); 210 } 211 212 public void writeToParcel(Parcel out, long batteryRealtime) { 213 out.writeInt(mCount); 214 out.writeInt(mLoadedCount); 215 out.writeInt(mLastCount); 216 out.writeInt(mUnpluggedCount); 217 out.writeLong(computeRunTimeLocked(batteryRealtime)); 218 out.writeLong(mLoadedTime); 219 out.writeLong(mLastTime); 220 out.writeLong(mUpdateTime); 221 out.writeLong(mUnpluggedTime); 222 } 223 224 public void unplug(long batteryUptime, long batteryRealtime) { 225 if (DEBUG && mType < 0) { 226 Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime 227 + " old mUnpluggedTime=" + mUnpluggedTime 228 + " old mUnpluggedCount=" + mUnpluggedCount); 229 } 230 mUnpluggedTime = computeRunTimeLocked(batteryRealtime); 231 mUnpluggedCount = mCount; 232 if (DEBUG && mType < 0) { 233 Log.v(TAG, "unplug #" + mType 234 + ": new mUnpluggedTime=" + mUnpluggedTime 235 + " new mUnpluggedCount=" + mUnpluggedCount); 236 } 237 } 238 239 public void plug(long batteryUptime, long batteryRealtime) { 240 if (mNesting > 0) { 241 if (DEBUG && mType < 0) { 242 Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime 243 + " old mTotalTime=" + mTotalTime 244 + " old mUpdateTime=" + mUpdateTime); 245 } 246 mTotalTime = computeRunTimeLocked(batteryRealtime); 247 mUpdateTime = batteryRealtime; 248 if (DEBUG && mType < 0) { 249 Log.v(TAG, "plug #" + mType 250 + ": new mTotalTime=" + mTotalTime 251 + " old mUpdateTime=" + mUpdateTime); 252 } 253 } 254 } 255 256 /** 257 * Writes a possibly null Timer to a Parcel. 258 * 259 * @param out the Parcel to be written to. 260 * @param timer a Timer, or null. 261 */ 262 public static void writeTimerToParcel(Parcel out, Timer timer, 263 long batteryRealtime) { 264 if (timer == null) { 265 out.writeInt(0); // indicates null 266 return; 267 } 268 out.writeInt(1); // indicates non-null 269 270 timer.writeToParcel(out, batteryRealtime); 271 } 272 273 @Override 274 public long getTotalTime(long batteryRealtime, int which) { 275 long val; 276 if (which == STATS_LAST) { 277 val = mLastTime; 278 } else { 279 val = computeRunTimeLocked(batteryRealtime); 280 if (which == STATS_UNPLUGGED) { 281 val -= mUnpluggedTime; 282 } else if (which != STATS_TOTAL) { 283 val -= mLoadedTime; 284 } 285 } 286 287 return val; 288 } 289 290 @Override 291 public int getCount(int which) { 292 int val; 293 if (which == STATS_LAST) { 294 val = mLastCount; 295 } else { 296 val = mCount; 297 if (which == STATS_UNPLUGGED) { 298 val -= mUnpluggedCount; 299 } else if (which != STATS_TOTAL) { 300 val -= mLoadedCount; 301 } 302 } 303 304 return val; 305 } 306 307 public void logState() { 308 Log.i("foo", "mNesting=" + mNesting + " mCount=" + mCount 309 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 310 + " mUnpluggedCount=" + mUnpluggedCount); 311 Log.i("foo", "mTotalTime=" + mTotalTime 312 + " mLoadedTime=" + mLoadedTime); 313 Log.i("foo", "mLastTime=" + mLastTime 314 + " mUnpluggedTime=" + mUnpluggedTime); 315 Log.i("foo", "mUpdateTime=" + mUpdateTime 316 + " mAcquireTime=" + mAcquireTime); 317 } 318 319 void startRunningLocked(BatteryStatsImpl stats) { 320 if (mNesting++ == 0) { 321 mUpdateTime = stats.getBatteryRealtimeLocked( 322 SystemClock.elapsedRealtime() * 1000); 323 if (mTimerPool != null) { 324 // Accumulate time to all currently active timers before adding 325 // this new one to the pool. 326 refreshTimersLocked(stats, mTimerPool); 327 // Add this timer to the active pool 328 mTimerPool.add(this); 329 } 330 // Increment the count 331 mCount++; 332 mAcquireTime = mTotalTime; 333 if (DEBUG && mType < 0) { 334 Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime 335 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 336 + " mAcquireTime=" + mAcquireTime); 337 } 338 } 339 } 340 341 void stopRunningLocked(BatteryStatsImpl stats) { 342 // Ignore attempt to stop a timer that isn't running 343 if (mNesting == 0) { 344 return; 345 } 346 if (--mNesting == 0) { 347 if (mTimerPool != null) { 348 // Accumulate time to all active counters, scaled by the total 349 // active in the pool, before taking this one out of the pool. 350 refreshTimersLocked(stats, mTimerPool); 351 // Remove this timer from the active pool 352 mTimerPool.remove(this); 353 } else { 354 final long realtime = SystemClock.elapsedRealtime() * 1000; 355 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 356 mNesting = 1; 357 mTotalTime = computeRunTimeLocked(batteryRealtime); 358 mNesting = 0; 359 } 360 361 if (DEBUG && mType < 0) { 362 Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime 363 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 364 + " mAcquireTime=" + mAcquireTime); 365 } 366 367 if (mTotalTime == mAcquireTime) { 368 // If there was no change in the time, then discard this 369 // count. A somewhat cheezy strategy, but hey. 370 mCount--; 371 } 372 } 373 } 374 375 // Update the total time for all other running Timers with the same type as this Timer 376 // due to a change in timer count 377 private static void refreshTimersLocked(final BatteryStatsImpl stats, 378 final ArrayList<Timer> pool) { 379 final long realtime = SystemClock.elapsedRealtime() * 1000; 380 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 381 final int N = pool.size(); 382 for (int i=N-1; i>= 0; i--) { 383 final Timer t = pool.get(i); 384 long heldTime = batteryRealtime - t.mUpdateTime; 385 if (heldTime > 0) { 386 t.mTotalTime += heldTime / N; 387 } 388 t.mUpdateTime = batteryRealtime; 389 } 390 } 391 392 private long computeRunTimeLocked(long curBatteryRealtime) { 393 return mTotalTime + (mNesting > 0 394 ? (curBatteryRealtime - mUpdateTime) 395 / (mTimerPool != null ? mTimerPool.size() : 1) 396 : 0); 397 } 398 399 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 400 long runTime = computeRunTimeLocked(batteryRealtime); 401 // Divide by 1000 for backwards compatibility 402 out.writeLong((runTime + 500) / 1000); 403 out.writeLong(((runTime - mLoadedTime) + 500) / 1000); 404 out.writeInt(mCount); 405 out.writeInt(mCount - mLoadedCount); 406 } 407 408 void readSummaryFromParcelLocked(Parcel in) { 409 // Multiply by 1000 for backwards compatibility 410 mTotalTime = mLoadedTime = in.readLong() * 1000; 411 mLastTime = in.readLong() * 1000; 412 mUnpluggedTime = mTotalTime; 413 mCount = mLoadedCount = in.readInt(); 414 mLastCount = in.readInt(); 415 mUnpluggedCount = mCount; 416 mNesting = 0; 417 } 418 } 419 420 public void doUnplug(long batteryUptime, long batteryRealtime) { 421 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 422 Uid u = mUidStats.valueAt(iu); 423 u.mStartedTcpBytesReceived = NetStat.getUidRxBytes(u.mUid); 424 u.mStartedTcpBytesSent = NetStat.getUidTxBytes(u.mUid); 425 u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived; 426 u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent; 427 } 428 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 429 mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime); 430 } 431 } 432 433 public void doPlug(long batteryUptime, long batteryRealtime) { 434 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 435 Uid u = mUidStats.valueAt(iu); 436 if (u.mStartedTcpBytesReceived >= 0) { 437 u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived(); 438 u.mStartedTcpBytesReceived = -1; 439 } 440 if (u.mStartedTcpBytesSent >= 0) { 441 u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent(); 442 u.mStartedTcpBytesSent = -1; 443 } 444 } 445 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 446 mUnpluggables.get(i).plug(batteryUptime, batteryRealtime); 447 } 448 } 449 450 public void noteStartGps(int uid) { 451 mUidStats.get(uid).noteStartGps(); 452 } 453 454 public void noteStopGps(int uid) { 455 mUidStats.get(uid).noteStopGps(); 456 } 457 458 public void noteScreenOnLocked() { 459 if (!mScreenOn) { 460 mScreenOn = true; 461 mScreenOnTimer.startRunningLocked(this); 462 } 463 } 464 465 public void noteScreenOffLocked() { 466 if (mScreenOn) { 467 mScreenOn = false; 468 mScreenOnTimer.stopRunningLocked(this); 469 } 470 } 471 472 public void notePhoneOnLocked() { 473 if (!mPhoneOn) { 474 mPhoneOn = true; 475 mPhoneOnTimer.startRunningLocked(this); 476 } 477 } 478 479 public void notePhoneOffLocked() { 480 if (mPhoneOn) { 481 mPhoneOn = false; 482 mPhoneOnTimer.stopRunningLocked(this); 483 } 484 } 485 486 public void noteWifiOnLocked() { 487 if (!mWifiOn) { 488 mWifiOn = true; 489 mWifiOnTimer.startRunningLocked(this); 490 } 491 } 492 493 public void noteWifiOffLocked() { 494 if (mWifiOn) { 495 mWifiOn = false; 496 mWifiOnTimer.stopRunningLocked(this); 497 } 498 } 499 500 public void noteBluetoothOnLocked() { 501 if (!mBluetoothOn) { 502 mBluetoothOn = true; 503 mBluetoothOnTimer.startRunningLocked(this); 504 } 505 } 506 507 public void noteBluetoothOffLocked() { 508 if (mBluetoothOn) { 509 mBluetoothOn = false; 510 mBluetoothOnTimer.stopRunningLocked(this); 511 } 512 } 513 514 public void noteFullWifiLockAcquiredLocked(int uid) { 515 Uid u = mUidStats.get(uid); 516 if (u != null) { 517 u.noteFullWifiLockAcquiredLocked(); 518 } 519 } 520 521 public void noteFullWifiLockReleasedLocked(int uid) { 522 Uid u = mUidStats.get(uid); 523 if (u != null) { 524 u.noteFullWifiLockReleasedLocked(); 525 } 526 } 527 528 public void noteScanWifiLockAcquiredLocked(int uid) { 529 Uid u = mUidStats.get(uid); 530 if (u != null) { 531 u.noteScanWifiLockAcquiredLocked(); 532 } 533 } 534 535 public void noteScanWifiLockReleasedLocked(int uid) { 536 Uid u = mUidStats.get(uid); 537 if (u != null) { 538 u.noteScanWifiLockReleasedLocked(); 539 } 540 } 541 542 @Override public long getScreenOnTime(long batteryRealtime, int which) { 543 return mScreenOnTimer.getTotalTime(batteryRealtime, which); 544 } 545 546 @Override public long getPhoneOnTime(long batteryRealtime, int which) { 547 return mPhoneOnTimer.getTotalTime(batteryRealtime, which); 548 } 549 550 @Override public long getWifiOnTime(long batteryRealtime, int which) { 551 return mWifiOnTimer.getTotalTime(batteryRealtime, which); 552 } 553 554 @Override public long getBluetoothOnTime(long batteryRealtime, int which) { 555 return mBluetoothOnTimer.getTotalTime(batteryRealtime, which); 556 } 557 558 @Override public boolean getIsOnBattery() { 559 return mOnBattery; 560 } 561 562 @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() { 563 return mUidStats; 564 } 565 566 /** 567 * The statistics associated with a particular uid. 568 */ 569 public final class Uid extends BatteryStats.Uid { 570 571 final int mUid; 572 long mLoadedTcpBytesReceived; 573 long mLoadedTcpBytesSent; 574 long mCurrentTcpBytesReceived; 575 long mCurrentTcpBytesSent; 576 long mTcpBytesReceivedAtLastUnplug; 577 long mTcpBytesSentAtLastUnplug; 578 579 // These are not saved/restored when parcelling, since we want 580 // to return from the parcel with a snapshot of the state. 581 long mStartedTcpBytesReceived = -1; 582 long mStartedTcpBytesSent = -1; 583 584 boolean mFullWifiLockOut; 585 Timer mFullWifiLockTimer; 586 587 boolean mScanWifiLockOut; 588 Timer mScanWifiLockTimer; 589 590 /** 591 * The statistics we have collected for this uid's wake locks. 592 */ 593 final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>(); 594 595 /** 596 * The statistics we have collected for this uid's sensor activations. 597 */ 598 final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>(); 599 600 /** 601 * The statistics we have collected for this uid's processes. 602 */ 603 final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>(); 604 605 /** 606 * The statistics we have collected for this uid's processes. 607 */ 608 final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>(); 609 610 public Uid(int uid) { 611 mUid = uid; 612 mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables); 613 mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables); 614 } 615 616 @Override 617 public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() { 618 return mWakelockStats; 619 } 620 621 @Override 622 public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() { 623 return mSensorStats; 624 } 625 626 @Override 627 public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() { 628 return mProcessStats; 629 } 630 631 @Override 632 public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { 633 return mPackageStats; 634 } 635 636 public int getUid() { 637 return mUid; 638 } 639 640 public long getTcpBytesReceived(int which) { 641 if (which == STATS_LAST) { 642 return mLoadedTcpBytesReceived; 643 } else { 644 long current = computeCurrentTcpBytesReceived(); 645 if (which == STATS_UNPLUGGED) { 646 current -= mTcpBytesReceivedAtLastUnplug; 647 } else if (which == STATS_TOTAL) { 648 current += mLoadedTcpBytesReceived; 649 } 650 return current; 651 } 652 } 653 654 public long computeCurrentTcpBytesReceived() { 655 return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0 656 ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0); 657 } 658 659 public long getTcpBytesSent(int which) { 660 if (which == STATS_LAST) { 661 return mLoadedTcpBytesSent; 662 } else { 663 long current = computeCurrentTcpBytesSent(); 664 if (which == STATS_UNPLUGGED) { 665 current -= mTcpBytesSentAtLastUnplug; 666 } else if (which == STATS_TOTAL) { 667 current += mLoadedTcpBytesSent; 668 } 669 return current; 670 } 671 } 672 673 @Override 674 public void noteFullWifiLockAcquiredLocked() { 675 if (!mFullWifiLockOut) { 676 mFullWifiLockOut = true; 677 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 678 } 679 } 680 681 @Override 682 public void noteFullWifiLockReleasedLocked() { 683 if (mFullWifiLockOut) { 684 mFullWifiLockOut = false; 685 mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 686 } 687 } 688 689 @Override 690 public void noteScanWifiLockAcquiredLocked() { 691 if (!mScanWifiLockOut) { 692 mScanWifiLockOut = true; 693 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 694 } 695 } 696 697 @Override 698 public void noteScanWifiLockReleasedLocked() { 699 if (mScanWifiLockOut) { 700 mScanWifiLockOut = false; 701 mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 702 } 703 } 704 @Override 705 public long getFullWifiLockTime(long batteryRealtime, int which) { 706 return mFullWifiLockTimer.getTotalTime(batteryRealtime, which); 707 } 708 709 @Override 710 public long getScanWifiLockTime(long batteryRealtime, int which) { 711 return mScanWifiLockTimer.getTotalTime(batteryRealtime, which); 712 } 713 714 public long computeCurrentTcpBytesSent() { 715 return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0 716 ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0); 717 } 718 719 void writeToParcelLocked(Parcel out, long batteryRealtime) { 720 out.writeInt(mWakelockStats.size()); 721 for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) { 722 out.writeString(wakelockEntry.getKey()); 723 Uid.Wakelock wakelock = wakelockEntry.getValue(); 724 wakelock.writeToParcelLocked(out, batteryRealtime); 725 } 726 727 out.writeInt(mSensorStats.size()); 728 for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) { 729 out.writeInt(sensorEntry.getKey()); 730 Uid.Sensor sensor = sensorEntry.getValue(); 731 sensor.writeToParcelLocked(out, batteryRealtime); 732 } 733 734 out.writeInt(mProcessStats.size()); 735 for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) { 736 out.writeString(procEntry.getKey()); 737 Uid.Proc proc = procEntry.getValue(); 738 proc.writeToParcelLocked(out); 739 } 740 741 out.writeInt(mPackageStats.size()); 742 for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) { 743 out.writeString(pkgEntry.getKey()); 744 Uid.Pkg pkg = pkgEntry.getValue(); 745 pkg.writeToParcelLocked(out); 746 } 747 748 out.writeLong(mLoadedTcpBytesReceived); 749 out.writeLong(mLoadedTcpBytesSent); 750 out.writeLong(computeCurrentTcpBytesReceived()); 751 out.writeLong(computeCurrentTcpBytesSent()); 752 out.writeLong(mTcpBytesReceivedAtLastUnplug); 753 out.writeLong(mTcpBytesSentAtLastUnplug); 754 mFullWifiLockTimer.writeToParcel(out, batteryRealtime); 755 mScanWifiLockTimer.writeToParcel(out, batteryRealtime); 756 } 757 758 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 759 int numWakelocks = in.readInt(); 760 mWakelockStats.clear(); 761 for (int j = 0; j < numWakelocks; j++) { 762 String wakelockName = in.readString(); 763 Uid.Wakelock wakelock = new Wakelock(); 764 wakelock.readFromParcelLocked(unpluggables, in); 765 mWakelockStats.put(wakelockName, wakelock); 766 } 767 768 int numSensors = in.readInt(); 769 mSensorStats.clear(); 770 for (int k = 0; k < numSensors; k++) { 771 int sensorNumber = in.readInt(); 772 Uid.Sensor sensor = new Sensor(sensorNumber); 773 sensor.readFromParcelLocked(mUnpluggables, in); 774 mSensorStats.put(sensorNumber, sensor); 775 } 776 777 int numProcs = in.readInt(); 778 mProcessStats.clear(); 779 for (int k = 0; k < numProcs; k++) { 780 String processName = in.readString(); 781 Uid.Proc proc = new Proc(); 782 proc.readFromParcelLocked(in); 783 mProcessStats.put(processName, proc); 784 } 785 786 int numPkgs = in.readInt(); 787 mPackageStats.clear(); 788 for (int l = 0; l < numPkgs; l++) { 789 String packageName = in.readString(); 790 Uid.Pkg pkg = new Pkg(); 791 pkg.readFromParcelLocked(in); 792 mPackageStats.put(packageName, pkg); 793 } 794 795 mLoadedTcpBytesReceived = in.readLong(); 796 mLoadedTcpBytesSent = in.readLong(); 797 mCurrentTcpBytesReceived = in.readLong(); 798 mCurrentTcpBytesSent = in.readLong(); 799 mTcpBytesReceivedAtLastUnplug = in.readLong(); 800 mTcpBytesSentAtLastUnplug = in.readLong(); 801 mFullWifiLockOut = false; 802 mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables, in); 803 mScanWifiLockOut = false; 804 mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables, in); 805 } 806 807 /** 808 * The statistics associated with a particular wake lock. 809 */ 810 public final class Wakelock extends BatteryStats.Uid.Wakelock { 811 /** 812 * How long (in ms) this uid has been keeping the device partially awake. 813 */ 814 Timer mTimerPartial; 815 816 /** 817 * How long (in ms) this uid has been keeping the device fully awake. 818 */ 819 Timer mTimerFull; 820 821 /** 822 * How long (in ms) this uid has had a window keeping the device awake. 823 */ 824 Timer mTimerWindow; 825 826 /** 827 * Reads a possibly null Timer from a Parcel. The timer is associated with the 828 * proper timer pool from the given BatteryStatsImpl object. 829 * 830 * @param in the Parcel to be read from. 831 * return a new Timer, or null. 832 */ 833 private Timer readTimerFromParcel(int type, ArrayList<Timer> pool, 834 ArrayList<Unpluggable> unpluggables, Parcel in) { 835 if (in.readInt() == 0) { 836 return null; 837 } 838 839 return new Timer(type, pool, unpluggables, in); 840 } 841 842 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 843 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL, 844 mPartialTimers, unpluggables, in); 845 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, 846 mFullTimers, unpluggables, in); 847 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, 848 mWindowTimers, unpluggables, in); 849 } 850 851 void writeToParcelLocked(Parcel out, long batteryRealtime) { 852 Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime); 853 Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime); 854 Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime); 855 } 856 857 @Override 858 public Timer getWakeTime(int type) { 859 switch (type) { 860 case WAKE_TYPE_FULL: return mTimerFull; 861 case WAKE_TYPE_PARTIAL: return mTimerPartial; 862 case WAKE_TYPE_WINDOW: return mTimerWindow; 863 default: throw new IllegalArgumentException("type = " + type); 864 } 865 } 866 } 867 868 public final class Sensor extends BatteryStats.Uid.Sensor { 869 final int mHandle; 870 Timer mTimer; 871 872 public Sensor(int handle) { 873 mHandle = handle; 874 } 875 876 private Timer readTimerFromParcel(ArrayList<Unpluggable> unpluggables, 877 Parcel in) { 878 if (in.readInt() == 0) { 879 return null; 880 } 881 882 ArrayList<Timer> pool = mSensorTimers.get(mHandle); 883 if (pool == null) { 884 pool = new ArrayList<Timer>(); 885 mSensorTimers.put(mHandle, pool); 886 } 887 return new Timer(0, pool, unpluggables, in); 888 } 889 890 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 891 mTimer = readTimerFromParcel(unpluggables, in); 892 } 893 894 void writeToParcelLocked(Parcel out, long batteryRealtime) { 895 Timer.writeTimerToParcel(out, mTimer, batteryRealtime); 896 } 897 898 @Override 899 public Timer getSensorTime() { 900 return mTimer; 901 } 902 903 public int getHandle() { 904 return mHandle; 905 } 906 } 907 908 /** 909 * The statistics associated with a particular process. 910 */ 911 public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable { 912 /** 913 * Total time (in 1/100 sec) spent executing in user code. 914 */ 915 long mUserTime; 916 917 /** 918 * Total time (in 1/100 sec) spent executing in kernel code. 919 */ 920 long mSystemTime; 921 922 /** 923 * Number of times the process has been started. 924 */ 925 int mStarts; 926 927 /** 928 * The amount of user time loaded from a previous save. 929 */ 930 long mLoadedUserTime; 931 932 /** 933 * The amount of system time loaded from a previous save. 934 */ 935 long mLoadedSystemTime; 936 937 /** 938 * The number of times the process has started from a previous save. 939 */ 940 int mLoadedStarts; 941 942 /** 943 * The amount of user time loaded from the previous run. 944 */ 945 long mLastUserTime; 946 947 /** 948 * The amount of system time loaded from the previous run. 949 */ 950 long mLastSystemTime; 951 952 /** 953 * The number of times the process has started from the previous run. 954 */ 955 int mLastStarts; 956 957 /** 958 * The amount of user time when last unplugged. 959 */ 960 long mUnpluggedUserTime; 961 962 /** 963 * The amount of system time when last unplugged. 964 */ 965 long mUnpluggedSystemTime; 966 967 /** 968 * The number of times the process has started before unplugged. 969 */ 970 int mUnpluggedStarts; 971 972 Proc() { 973 mUnpluggables.add(this); 974 } 975 976 public void unplug(long batteryUptime, long batteryRealtime) { 977 mUnpluggedUserTime = mUserTime; 978 mUnpluggedSystemTime = mSystemTime; 979 mUnpluggedStarts = mStarts; 980 } 981 982 public void plug(long batteryUptime, long batteryRealtime) { 983 } 984 985 void writeToParcelLocked(Parcel out) { 986 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 987 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 988 989 out.writeLong(mUserTime); 990 out.writeLong(mSystemTime); 991 out.writeInt(mStarts); 992 out.writeLong(mLoadedUserTime); 993 out.writeLong(mLoadedSystemTime); 994 out.writeInt(mLoadedStarts); 995 out.writeLong(mLastUserTime); 996 out.writeLong(mLastSystemTime); 997 out.writeInt(mLastStarts); 998 out.writeLong(mUnpluggedUserTime); 999 out.writeLong(mUnpluggedSystemTime); 1000 out.writeInt(mUnpluggedStarts); 1001 } 1002 1003 void readFromParcelLocked(Parcel in) { 1004 mUserTime = in.readLong(); 1005 mSystemTime = in.readLong(); 1006 mStarts = in.readInt(); 1007 mLoadedUserTime = in.readLong(); 1008 mLoadedSystemTime = in.readLong(); 1009 mLoadedStarts = in.readInt(); 1010 mLastUserTime = in.readLong(); 1011 mLastSystemTime = in.readLong(); 1012 mLastStarts = in.readInt(); 1013 mUnpluggedUserTime = in.readLong(); 1014 mUnpluggedSystemTime = in.readLong(); 1015 mUnpluggedStarts = in.readInt(); 1016 } 1017 1018 public BatteryStatsImpl getBatteryStats() { 1019 return BatteryStatsImpl.this; 1020 } 1021 1022 public void addCpuTimeLocked(int utime, int stime) { 1023 mUserTime += utime; 1024 mSystemTime += stime; 1025 } 1026 1027 public void incStartsLocked() { 1028 mStarts++; 1029 } 1030 1031 @Override 1032 public long getUserTime(int which) { 1033 long val; 1034 if (which == STATS_LAST) { 1035 val = mLastUserTime; 1036 } else { 1037 val = mUserTime; 1038 if (which == STATS_CURRENT) { 1039 val -= mLoadedUserTime; 1040 } else if (which == STATS_UNPLUGGED) { 1041 val -= mUnpluggedUserTime; 1042 } 1043 } 1044 return val; 1045 } 1046 1047 @Override 1048 public long getSystemTime(int which) { 1049 long val; 1050 if (which == STATS_LAST) { 1051 val = mLastSystemTime; 1052 } else { 1053 val = mSystemTime; 1054 if (which == STATS_CURRENT) { 1055 val -= mLoadedSystemTime; 1056 } else if (which == STATS_UNPLUGGED) { 1057 val -= mUnpluggedSystemTime; 1058 } 1059 } 1060 return val; 1061 } 1062 1063 @Override 1064 public int getStarts(int which) { 1065 int val; 1066 if (which == STATS_LAST) { 1067 val = mLastStarts; 1068 } else { 1069 val = mStarts; 1070 if (which == STATS_CURRENT) { 1071 val -= mLoadedStarts; 1072 } else if (which == STATS_UNPLUGGED) { 1073 val -= mUnpluggedStarts; 1074 } 1075 } 1076 return val; 1077 } 1078 } 1079 1080 /** 1081 * The statistics associated with a particular package. 1082 */ 1083 public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable { 1084 /** 1085 * Number of times this package has done something that could wake up the 1086 * device from sleep. 1087 */ 1088 int mWakeups; 1089 1090 /** 1091 * Number of things that could wake up the device loaded from a 1092 * previous save. 1093 */ 1094 int mLoadedWakeups; 1095 1096 /** 1097 * Number of things that could wake up the device as of the 1098 * last run. 1099 */ 1100 int mLastWakeups; 1101 1102 /** 1103 * Number of things that could wake up the device as of the 1104 * last run. 1105 */ 1106 int mUnpluggedWakeups; 1107 1108 /** 1109 * The statics we have collected for this package's services. 1110 */ 1111 final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>(); 1112 1113 Pkg() { 1114 mUnpluggables.add(this); 1115 } 1116 1117 public void unplug(long batteryUptime, long batteryRealtime) { 1118 mUnpluggedWakeups = mWakeups; 1119 } 1120 1121 public void plug(long batteryUptime, long batteryRealtime) { 1122 } 1123 1124 void readFromParcelLocked(Parcel in) { 1125 mWakeups = in.readInt(); 1126 mLoadedWakeups = in.readInt(); 1127 mLastWakeups = in.readInt(); 1128 mUnpluggedWakeups = in.readInt(); 1129 1130 int numServs = in.readInt(); 1131 mServiceStats.clear(); 1132 for (int m = 0; m < numServs; m++) { 1133 String serviceName = in.readString(); 1134 Uid.Pkg.Serv serv = new Serv(); 1135 mServiceStats.put(serviceName, serv); 1136 1137 serv.readFromParcelLocked(in); 1138 } 1139 } 1140 1141 void writeToParcelLocked(Parcel out) { 1142 out.writeInt(mWakeups); 1143 out.writeInt(mLoadedWakeups); 1144 out.writeInt(mLastWakeups); 1145 out.writeInt(mUnpluggedWakeups); 1146 1147 out.writeInt(mServiceStats.size()); 1148 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) { 1149 out.writeString(servEntry.getKey()); 1150 Uid.Pkg.Serv serv = servEntry.getValue(); 1151 1152 serv.writeToParcelLocked(out); 1153 } 1154 } 1155 1156 @Override 1157 public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() { 1158 return mServiceStats; 1159 } 1160 1161 @Override 1162 public int getWakeups(int which) { 1163 int val; 1164 if (which == STATS_LAST) { 1165 val = mLastWakeups; 1166 } else { 1167 val = mWakeups; 1168 if (which == STATS_CURRENT) { 1169 val -= mLoadedWakeups; 1170 } else if (which == STATS_UNPLUGGED) { 1171 val -= mUnpluggedWakeups; 1172 } 1173 } 1174 1175 return val; 1176 } 1177 1178 /** 1179 * The statistics associated with a particular service. 1180 */ 1181 public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable { 1182 /** 1183 * Total time (ms in battery uptime) the service has been left started. 1184 */ 1185 long mStartTime; 1186 1187 /** 1188 * If service has been started and not yet stopped, this is 1189 * when it was started. 1190 */ 1191 long mRunningSince; 1192 1193 /** 1194 * True if we are currently running. 1195 */ 1196 boolean mRunning; 1197 1198 /** 1199 * Total number of times startService() has been called. 1200 */ 1201 int mStarts; 1202 1203 /** 1204 * Total time (ms in battery uptime) the service has been left launched. 1205 */ 1206 long mLaunchedTime; 1207 1208 /** 1209 * If service has been launched and not yet exited, this is 1210 * when it was launched (ms in battery uptime). 1211 */ 1212 long mLaunchedSince; 1213 1214 /** 1215 * True if we are currently launched. 1216 */ 1217 boolean mLaunched; 1218 1219 /** 1220 * Total number times the service has been launched. 1221 */ 1222 int mLaunches; 1223 1224 /** 1225 * The amount of time spent started loaded from a previous save 1226 * (ms in battery uptime). 1227 */ 1228 long mLoadedStartTime; 1229 1230 /** 1231 * The number of starts loaded from a previous save. 1232 */ 1233 int mLoadedStarts; 1234 1235 /** 1236 * The number of launches loaded from a previous save. 1237 */ 1238 int mLoadedLaunches; 1239 1240 /** 1241 * The amount of time spent started as of the last run (ms 1242 * in battery uptime). 1243 */ 1244 long mLastStartTime; 1245 1246 /** 1247 * The number of starts as of the last run. 1248 */ 1249 int mLastStarts; 1250 1251 /** 1252 * The number of launches as of the last run. 1253 */ 1254 int mLastLaunches; 1255 1256 /** 1257 * The amount of time spent started when last unplugged (ms 1258 * in battery uptime). 1259 */ 1260 long mUnpluggedStartTime; 1261 1262 /** 1263 * The number of starts when last unplugged. 1264 */ 1265 int mUnpluggedStarts; 1266 1267 /** 1268 * The number of launches when last unplugged. 1269 */ 1270 int mUnpluggedLaunches; 1271 1272 Serv() { 1273 mUnpluggables.add(this); 1274 } 1275 1276 public void unplug(long batteryUptime, long batteryRealtime) { 1277 mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime); 1278 mUnpluggedStarts = mStarts; 1279 mUnpluggedLaunches = mLaunches; 1280 } 1281 1282 public void plug(long batteryUptime, long batteryRealtime) { 1283 } 1284 1285 void readFromParcelLocked(Parcel in) { 1286 mStartTime = in.readLong(); 1287 mRunningSince = in.readLong(); 1288 mRunning = in.readInt() != 0; 1289 mStarts = in.readInt(); 1290 mLaunchedTime = in.readLong(); 1291 mLaunchedSince = in.readLong(); 1292 mLaunched = in.readInt() != 0; 1293 mLaunches = in.readInt(); 1294 mLoadedStartTime = in.readLong(); 1295 mLoadedStarts = in.readInt(); 1296 mLoadedLaunches = in.readInt(); 1297 mLastStartTime = in.readLong(); 1298 mLastStarts = in.readInt(); 1299 mLastLaunches = in.readInt(); 1300 mUnpluggedStartTime = in.readLong(); 1301 mUnpluggedStarts = in.readInt(); 1302 mUnpluggedLaunches = in.readInt(); 1303 } 1304 1305 void writeToParcelLocked(Parcel out) { 1306 out.writeLong(mStartTime); 1307 out.writeLong(mRunningSince); 1308 out.writeInt(mRunning ? 1 : 0); 1309 out.writeInt(mStarts); 1310 out.writeLong(mLaunchedTime); 1311 out.writeLong(mLaunchedSince); 1312 out.writeInt(mLaunched ? 1 : 0); 1313 out.writeInt(mLaunches); 1314 out.writeLong(mLoadedStartTime); 1315 out.writeInt(mLoadedStarts); 1316 out.writeInt(mLoadedLaunches); 1317 out.writeLong(mLastStartTime); 1318 out.writeInt(mLastStarts); 1319 out.writeInt(mLastLaunches); 1320 out.writeLong(mUnpluggedStartTime); 1321 out.writeInt(mUnpluggedStarts); 1322 out.writeInt(mUnpluggedLaunches); 1323 } 1324 1325 long getLaunchTimeToNowLocked(long batteryUptime) { 1326 if (!mLaunched) return mLaunchedTime; 1327 return mLaunchedTime + batteryUptime - mLaunchedSince; 1328 } 1329 1330 long getStartTimeToNowLocked(long batteryUptime) { 1331 if (!mRunning) return mStartTime; 1332 return mStartTime + batteryUptime - mRunningSince; 1333 } 1334 1335 public void startLaunchedLocked() { 1336 if (!mLaunched) { 1337 mLaunches++; 1338 mLaunchedSince = getBatteryUptimeLocked(); 1339 mLaunched = true; 1340 } 1341 } 1342 1343 public void stopLaunchedLocked() { 1344 if (mLaunched) { 1345 long time = getBatteryUptimeLocked() - mLaunchedSince; 1346 if (time > 0) { 1347 mLaunchedTime += time; 1348 } else { 1349 mLaunches--; 1350 } 1351 mLaunched = false; 1352 } 1353 } 1354 1355 public void startRunningLocked() { 1356 if (!mRunning) { 1357 mStarts++; 1358 mRunningSince = getBatteryUptimeLocked(); 1359 mRunning = true; 1360 } 1361 } 1362 1363 public void stopRunningLocked() { 1364 if (mRunning) { 1365 long time = getBatteryUptimeLocked() - mRunningSince; 1366 if (time > 0) { 1367 mStartTime += time; 1368 } else { 1369 mStarts--; 1370 } 1371 mRunning = false; 1372 } 1373 } 1374 1375 public BatteryStatsImpl getBatteryStats() { 1376 return BatteryStatsImpl.this; 1377 } 1378 1379 @Override 1380 public int getLaunches(int which) { 1381 int val; 1382 1383 if (which == STATS_LAST) { 1384 val = mLastLaunches; 1385 } else { 1386 val = mLaunches; 1387 if (which == STATS_CURRENT) { 1388 val -= mLoadedLaunches; 1389 } else if (which == STATS_UNPLUGGED) { 1390 val -= mUnpluggedLaunches; 1391 } 1392 } 1393 1394 return val; 1395 } 1396 1397 @Override 1398 public long getStartTime(long now, int which) { 1399 long val; 1400 if (which == STATS_LAST) { 1401 val = mLastStartTime; 1402 } else { 1403 val = getStartTimeToNowLocked(now); 1404 if (which == STATS_CURRENT) { 1405 val -= mLoadedStartTime; 1406 } else if (which == STATS_UNPLUGGED) { 1407 val -= mUnpluggedStartTime; 1408 } 1409 } 1410 1411 return val; 1412 } 1413 1414 @Override 1415 public int getStarts(int which) { 1416 int val; 1417 if (which == STATS_LAST) { 1418 val = mLastStarts; 1419 } else { 1420 val = mStarts; 1421 if (which == STATS_CURRENT) { 1422 val -= mLoadedStarts; 1423 } else if (which == STATS_UNPLUGGED) { 1424 val -= mUnpluggedStarts; 1425 } 1426 } 1427 1428 return val; 1429 } 1430 } 1431 1432 public BatteryStatsImpl getBatteryStats() { 1433 return BatteryStatsImpl.this; 1434 } 1435 1436 public void incWakeupsLocked() { 1437 mWakeups++; 1438 } 1439 1440 final Serv newServiceStatsLocked() { 1441 return new Serv(); 1442 } 1443 } 1444 1445 /** 1446 * Retrieve the statistics object for a particular process, creating 1447 * if needed. 1448 */ 1449 public Proc getProcessStatsLocked(String name) { 1450 Proc ps = mProcessStats.get(name); 1451 if (ps == null) { 1452 ps = new Proc(); 1453 mProcessStats.put(name, ps); 1454 } 1455 1456 return ps; 1457 } 1458 1459 /** 1460 * Retrieve the statistics object for a particular service, creating 1461 * if needed. 1462 */ 1463 public Pkg getPackageStatsLocked(String name) { 1464 Pkg ps = mPackageStats.get(name); 1465 if (ps == null) { 1466 ps = new Pkg(); 1467 mPackageStats.put(name, ps); 1468 } 1469 1470 return ps; 1471 } 1472 1473 /** 1474 * Retrieve the statistics object for a particular service, creating 1475 * if needed. 1476 */ 1477 public Pkg.Serv getServiceStatsLocked(String pkg, String serv) { 1478 Pkg ps = getPackageStatsLocked(pkg); 1479 Pkg.Serv ss = ps.mServiceStats.get(serv); 1480 if (ss == null) { 1481 ss = ps.newServiceStatsLocked(); 1482 ps.mServiceStats.put(serv, ss); 1483 } 1484 1485 return ss; 1486 } 1487 1488 public Timer getWakeTimerLocked(String name, int type) { 1489 Wakelock wl = mWakelockStats.get(name); 1490 if (wl == null) { 1491 wl = new Wakelock(); 1492 mWakelockStats.put(name, wl); 1493 } 1494 Timer t = null; 1495 switch (type) { 1496 case WAKE_TYPE_PARTIAL: 1497 t = wl.mTimerPartial; 1498 if (t == null) { 1499 t = new Timer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables); 1500 wl.mTimerPartial = t; 1501 } 1502 return t; 1503 case WAKE_TYPE_FULL: 1504 t = wl.mTimerFull; 1505 if (t == null) { 1506 t = new Timer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables); 1507 wl.mTimerFull = t; 1508 } 1509 return t; 1510 case WAKE_TYPE_WINDOW: 1511 t = wl.mTimerWindow; 1512 if (t == null) { 1513 t = new Timer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables); 1514 wl.mTimerWindow = t; 1515 } 1516 return t; 1517 default: 1518 throw new IllegalArgumentException("type=" + type); 1519 } 1520 } 1521 1522 public Timer getSensorTimerLocked(int sensor, boolean create) { 1523 Sensor se = mSensorStats.get(sensor); 1524 if (se == null) { 1525 if (!create) { 1526 return null; 1527 } 1528 se = new Sensor(sensor); 1529 mSensorStats.put(sensor, se); 1530 } 1531 Timer t = se.mTimer; 1532 if (t != null) { 1533 return t; 1534 } 1535 ArrayList<Timer> timers = mSensorTimers.get(sensor); 1536 if (timers == null) { 1537 timers = new ArrayList<Timer>(); 1538 mSensorTimers.put(sensor, timers); 1539 } 1540 t = new Timer(BatteryStats.SENSOR, timers, mUnpluggables); 1541 se.mTimer = t; 1542 return t; 1543 } 1544 1545 public void noteStartWakeLocked(String name, int type) { 1546 Timer t = getWakeTimerLocked(name, type); 1547 if (t != null) { 1548 t.startRunningLocked(BatteryStatsImpl.this); 1549 } 1550 } 1551 1552 public void noteStopWakeLocked(String name, int type) { 1553 Timer t = getWakeTimerLocked(name, type); 1554 if (t != null) { 1555 t.stopRunningLocked(BatteryStatsImpl.this); 1556 } 1557 } 1558 1559 public void noteStartSensor(int sensor) { 1560 Timer t = getSensorTimerLocked(sensor, true); 1561 if (t != null) { 1562 t.startRunningLocked(BatteryStatsImpl.this); 1563 } 1564 } 1565 1566 public void noteStopSensor(int sensor) { 1567 // Don't create a timer if one doesn't already exist 1568 Timer t = getSensorTimerLocked(sensor, false); 1569 if (t != null) { 1570 t.stopRunningLocked(BatteryStatsImpl.this); 1571 } 1572 } 1573 1574 public void noteStartGps() { 1575 Timer t = getSensorTimerLocked(Sensor.GPS, true); 1576 if (t != null) { 1577 t.startRunningLocked(BatteryStatsImpl.this); 1578 } 1579 } 1580 1581 public void noteStopGps() { 1582 Timer t = getSensorTimerLocked(Sensor.GPS, false); 1583 if (t != null) { 1584 t.stopRunningLocked(BatteryStatsImpl.this); 1585 } 1586 } 1587 1588 public BatteryStatsImpl getBatteryStats() { 1589 return BatteryStatsImpl.this; 1590 } 1591 } 1592 1593 public BatteryStatsImpl(String filename) { 1594 mFile = new File(filename); 1595 mBackupFile = new File(filename + ".bak"); 1596 mStartCount++; 1597 mScreenOnTimer = new Timer(-1, null, mUnpluggables); 1598 mPhoneOnTimer = new Timer(-2, null, mUnpluggables); 1599 mWifiOnTimer = new Timer(-3, null, mUnpluggables); 1600 mBluetoothOnTimer = new Timer(-4, null, mUnpluggables); 1601 mOnBattery = mOnBatteryInternal = false; 1602 mTrackBatteryPastUptime = 0; 1603 mTrackBatteryPastRealtime = 0; 1604 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; 1605 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; 1606 mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); 1607 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); 1608 mUnpluggedStartLevel = 0; 1609 mPluggedStartLevel = 0; 1610 } 1611 1612 public BatteryStatsImpl(Parcel p) { 1613 mFile = mBackupFile = null; 1614 readFromParcel(p); 1615 } 1616 1617 @Override 1618 public int getStartCount() { 1619 return mStartCount; 1620 } 1621 1622 public boolean isOnBattery() { 1623 return mOnBattery; 1624 } 1625 1626 public void setOnBattery(boolean onBattery, int level) { 1627 synchronized(this) { 1628 if (mOnBattery != onBattery) { 1629 mOnBattery = mOnBatteryInternal = onBattery; 1630 1631 long uptime = SystemClock.uptimeMillis() * 1000; 1632 long mSecRealtime = SystemClock.elapsedRealtime(); 1633 long realtime = mSecRealtime * 1000; 1634 if (onBattery) { 1635 mTrackBatteryUptimeStart = uptime; 1636 mTrackBatteryRealtimeStart = realtime; 1637 mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); 1638 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); 1639 mUnpluggedStartLevel = level; 1640 doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); 1641 } else { 1642 mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; 1643 mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; 1644 mPluggedStartLevel = level; 1645 doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); 1646 } 1647 if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) { 1648 if (mFile != null) { 1649 writeLocked(); 1650 } 1651 } 1652 } 1653 } 1654 } 1655 1656 public long getAwakeTimeBattery() { 1657 return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT); 1658 } 1659 1660 public long getAwakeTimePlugged() { 1661 return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery(); 1662 } 1663 1664 @Override 1665 public long computeUptime(long curTime, int which) { 1666 switch (which) { 1667 case STATS_TOTAL: return mUptime + (curTime-mUptimeStart); 1668 case STATS_LAST: return mLastUptime; 1669 case STATS_CURRENT: return (curTime-mUptimeStart); 1670 case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart); 1671 } 1672 return 0; 1673 } 1674 1675 @Override 1676 public long computeRealtime(long curTime, int which) { 1677 switch (which) { 1678 case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart); 1679 case STATS_LAST: return mLastRealtime; 1680 case STATS_CURRENT: return (curTime-mRealtimeStart); 1681 case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart); 1682 } 1683 return 0; 1684 } 1685 1686 @Override 1687 public long computeBatteryUptime(long curTime, int which) { 1688 switch (which) { 1689 case STATS_TOTAL: 1690 return mBatteryUptime + getBatteryUptime(curTime); 1691 case STATS_LAST: 1692 return mBatteryLastUptime; 1693 case STATS_CURRENT: 1694 return getBatteryUptime(curTime); 1695 case STATS_UNPLUGGED: 1696 return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime; 1697 } 1698 return 0; 1699 } 1700 1701 @Override 1702 public long computeBatteryRealtime(long curTime, int which) { 1703 switch (which) { 1704 case STATS_TOTAL: 1705 return mBatteryRealtime + getBatteryRealtimeLocked(curTime); 1706 case STATS_LAST: 1707 return mBatteryLastRealtime; 1708 case STATS_CURRENT: 1709 return getBatteryRealtimeLocked(curTime); 1710 case STATS_UNPLUGGED: 1711 return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime; 1712 } 1713 return 0; 1714 } 1715 1716 long getBatteryUptimeLocked(long curTime) { 1717 long time = mTrackBatteryPastUptime; 1718 if (mOnBatteryInternal) { 1719 time += curTime - mTrackBatteryUptimeStart; 1720 } 1721 return time; 1722 } 1723 1724 long getBatteryUptimeLocked() { 1725 return getBatteryUptime(SystemClock.uptimeMillis() * 1000); 1726 } 1727 1728 @Override 1729 public long getBatteryUptime(long curTime) { 1730 return getBatteryUptimeLocked(curTime); 1731 } 1732 1733 long getBatteryRealtimeLocked(long curTime) { 1734 long time = mTrackBatteryPastRealtime; 1735 if (mOnBatteryInternal) { 1736 time += curTime - mTrackBatteryRealtimeStart; 1737 } 1738 return time; 1739 } 1740 1741 @Override 1742 public long getBatteryRealtime(long curTime) { 1743 return getBatteryRealtimeLocked(curTime); 1744 } 1745 1746 @Override 1747 public int getUnpluggedStartLevel() { 1748 synchronized(this) { 1749 return getUnluggedStartLevelLocked(); 1750 } 1751 } 1752 1753 public int getUnluggedStartLevelLocked() { 1754 return mUnpluggedStartLevel; 1755 } 1756 1757 @Override 1758 public int getPluggedStartLevel() { 1759 synchronized(this) { 1760 return getPluggedStartLevelLocked(); 1761 } 1762 } 1763 1764 public int getPluggedStartLevelLocked() { 1765 return mPluggedStartLevel; 1766 } 1767 1768 /** 1769 * Retrieve the statistics object for a particular uid, creating if needed. 1770 */ 1771 public Uid getUidStatsLocked(int uid) { 1772 Uid u = mUidStats.get(uid); 1773 if (u == null) { 1774 u = new Uid(uid); 1775 mUidStats.put(uid, u); 1776 } 1777 return u; 1778 } 1779 1780 /** 1781 * Remove the statistics object for a particular uid. 1782 */ 1783 public void removeUidStatsLocked(int uid) { 1784 mUidStats.remove(uid); 1785 } 1786 1787 /** 1788 * Retrieve the statistics object for a particular process, creating 1789 * if needed. 1790 */ 1791 public Uid.Proc getProcessStatsLocked(int uid, String name) { 1792 Uid u = getUidStatsLocked(uid); 1793 return u.getProcessStatsLocked(name); 1794 } 1795 1796 /** 1797 * Retrieve the statistics object for a particular process, creating 1798 * if needed. 1799 */ 1800 public Uid.Pkg getPackageStatsLocked(int uid, String pkg) { 1801 Uid u = getUidStatsLocked(uid); 1802 return u.getPackageStatsLocked(pkg); 1803 } 1804 1805 /** 1806 * Retrieve the statistics object for a particular service, creating 1807 * if needed. 1808 */ 1809 public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) { 1810 Uid u = getUidStatsLocked(uid); 1811 return u.getServiceStatsLocked(pkg, name); 1812 } 1813 1814 public void writeLocked() { 1815 if ((mFile == null) || (mBackupFile == null)) { 1816 Log.w("BatteryStats", "writeLocked: no file associated with this instance"); 1817 return; 1818 } 1819 1820 // Keep the old file around until we know the new one has 1821 // been successfully written. 1822 if (mFile.exists()) { 1823 if (mBackupFile.exists()) { 1824 mBackupFile.delete(); 1825 } 1826 mFile.renameTo(mBackupFile); 1827 } 1828 1829 try { 1830 FileOutputStream stream = new FileOutputStream(mFile); 1831 Parcel out = Parcel.obtain(); 1832 writeSummaryToParcel(out); 1833 stream.write(out.marshall()); 1834 out.recycle(); 1835 1836 stream.flush(); 1837 stream.close(); 1838 mBackupFile.delete(); 1839 1840 mLastWriteTime = SystemClock.elapsedRealtime(); 1841 } catch (IOException e) { 1842 Log.e("BatteryStats", "Error writing battery statistics", e); 1843 } 1844 } 1845 1846 static byte[] readFully(FileInputStream stream) throws java.io.IOException { 1847 int pos = 0; 1848 int avail = stream.available(); 1849 byte[] data = new byte[avail]; 1850 while (true) { 1851 int amt = stream.read(data, pos, data.length-pos); 1852 //Log.i("foo", "Read " + amt + " bytes at " + pos 1853 // + " of avail " + data.length); 1854 if (amt <= 0) { 1855 //Log.i("foo", "**** FINISHED READING: pos=" + pos 1856 // + " len=" + data.length); 1857 return data; 1858 } 1859 pos += amt; 1860 avail = stream.available(); 1861 if (avail > data.length-pos) { 1862 byte[] newData = new byte[pos+avail]; 1863 System.arraycopy(data, 0, newData, 0, pos); 1864 data = newData; 1865 } 1866 } 1867 } 1868 1869 public void readLocked() { 1870 if ((mFile == null) || (mBackupFile == null)) { 1871 Log.w("BatteryStats", "readLocked: no file associated with this instance"); 1872 return; 1873 } 1874 1875 mUidStats.clear(); 1876 1877 FileInputStream stream = null; 1878 if (mBackupFile.exists()) { 1879 try { 1880 stream = new FileInputStream(mBackupFile); 1881 } catch (java.io.IOException e) { 1882 // We'll try for the normal settings file. 1883 } 1884 } 1885 1886 try { 1887 if (stream == null) { 1888 if (!mFile.exists()) { 1889 return; 1890 } 1891 stream = new FileInputStream(mFile); 1892 } 1893 1894 byte[] raw = readFully(stream); 1895 Parcel in = Parcel.obtain(); 1896 in.unmarshall(raw, 0, raw.length); 1897 in.setDataPosition(0); 1898 stream.close(); 1899 1900 readSummaryFromParcel(in); 1901 } catch(java.io.IOException e) { 1902 Log.e("BatteryStats", "Error reading battery statistics", e); 1903 } 1904 } 1905 1906 public int describeContents() { 1907 return 0; 1908 } 1909 1910 private void readSummaryFromParcel(Parcel in) { 1911 final int version = in.readInt(); 1912 if (version != VERSION) { 1913 Log.w("BatteryStats", "readFromParcel: version got " + version 1914 + ", expected " + VERSION + "; erasing old stats"); 1915 return; 1916 } 1917 1918 mStartCount = in.readInt(); 1919 mBatteryUptime = in.readLong(); 1920 mBatteryLastUptime = in.readLong(); 1921 mBatteryRealtime = in.readLong(); 1922 mBatteryLastRealtime = in.readLong(); 1923 mUptime = in.readLong(); 1924 mLastUptime = in.readLong(); 1925 mRealtime = in.readLong(); 1926 mLastRealtime = in.readLong(); 1927 mUnpluggedStartLevel = in.readInt(); 1928 mPluggedStartLevel = in.readInt(); 1929 1930 mStartCount++; 1931 1932 mScreenOn = false; 1933 mScreenOnTimer.readSummaryFromParcelLocked(in); 1934 mPhoneOn = false; 1935 mPhoneOnTimer.readSummaryFromParcelLocked(in); 1936 mWifiOn = false; 1937 mWifiOnTimer.readSummaryFromParcelLocked(in); 1938 mBluetoothOn = false; 1939 mBluetoothOnTimer.readSummaryFromParcelLocked(in); 1940 1941 final int NU = in.readInt(); 1942 for (int iu = 0; iu < NU; iu++) { 1943 int uid = in.readInt(); 1944 Uid u = new Uid(uid); 1945 mUidStats.put(uid, u); 1946 1947 u.mFullWifiLockOut = false; 1948 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); 1949 u.mScanWifiLockOut = false; 1950 u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); 1951 1952 int NW = in.readInt(); 1953 for (int iw = 0; iw < NW; iw++) { 1954 String wlName = in.readString(); 1955 if (in.readInt() != 0) { 1956 u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in); 1957 } 1958 if (in.readInt() != 0) { 1959 u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in); 1960 } 1961 if (in.readInt() != 0) { 1962 u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in); 1963 } 1964 } 1965 1966 int NP = in.readInt(); 1967 for (int is = 0; is < NP; is++) { 1968 int seNumber = in.readInt(); 1969 if (in.readInt() != 0) { 1970 u.getSensorTimerLocked(seNumber, true) 1971 .readSummaryFromParcelLocked(in); 1972 } 1973 } 1974 1975 NP = in.readInt(); 1976 for (int ip = 0; ip < NP; ip++) { 1977 String procName = in.readString(); 1978 Uid.Proc p = u.getProcessStatsLocked(procName); 1979 p.mUserTime = p.mLoadedUserTime = in.readLong(); 1980 p.mLastUserTime = in.readLong(); 1981 p.mSystemTime = p.mLoadedSystemTime = in.readLong(); 1982 p.mLastSystemTime = in.readLong(); 1983 p.mStarts = p.mLoadedStarts = in.readInt(); 1984 p.mLastStarts = in.readInt(); 1985 } 1986 1987 NP = in.readInt(); 1988 for (int ip = 0; ip < NP; ip++) { 1989 String pkgName = in.readString(); 1990 Uid.Pkg p = u.getPackageStatsLocked(pkgName); 1991 p.mWakeups = p.mLoadedWakeups = in.readInt(); 1992 p.mLastWakeups = in.readInt(); 1993 final int NS = in.readInt(); 1994 for (int is = 0; is < NS; is++) { 1995 String servName = in.readString(); 1996 Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName); 1997 s.mStartTime = s.mLoadedStartTime = in.readLong(); 1998 s.mLastStartTime = in.readLong(); 1999 s.mStarts = s.mLoadedStarts = in.readInt(); 2000 s.mLastStarts = in.readInt(); 2001 s.mLaunches = s.mLoadedLaunches = in.readInt(); 2002 s.mLastLaunches = in.readInt(); 2003 } 2004 } 2005 2006 u.mLoadedTcpBytesReceived = in.readLong(); 2007 u.mLoadedTcpBytesSent = in.readLong(); 2008 } 2009 } 2010 2011 /** 2012 * Writes a summary of the statistics to a Parcel, in a format suitable to be written to 2013 * disk. This format does not allow a lossless round-trip. 2014 * 2015 * @param out the Parcel to be written to. 2016 */ 2017 public void writeSummaryToParcel(Parcel out) { 2018 final long NOW_SYS = SystemClock.uptimeMillis() * 1000; 2019 final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; 2020 final long NOW = getBatteryUptimeLocked(NOW_SYS); 2021 final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS); 2022 2023 out.writeInt(VERSION); 2024 2025 out.writeInt(mStartCount); 2026 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_TOTAL)); 2027 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT)); 2028 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_TOTAL)); 2029 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT)); 2030 out.writeLong(computeUptime(NOW_SYS, STATS_TOTAL)); 2031 out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT)); 2032 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL)); 2033 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT)); 2034 out.writeInt(mUnpluggedStartLevel); 2035 out.writeInt(mPluggedStartLevel); 2036 2037 2038 mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2039 mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2040 mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2041 mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2042 2043 final int NU = mUidStats.size(); 2044 out.writeInt(NU); 2045 for (int iu = 0; iu < NU; iu++) { 2046 out.writeInt(mUidStats.keyAt(iu)); 2047 Uid u = mUidStats.valueAt(iu); 2048 2049 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2050 u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2051 2052 int NW = u.mWakelockStats.size(); 2053 out.writeInt(NW); 2054 if (NW > 0) { 2055 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent 2056 : u.mWakelockStats.entrySet()) { 2057 out.writeString(ent.getKey()); 2058 Uid.Wakelock wl = ent.getValue(); 2059 if (wl.mTimerFull != null) { 2060 out.writeInt(1); 2061 wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL); 2062 } else { 2063 out.writeInt(0); 2064 } 2065 if (wl.mTimerPartial != null) { 2066 out.writeInt(1); 2067 wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL); 2068 } else { 2069 out.writeInt(0); 2070 } 2071 if (wl.mTimerWindow != null) { 2072 out.writeInt(1); 2073 wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL); 2074 } else { 2075 out.writeInt(0); 2076 } 2077 } 2078 } 2079 2080 int NSE = u.mSensorStats.size(); 2081 out.writeInt(NSE); 2082 if (NSE > 0) { 2083 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent 2084 : u.mSensorStats.entrySet()) { 2085 out.writeInt(ent.getKey()); 2086 Uid.Sensor se = ent.getValue(); 2087 if (se.mTimer != null) { 2088 out.writeInt(1); 2089 se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL); 2090 } else { 2091 out.writeInt(0); 2092 } 2093 } 2094 } 2095 2096 int NP = u.mProcessStats.size(); 2097 out.writeInt(NP); 2098 if (NP > 0) { 2099 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent 2100 : u.mProcessStats.entrySet()) { 2101 out.writeString(ent.getKey()); 2102 Uid.Proc ps = ent.getValue(); 2103 out.writeLong(ps.mUserTime); 2104 out.writeLong(ps.mUserTime - ps.mLoadedUserTime); 2105 out.writeLong(ps.mSystemTime); 2106 out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime); 2107 out.writeInt(ps.mStarts); 2108 out.writeInt(ps.mStarts - ps.mLoadedStarts); 2109 } 2110 } 2111 2112 NP = u.mPackageStats.size(); 2113 out.writeInt(NP); 2114 if (NP > 0) { 2115 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent 2116 : u.mPackageStats.entrySet()) { 2117 out.writeString(ent.getKey()); 2118 Uid.Pkg ps = ent.getValue(); 2119 out.writeInt(ps.mWakeups); 2120 out.writeInt(ps.mWakeups - ps.mLoadedWakeups); 2121 final int NS = ps.mServiceStats.size(); 2122 out.writeInt(NS); 2123 if (NS > 0) { 2124 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent 2125 : ps.mServiceStats.entrySet()) { 2126 out.writeString(sent.getKey()); 2127 BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue(); 2128 long time = ss.getStartTimeToNowLocked(NOW); 2129 out.writeLong(time); 2130 out.writeLong(time - ss.mLoadedStartTime); 2131 out.writeInt(ss.mStarts); 2132 out.writeInt(ss.mStarts - ss.mLoadedStarts); 2133 out.writeInt(ss.mLaunches); 2134 out.writeInt(ss.mLaunches - ss.mLoadedLaunches); 2135 } 2136 } 2137 } 2138 } 2139 2140 out.writeLong(u.getTcpBytesReceived(STATS_TOTAL)); 2141 out.writeLong(u.getTcpBytesSent(STATS_TOTAL)); 2142 } 2143 } 2144 2145 public void readFromParcel(Parcel in) { 2146 readFromParcelLocked(in); 2147 } 2148 2149 void readFromParcelLocked(Parcel in) { 2150 int magic = in.readInt(); 2151 if (magic != MAGIC) { 2152 throw new ParcelFormatException("Bad magic number"); 2153 } 2154 2155 mStartCount = in.readInt(); 2156 mBatteryUptime = in.readLong(); 2157 mBatteryLastUptime = in.readLong(); 2158 mBatteryRealtime = in.readLong(); 2159 mBatteryLastRealtime = in.readLong(); 2160 mScreenOn = false; 2161 mScreenOnTimer = new Timer(-1, null, mUnpluggables, in); 2162 mPhoneOn = false; 2163 mPhoneOnTimer = new Timer(-2, null, mUnpluggables, in); 2164 mWifiOn = false; 2165 mWifiOnTimer = new Timer(-2, null, mUnpluggables, in); 2166 mBluetoothOn = false; 2167 mBluetoothOnTimer = new Timer(-2, null, mUnpluggables, in); 2168 mUptime = in.readLong(); 2169 mUptimeStart = in.readLong(); 2170 mLastUptime = in.readLong(); 2171 mRealtime = in.readLong(); 2172 mRealtimeStart = in.readLong(); 2173 mLastRealtime = in.readLong(); 2174 mOnBattery = in.readInt() != 0; 2175 mOnBatteryInternal = false; // we are no longer really running. 2176 mTrackBatteryPastUptime = in.readLong(); 2177 mTrackBatteryUptimeStart = in.readLong(); 2178 mTrackBatteryPastRealtime = in.readLong(); 2179 mTrackBatteryRealtimeStart = in.readLong(); 2180 mUnpluggedBatteryUptime = in.readLong(); 2181 mUnpluggedBatteryRealtime = in.readLong(); 2182 mUnpluggedStartLevel = in.readInt(); 2183 mPluggedStartLevel = in.readInt(); 2184 mLastWriteTime = in.readLong(); 2185 2186 mPartialTimers.clear(); 2187 mFullTimers.clear(); 2188 mWindowTimers.clear(); 2189 2190 int numUids = in.readInt(); 2191 mUidStats.clear(); 2192 for (int i = 0; i < numUids; i++) { 2193 int uid = in.readInt(); 2194 Uid u = new Uid(uid); 2195 u.readFromParcelLocked(mUnpluggables, in); 2196 mUidStats.append(uid, u); 2197 } 2198 } 2199 2200 public void writeToParcel(Parcel out, int flags) { 2201 writeToParcelLocked(out, flags); 2202 } 2203 2204 @SuppressWarnings("unused") 2205 void writeToParcelLocked(Parcel out, int flags) { 2206 final long uSecUptime = SystemClock.uptimeMillis() * 1000; 2207 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 2208 final long batteryUptime = getBatteryUptimeLocked(uSecUptime); 2209 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 2210 2211 out.writeInt(MAGIC); 2212 out.writeInt(mStartCount); 2213 out.writeLong(mBatteryUptime); 2214 out.writeLong(mBatteryLastUptime); 2215 out.writeLong(mBatteryRealtime); 2216 out.writeLong(mBatteryLastRealtime); 2217 mScreenOnTimer.writeToParcel(out, batteryRealtime); 2218 mPhoneOnTimer.writeToParcel(out, batteryRealtime); 2219 mWifiOnTimer.writeToParcel(out, batteryRealtime); 2220 mBluetoothOnTimer.writeToParcel(out, batteryRealtime); 2221 out.writeLong(mUptime); 2222 out.writeLong(mUptimeStart); 2223 out.writeLong(mLastUptime); 2224 out.writeLong(mRealtime); 2225 out.writeLong(mRealtimeStart); 2226 out.writeLong(mLastRealtime); 2227 out.writeInt(mOnBattery ? 1 : 0); 2228 out.writeLong(batteryUptime); 2229 out.writeLong(mTrackBatteryUptimeStart); 2230 out.writeLong(batteryRealtime); 2231 out.writeLong(mTrackBatteryRealtimeStart); 2232 out.writeLong(mUnpluggedBatteryUptime); 2233 out.writeLong(mUnpluggedBatteryRealtime); 2234 out.writeInt(mUnpluggedStartLevel); 2235 out.writeInt(mPluggedStartLevel); 2236 out.writeLong(mLastWriteTime); 2237 2238 int size = mUidStats.size(); 2239 out.writeInt(size); 2240 for (int i = 0; i < size; i++) { 2241 out.writeInt(mUidStats.keyAt(i)); 2242 Uid uid = mUidStats.valueAt(i); 2243 2244 uid.writeToParcelLocked(out, batteryRealtime); 2245 } 2246 } 2247 2248 public static final Parcelable.Creator<BatteryStatsImpl> CREATOR = 2249 new Parcelable.Creator<BatteryStatsImpl>() { 2250 public BatteryStatsImpl createFromParcel(Parcel in) { 2251 return new BatteryStatsImpl(in); 2252 } 2253 2254 public BatteryStatsImpl[] newArray(int size) { 2255 return new BatteryStatsImpl[size]; 2256 } 2257 }; 2258 2259 public void dumpLocked(Printer pw) { 2260 if (DEBUG) { 2261 Log.i(TAG, "*** Screen timer:"); 2262 mScreenOnTimer.logState(); 2263 Log.i(TAG, "*** Phone timer:"); 2264 mPhoneOnTimer.logState(); 2265 Log.i(TAG, "*** Wifi timer:"); 2266 mWifiOnTimer.logState(); 2267 Log.i(TAG, "*** Bluetooth timer:"); 2268 mBluetoothOnTimer.logState(); 2269 } 2270 super.dumpLocked(pw); 2271 } 2272} 2273