BatteryStatsImpl.java revision f013e1afd1e68af5e3b868c26a653bbfb39538f8
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.Parcel; 21import android.os.ParcelFormatException; 22import android.os.Parcelable; 23import android.os.SystemClock; 24import android.util.Log; 25import android.util.SparseArray; 26 27import java.io.File; 28import java.io.FileInputStream; 29import java.io.FileOutputStream; 30import java.io.IOException; 31import java.lang.ref.WeakReference; 32import java.util.ArrayList; 33import java.util.HashMap; 34import java.util.Map; 35 36/** 37 * All information we are collecting about things that can happen that impact 38 * battery life. All times are represented in microseconds except where indicated 39 * otherwise. 40 */ 41public final class BatteryStatsImpl extends BatteryStats implements Parcelable { 42 43 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data 44 private static final int MAGIC = 0xBA757475; // 'BATSTATS' 45 46 // Current on-disk Parcel version 47 private static final int VERSION = 13; 48 49 private final File mFile; 50 private final File mBackupFile; 51 52 /** 53 * The statistics we have collected organized by uids. 54 */ 55 final SparseArray<BatteryStatsImpl.Uid> mUidStats = 56 new SparseArray<BatteryStatsImpl.Uid>(); 57 58 // A set of pools of currently active timers. When a timer is queried, we will divide the 59 // elapsed time by the number of active timers to arrive at that timer's share of the time. 60 // In order to do this, we must refresh each timer whenever the number of active timers 61 // changes. 62 final ArrayList<Timer> mPartialTimers = new ArrayList<Timer>(); 63 final ArrayList<Timer> mFullTimers = new ArrayList<Timer>(); 64 final ArrayList<Timer> mWindowTimers = new ArrayList<Timer>(); 65 final ArrayList<Timer> mSensorTimers = new ArrayList<Timer>(); 66 67 int mStartCount; 68 69 long mBatteryUptime; 70 long mBatteryLastUptime; 71 long mBatteryRealtime; 72 long mBatteryLastRealtime; 73 74 long mUptime; 75 long mUptimeStart; 76 long mLastUptime; 77 long mRealtime; 78 long mRealtimeStart; 79 long mLastRealtime; 80 81 /** 82 * These provide time bases that discount the time the device is plugged 83 * in to power. 84 */ 85 boolean mOnBattery; 86 long mTrackBatteryPastUptime; 87 long mTrackBatteryUptimeStart; 88 long mTrackBatteryPastRealtime; 89 long mTrackBatteryRealtimeStart; 90 91 long mLastWriteTime = 0; // Milliseconds 92 93 // For debugging 94 public BatteryStatsImpl() { 95 mFile = mBackupFile = null; 96 } 97 98 /** 99 * State for keeping track of timing information. 100 */ 101 public static final class Timer extends BatteryStats.Timer { 102 ArrayList<Timer> mTimerPool; 103 104 int mType; 105 int mNesting; 106 107 int mCount; 108 int mLoadedCount; 109 int mLastCount; 110 111 // Times are in microseconds for better accuracy when dividing by the lock count 112 113 long mTotalTime; // Add mUnpluggedTotalTime to get true value 114 long mLoadedTotalTime; 115 long mLastTotalTime; 116 long mStartTime; 117 long mUpdateTime; 118 119 /** 120 * The value of mTotalTime when unplug() was last called, initially 0. 121 */ 122 long mTotalTimeAtLastUnplug; 123 124 /** Constructor used for unmarshalling only. */ 125 Timer() {} 126 127 Timer(int type, ArrayList<Timer> timerPool) { 128 mType = type; 129 mTimerPool = timerPool; 130 } 131 132 public void writeToParcel(Parcel out) { 133 out.writeInt(mType); 134 out.writeInt(mNesting); 135 out.writeInt(mCount); 136 out.writeInt(mLoadedCount); 137 out.writeInt(mLastCount); 138 out.writeLong(mTotalTime); 139 out.writeLong(mLoadedTotalTime); 140 out.writeLong(mLastTotalTime); 141 out.writeLong(mStartTime); 142 out.writeLong(mUpdateTime); 143 out.writeLong(mTotalTimeAtLastUnplug); 144 } 145 146 public void readFromParcel(Parcel in) { 147 mType = in.readInt(); 148 mNesting = in.readInt(); 149 mCount = in.readInt(); 150 mLoadedCount = in.readInt(); 151 mLastCount = in.readInt(); 152 mTotalTime = in.readLong(); 153 mLoadedTotalTime = in.readLong(); 154 mLastTotalTime = in.readLong(); 155 mStartTime = in.readLong(); 156 mUpdateTime = in.readLong(); 157 mTotalTimeAtLastUnplug = in.readLong(); 158 } 159 160 private void unplug() { 161 mTotalTimeAtLastUnplug += mTotalTime; 162 mTotalTime = 0; 163 } 164 165 /** 166 * Writes a possibly null Timer to a Parcel. 167 * 168 * @param out the Parcel to be written to. 169 * @param timer a Timer, or null. 170 */ 171 public static void writeTimerToParcel(Parcel out, Timer timer) { 172 if (timer == null) { 173 out.writeInt(0); // indicates null 174 return; 175 } 176 out.writeInt(1); // indicates non-null 177 178 timer.writeToParcel(out); 179 } 180 181 @Override 182 public long getTotalTime(long now, int which) { 183 long val; 184 if (which == STATS_LAST) { 185 val = mLastTotalTime; 186 } else { 187 val = computeRunTimeLocked(now); 188 if (which != STATS_UNPLUGGED) { 189 val += mTotalTimeAtLastUnplug; 190 } 191 if ((which == STATS_CURRENT) || (which == STATS_UNPLUGGED)) { 192 val -= mLoadedTotalTime; 193 } 194 } 195 196 return val; 197 } 198 199 @Override 200 public int getCount(int which) { 201 int val; 202 if (which == STATS_LAST) { 203 val = mLastCount; 204 } else { 205 val = mCount; 206 if ((which == STATS_CURRENT) || (which == STATS_UNPLUGGED)) { 207 val -= mLoadedCount; 208 } 209 } 210 211 return val; 212 } 213 214 void startRunningLocked(BatteryStatsImpl stats) { 215 if (mNesting++ == 0) { 216 mStartTime = mUpdateTime = 217 stats.getBatteryUptimeLocked(SystemClock.elapsedRealtime() * 1000); 218 // Accumulate time to all other active counters with the current value of mCount 219 refreshTimersLocked(stats); 220 // Add this timer to the active pool 221 mTimerPool.add(this); 222 // Increment the count 223 mCount++; 224 } 225 } 226 227 void stopRunningLocked(BatteryStatsImpl stats) { 228 // Ignore attempt to stop a timer that isn't running 229 if (mNesting == 0) { 230 return; 231 } 232 if (--mNesting == 0) { 233 // Accumulate time to all active counters with the current value of mCount 234 refreshTimersLocked(stats); 235 // Remove this timer from the active pool 236 mTimerPool.remove(this); 237 // Decrement the count 238 mCount--; 239 } 240 } 241 242 // Update the total time for all other running Timers with the same type as this Timer 243 // due to a change in timer count 244 private void refreshTimersLocked(BatteryStatsImpl stats) { 245 for (Timer t : mTimerPool) { 246 t.updateTimeLocked(stats); 247 } 248 } 249 250 /** 251 * Update totalTime and reset updateTime 252 * @param stats 253 */ 254 private void updateTimeLocked(BatteryStatsImpl stats) { 255 long realtime = SystemClock.elapsedRealtime() * 1000; 256 long heldTime = stats.getBatteryUptimeLocked(realtime) - mUpdateTime; 257 if (heldTime > 0) { 258 mTotalTime += (heldTime * 1000) / mCount; 259 } 260 mUpdateTime = stats.getBatteryUptimeLocked(realtime); 261 } 262 263 private long computeRunTimeLocked(long curBatteryUptime) { 264 return mTotalTime + 265 (mNesting > 0 ? ((curBatteryUptime * 1000) - mUpdateTime) / mCount : 0); 266 } 267 268 void writeSummaryFromParcelLocked(Parcel out, long curBatteryUptime) { 269 long runTime = computeRunTimeLocked(curBatteryUptime); 270 // Divide by 1000 for backwards compatibility 271 out.writeLong((runTime + 500) / 1000); 272 out.writeLong(((runTime - mLoadedTotalTime) + 500) / 1000); 273 out.writeInt(mCount); 274 out.writeInt(mCount - mLoadedCount); 275 } 276 277 void readSummaryFromParcelLocked(Parcel in) { 278 // Multiply by 1000 for backwards compatibility 279 mTotalTime = mLoadedTotalTime = in.readLong() * 1000; 280 mLastTotalTime = in.readLong(); 281 mCount = mLoadedCount = in.readInt(); 282 mLastCount = in.readInt(); 283 mNesting = 0; 284 } 285 } 286 287 public void unplugTimers() { 288 ArrayList<Timer> timers; 289 290 timers = mPartialTimers; 291 for (int i = timers.size() - 1; i >= 0; i--) { 292 timers.get(i).unplug(); 293 } 294 timers = mFullTimers; 295 for (int i = timers.size() - 1; i >= 0; i--) { 296 timers.get(i).unplug(); 297 } 298 timers = mWindowTimers; 299 for (int i = timers.size() - 1; i >= 0; i--) { 300 timers.get(i).unplug(); 301 } 302 timers = mSensorTimers; 303 for (int i = timers.size() - 1; i >= 0; i--) { 304 timers.get(i).unplug(); 305 } 306 } 307 308 @Override 309 public SparseArray<? extends BatteryStats.Uid> getUidStats() { 310 return mUidStats; 311 } 312 313 /** 314 * The statistics associated with a particular uid. 315 */ 316 public final class Uid extends BatteryStats.Uid { 317 318 /** 319 * The statistics we have collected for this uid's wake locks. 320 */ 321 final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>(); 322 323 /** 324 * The statistics we have collected for this uid's sensor activations. 325 */ 326 final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>(); 327 328 /** 329 * The statistics we have collected for this uid's processes. 330 */ 331 final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>(); 332 333 /** 334 * The statistics we have collected for this uid's processes. 335 */ 336 final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>(); 337 338 @Override 339 public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() { 340 return mWakelockStats; 341 } 342 343 @Override 344 public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() { 345 return mSensorStats; 346 } 347 348 @Override 349 public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() { 350 return mProcessStats; 351 } 352 353 @Override 354 public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { 355 return mPackageStats; 356 } 357 358 void writeToParcelLocked(Parcel out) { 359 out.writeInt(mWakelockStats.size()); 360 for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) { 361 out.writeString(wakelockEntry.getKey()); 362 Uid.Wakelock wakelock = wakelockEntry.getValue(); 363 wakelock.writeToParcelLocked(out); 364 } 365 366 out.writeInt(mSensorStats.size()); 367 for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) { 368 out.writeInt(sensorEntry.getKey()); 369 Uid.Sensor sensor = sensorEntry.getValue(); 370 sensor.writeToParcelLocked(out); 371 } 372 373 out.writeInt(mProcessStats.size()); 374 for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) { 375 out.writeString(procEntry.getKey()); 376 Uid.Proc proc = procEntry.getValue(); 377 proc.writeToParcelLocked(out); 378 } 379 380 out.writeInt(mPackageStats.size()); 381 for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) { 382 out.writeString(pkgEntry.getKey()); 383 Uid.Pkg pkg = pkgEntry.getValue(); 384 pkg.writeToParcelLocked(out); 385 } 386 } 387 388 void readFromParcelLocked(Parcel in) { 389 int numWakelocks = in.readInt(); 390 mWakelockStats.clear(); 391 for (int j = 0; j < numWakelocks; j++) { 392 String wakelockName = in.readString(); 393 Uid.Wakelock wakelock = new Wakelock(); 394 wakelock.readFromParcelLocked(in); 395 mWakelockStats.put(wakelockName, wakelock); 396 } 397 398 int numSensors = in.readInt(); 399 mSensorStats.clear(); 400 for (int k = 0; k < numSensors; k++) { 401 int sensorNumber = in.readInt(); 402 Uid.Sensor sensor = new Sensor(); 403 sensor.readFromParcelLocked(in); 404 mSensorStats.put(sensorNumber, sensor); 405 } 406 407 int numProcs = in.readInt(); 408 mProcessStats.clear(); 409 for (int k = 0; k < numProcs; k++) { 410 String processName = in.readString(); 411 Uid.Proc proc = new Proc(); 412 proc.readFromParcelLocked(in); 413 mProcessStats.put(processName, proc); 414 } 415 416 int numPkgs = in.readInt(); 417 mPackageStats.clear(); 418 for (int l = 0; l < numPkgs; l++) { 419 String packageName = in.readString(); 420 Uid.Pkg pkg = new Pkg(); 421 pkg.readFromParcelLocked(in); 422 mPackageStats.put(packageName, pkg); 423 } 424 } 425 426 /** 427 * The statistics associated with a particular wake lock. 428 */ 429 public final class Wakelock extends BatteryStats.Uid.Wakelock { 430 /** 431 * How long (in ms) this uid has been keeping the device partially awake. 432 */ 433 Timer wakeTimePartial; 434 435 /** 436 * How long (in ms) this uid has been keeping the device fully awake. 437 */ 438 Timer wakeTimeFull; 439 440 /** 441 * How long (in ms) this uid has had a window keeping the device awake. 442 */ 443 Timer wakeTimeWindow; 444 445 /** 446 * Reads a possibly null Timer from a Parcel. The timer is associated with the 447 * proper timer pool from the given BatteryStatsImpl object. 448 * 449 * @param in the Parcel to be read from. 450 * return a new Timer, or null. 451 */ 452 private Timer readTimerFromParcel(Parcel in) { 453 if (in.readInt() == 0) { 454 return null; 455 } 456 457 Timer timer = new Timer(); 458 timer.readFromParcel(in); 459 // Set the timer pool for the timer according to its type 460 switch (timer.mType) { 461 case WAKE_TYPE_PARTIAL: 462 timer.mTimerPool = mPartialTimers; 463 break; 464 case WAKE_TYPE_FULL: 465 timer.mTimerPool = mFullTimers; 466 break; 467 case WAKE_TYPE_WINDOW: 468 timer.mTimerPool = mWindowTimers; 469 break; 470 } 471 // If the timer is active, add it to the pool 472 if (timer.mNesting > 0) { 473 timer.mTimerPool.add(timer); 474 } 475 return timer; 476 } 477 478 void readFromParcelLocked(Parcel in) { 479 wakeTimePartial = readTimerFromParcel(in); 480 wakeTimeFull = readTimerFromParcel(in); 481 wakeTimeWindow = readTimerFromParcel(in); 482 } 483 484 void writeToParcelLocked(Parcel out) { 485 Timer.writeTimerToParcel(out, wakeTimePartial); 486 Timer.writeTimerToParcel(out, wakeTimeFull); 487 Timer.writeTimerToParcel(out, wakeTimeWindow); 488 } 489 490 @Override 491 public Timer getWakeTime(int type) { 492 switch (type) { 493 case WAKE_TYPE_FULL: return wakeTimeFull; 494 case WAKE_TYPE_PARTIAL: return wakeTimePartial; 495 case WAKE_TYPE_WINDOW: return wakeTimeWindow; 496 default: throw new IllegalArgumentException("type = " + type); 497 } 498 } 499 } 500 501 public final class Sensor extends BatteryStats.Uid.Sensor { 502 Timer sensorTime; 503 504 private Timer readTimerFromParcel(Parcel in) { 505 if (in.readInt() == 0) { 506 return null; 507 } 508 509 Timer timer = new Timer(); 510 timer.readFromParcel(in); 511 // Set the timer pool for the timer 512 timer.mTimerPool = mSensorTimers; 513 514 // If the timer is active, add it to the pool 515 if (timer.mNesting > 0) { 516 timer.mTimerPool.add(timer); 517 } 518 return timer; 519 } 520 521 void readFromParcelLocked(Parcel in) { 522 sensorTime = readTimerFromParcel(in); 523 } 524 525 void writeToParcelLocked(Parcel out) { 526 Timer.writeTimerToParcel(out, sensorTime); 527 } 528 529 @Override 530 public Timer getSensorTime() { 531 return sensorTime; 532 } 533 } 534 535 /** 536 * The statistics associated with a particular process. 537 */ 538 public final class Proc extends BatteryStats.Uid.Proc { 539 /** 540 * Total time (in 1/100 sec) spent executing in user code. 541 */ 542 long mUserTime; 543 544 /** 545 * Total time (in 1/100 sec) spent executing in kernel code. 546 */ 547 long mSystemTime; 548 549 /** 550 * Number of times the process has been started. 551 */ 552 int mStarts; 553 554 /** 555 * The amount of user time loaded from a previous save. 556 */ 557 long mLoadedUserTime; 558 559 /** 560 * The amount of system time loaded from a previous save. 561 */ 562 long mLoadedSystemTime; 563 564 /** 565 * The number of times the process has started from a previous save. 566 */ 567 int mLoadedStarts; 568 569 /** 570 * The amount of user time loaded from the previous run. 571 */ 572 long mLastUserTime; 573 574 /** 575 * The amount of system time loaded from the previous run. 576 */ 577 long mLastSystemTime; 578 579 /** 580 * The number of times the process has started from the previous run. 581 */ 582 int mLastStarts; 583 584 void writeToParcelLocked(Parcel out) { 585 out.writeLong(mUserTime); 586 out.writeLong(mSystemTime); 587 out.writeInt(mStarts); 588 out.writeLong(mLoadedUserTime); 589 out.writeLong(mLoadedSystemTime); 590 out.writeInt(mLoadedStarts); 591 out.writeLong(mLastUserTime); 592 out.writeLong(mLastSystemTime); 593 out.writeInt(mLastStarts); 594 } 595 596 void readFromParcelLocked(Parcel in) { 597 mUserTime = in.readLong(); 598 mSystemTime = in.readLong(); 599 mStarts = in.readInt(); 600 mLoadedUserTime = in.readLong(); 601 mLoadedSystemTime = in.readLong(); 602 mLoadedStarts = in.readInt(); 603 mLastUserTime = in.readLong(); 604 mLastSystemTime = in.readLong(); 605 mLastStarts = in.readInt(); 606 } 607 608 public BatteryStatsImpl getBatteryStats() { 609 return BatteryStatsImpl.this; 610 } 611 612 public void addCpuTimeLocked(int utime, int stime) { 613 mUserTime += utime; 614 mSystemTime += stime; 615 } 616 617 public void incStartsLocked() { 618 mStarts++; 619 } 620 621 @Override 622 public long getUserTime(int which) { 623 long val; 624 if (which == STATS_LAST) { 625 val = mLastUserTime; 626 } else { 627 val = mUserTime; 628 if (which == STATS_CURRENT) { 629 val -= mLoadedUserTime; 630 } 631 } 632 return val; 633 } 634 635 @Override 636 public long getSystemTime(int which) { 637 long val; 638 if (which == STATS_LAST) { 639 val = mLastSystemTime; 640 } else { 641 val = mSystemTime; 642 if (which == STATS_CURRENT) { 643 val -= mLoadedSystemTime; 644 } 645 } 646 return val; 647 } 648 649 @Override 650 public int getStarts(int which) { 651 int val; 652 if (which == STATS_LAST) { 653 val = mLastStarts; 654 } else { 655 val = mStarts; 656 if (which == STATS_CURRENT) { 657 val -= mLoadedStarts; 658 } 659 } 660 return val; 661 } 662 } 663 664 /** 665 * The statistics associated with a particular package. 666 */ 667 public final class Pkg extends BatteryStats.Uid.Pkg { 668 /** 669 * Number of times this package has done something that could wake up the 670 * device from sleep. 671 */ 672 int mWakeups; 673 674 /** 675 * Number of things that could wake up the device loaded from a 676 * previous save. 677 */ 678 int mLoadedWakeups; 679 680 /** 681 * Number of things that could wake up the device as of the 682 * last run. 683 */ 684 int mLastWakeups; 685 686 /** 687 * The statics we have collected for this package's services. 688 */ 689 final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>(); 690 691 void readFromParcelLocked(Parcel in) { 692 mWakeups = in.readInt(); 693 mLoadedWakeups = in.readInt(); 694 mLastWakeups = in.readInt(); 695 696 int numServs = in.readInt(); 697 mServiceStats.clear(); 698 for (int m = 0; m < numServs; m++) { 699 String serviceName = in.readString(); 700 Uid.Pkg.Serv serv = new Serv(); 701 mServiceStats.put(serviceName, serv); 702 703 serv.readFromParcelLocked(in); 704 } 705 } 706 707 void writeToParcelLocked(Parcel out) { 708 out.writeInt(mWakeups); 709 out.writeInt(mLoadedWakeups); 710 out.writeInt(mLastWakeups); 711 712 out.writeInt(mServiceStats.size()); 713 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) { 714 out.writeString(servEntry.getKey()); 715 Uid.Pkg.Serv serv = servEntry.getValue(); 716 717 serv.writeToParcelLocked(out); 718 } 719 } 720 721 @Override 722 public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() { 723 return mServiceStats; 724 } 725 726 @Override 727 public int getWakeups(int which) { 728 int val; 729 if (which == STATS_LAST) { 730 val = mLastWakeups; 731 } else { 732 val = mWakeups; 733 if (which == STATS_CURRENT) { 734 val -= mLoadedWakeups; 735 } 736 } 737 738 return val; 739 } 740 741 /** 742 * The statistics associated with a particular service. 743 */ 744 public final class Serv extends BatteryStats.Uid.Pkg.Serv { 745 /** 746 * Total time (ms) the service has been left started. 747 */ 748 long mStartTime; 749 750 /** 751 * If service has been started and not yet stopped, this is 752 * when it was started. 753 */ 754 long mRunningSince; 755 756 /** 757 * True if we are currently running. 758 */ 759 boolean mRunning; 760 761 /** 762 * Total number of times startService() has been called. 763 */ 764 int mStarts; 765 766 /** 767 * Total time (ms) the service has been left launched. 768 */ 769 long mLaunchedTime; 770 771 /** 772 * If service has been launched and not yet exited, this is 773 * when it was launched. 774 */ 775 long mLaunchedSince; 776 777 /** 778 * True if we are currently launched. 779 */ 780 boolean mLaunched; 781 782 /** 783 * Total number times the service has been launched. 784 */ 785 int mLaunches; 786 787 /** 788 * The amount of time spent started loaded from a previous save. 789 */ 790 long mLoadedStartTime; 791 792 /** 793 * The number of starts loaded from a previous save. 794 */ 795 int mLoadedStarts; 796 797 /** 798 * The number of launches loaded from a previous save. 799 */ 800 int mLoadedLaunches; 801 802 /** 803 * The amount of time spent started as of the last run. 804 */ 805 long mLastStartTime; 806 807 /** 808 * The number of starts as of the last run. 809 */ 810 int mLastStarts; 811 812 /** 813 * The number of launches as of the last run. 814 */ 815 int mLastLaunches; 816 817 void readFromParcelLocked(Parcel in) { 818 mStartTime = in.readLong(); 819 mRunningSince = in.readLong(); 820 mRunning = in.readInt() != 0; 821 mStarts = in.readInt(); 822 mLaunchedTime = in.readLong(); 823 mLaunchedSince = in.readLong(); 824 mLaunched = in.readInt() != 0; 825 mLaunches = in.readInt(); 826 mLoadedStartTime = in.readLong(); 827 mLoadedStarts = in.readInt(); 828 mLoadedLaunches = in.readInt(); 829 mLastStartTime = in.readLong(); 830 mLastStarts = in.readInt(); 831 mLastLaunches = in.readInt(); 832 } 833 834 void writeToParcelLocked(Parcel out) { 835 out.writeLong(mStartTime); 836 out.writeLong(mRunningSince); 837 out.writeInt(mRunning ? 1 : 0); 838 out.writeInt(mStarts); 839 out.writeLong(mLaunchedTime); 840 out.writeLong(mLaunchedSince); 841 out.writeInt(mLaunched ? 1 : 0); 842 out.writeInt(mLaunches); 843 out.writeLong(mLoadedStartTime); 844 out.writeInt(mLoadedStarts); 845 out.writeInt(mLoadedLaunches); 846 out.writeLong(mLastStartTime); 847 out.writeInt(mLastStarts); 848 out.writeInt(mLastLaunches); 849 } 850 851 long getLaunchTimeToNowLocked(long batteryUptime) { 852 if (!mLaunched) return mLaunchedTime; 853 return mLaunchedTime + batteryUptime - mLaunchedSince; 854 } 855 856 long getStartTimeToNowLocked(long batteryUptime) { 857 if (!mRunning) return mStartTime; 858 return mStartTime + batteryUptime - mRunningSince; 859 } 860 861 public void startLaunchedLocked() { 862 if (!mLaunched) { 863 mLaunches++; 864 mLaunchedSince = getBatteryUptimeLocked(); 865 mLaunched = true; 866 } 867 } 868 869 public void stopLaunchedLocked() { 870 if (mLaunched) { 871 long time = getBatteryUptimeLocked() - mLaunchedSince; 872 if (time > 0) { 873 mLaunchedTime += time; 874 } else { 875 mLaunches--; 876 } 877 mLaunched = false; 878 } 879 } 880 881 public void startRunningLocked() { 882 if (!mRunning) { 883 mStarts++; 884 mRunningSince = getBatteryUptimeLocked(); 885 mRunning = true; 886 } 887 } 888 889 public void stopRunningLocked() { 890 if (mRunning) { 891 long time = getBatteryUptimeLocked() - mRunningSince; 892 if (time > 0) { 893 mStartTime += time; 894 } else { 895 mStarts--; 896 } 897 mRunning = false; 898 } 899 } 900 901 public BatteryStatsImpl getBatteryStats() { 902 return BatteryStatsImpl.this; 903 } 904 905 @Override 906 public int getLaunches(int which) { 907 int val; 908 909 if (which == STATS_LAST) { 910 val = mLastLaunches; 911 } else { 912 val = mLaunches; 913 if (which == STATS_CURRENT) { 914 val -= mLoadedLaunches; 915 } 916 } 917 918 return val; 919 } 920 921 @Override 922 public long getStartTime(long now, int which) { 923 long val; 924 if (which == STATS_LAST) { 925 val = mLastStartTime; 926 } else { 927 val = getStartTimeToNowLocked(now); 928 if (which == STATS_CURRENT) { 929 val -= mLoadedStartTime; 930 } 931 } 932 933 return val; 934 } 935 936 @Override 937 public int getStarts(int which) { 938 int val; 939 if (which == STATS_LAST) { 940 val = mLastStarts; 941 } else { 942 val = mStarts; 943 if (which == STATS_CURRENT) { 944 val -= mLoadedStarts; 945 } 946 } 947 948 return val; 949 } 950 } 951 952 public BatteryStatsImpl getBatteryStats() { 953 return BatteryStatsImpl.this; 954 } 955 956 public void incWakeupsLocked() { 957 mWakeups++; 958 } 959 960 final Serv newServiceStatsLocked() { 961 return new Serv(); 962 } 963 } 964 965 /** 966 * Retrieve the statistics object for a particular process, creating 967 * if needed. 968 */ 969 public Proc getProcessStatsLocked(String name) { 970 Proc ps = mProcessStats.get(name); 971 if (ps == null) { 972 ps = new Proc(); 973 mProcessStats.put(name, ps); 974 } 975 976 return ps; 977 } 978 979 /** 980 * Retrieve the statistics object for a particular service, creating 981 * if needed. 982 */ 983 public Pkg getPackageStatsLocked(String name) { 984 Pkg ps = mPackageStats.get(name); 985 if (ps == null) { 986 ps = new Pkg(); 987 mPackageStats.put(name, ps); 988 } 989 990 return ps; 991 } 992 993 /** 994 * Retrieve the statistics object for a particular service, creating 995 * if needed. 996 */ 997 public Pkg.Serv getServiceStatsLocked(String pkg, String serv) { 998 Pkg ps = getPackageStatsLocked(pkg); 999 Pkg.Serv ss = ps.mServiceStats.get(serv); 1000 if (ss == null) { 1001 ss = ps.newServiceStatsLocked(); 1002 ps.mServiceStats.put(serv, ss); 1003 } 1004 1005 return ss; 1006 } 1007 1008 public Timer getWakeTimerLocked(String name, int type) { 1009 Wakelock wl = mWakelockStats.get(name); 1010 if (wl == null) { 1011 wl = new Wakelock(); 1012 mWakelockStats.put(name, wl); 1013 } 1014 Timer t = null; 1015 switch (type) { 1016 case WAKE_TYPE_PARTIAL: 1017 t = wl.wakeTimePartial; 1018 if (t == null) { 1019 t = new Timer(WAKE_TYPE_PARTIAL, mPartialTimers); 1020 wl.wakeTimePartial = t; 1021 } 1022 return t; 1023 case WAKE_TYPE_FULL: 1024 t = wl.wakeTimeFull; 1025 if (t == null) { 1026 t = new Timer(WAKE_TYPE_FULL, mFullTimers); 1027 wl.wakeTimeFull = t; 1028 } 1029 return t; 1030 case WAKE_TYPE_WINDOW: 1031 t = wl.wakeTimeWindow; 1032 if (t == null) { 1033 t = new Timer(WAKE_TYPE_WINDOW, mWindowTimers); 1034 wl.wakeTimeWindow = t; 1035 } 1036 return t; 1037 default: 1038 throw new IllegalArgumentException("type=" + type); 1039 } 1040 } 1041 1042 public Timer getSensorTimerLocked(int sensor, boolean create) { 1043 Integer sId = Integer.valueOf(sensor); 1044 Sensor se = mSensorStats.get(sId); 1045 if (se == null) { 1046 if (!create) { 1047 return null; 1048 } 1049 se = new Sensor(); 1050 mSensorStats.put(sId, se); 1051 } 1052 Timer t = se.sensorTime; 1053 if (t == null) { 1054 t = new Timer(0, mSensorTimers); 1055 se.sensorTime = t; 1056 } 1057 return t; 1058 } 1059 1060 public void noteStartWakeLocked(String name, int type) { 1061 Timer t = getWakeTimerLocked(name, type); 1062 if (t != null) { 1063 t.startRunningLocked(BatteryStatsImpl.this); 1064 } 1065 } 1066 1067 public void noteStopWakeLocked(String name, int type) { 1068 Timer t = getWakeTimerLocked(name, type); 1069 if (t != null) { 1070 t.stopRunningLocked(BatteryStatsImpl.this); 1071 } 1072 } 1073 1074 public void noteStartSensor(int sensor) { 1075 Timer t = getSensorTimerLocked(sensor, true); 1076 if (t != null) { 1077 t.startRunningLocked(BatteryStatsImpl.this); 1078 } 1079 } 1080 1081 public void noteStopSensor(int sensor) { 1082 // Don't create a timer if one doesn't already exist 1083 Timer t = getSensorTimerLocked(sensor, false); 1084 if (t != null) { 1085 t.stopRunningLocked(BatteryStatsImpl.this); 1086 } 1087 } 1088 1089 public BatteryStatsImpl getBatteryStats() { 1090 return BatteryStatsImpl.this; 1091 } 1092 } 1093 1094 public BatteryStatsImpl(String filename) { 1095 mFile = new File(filename); 1096 mBackupFile = new File(filename + ".bak"); 1097 mStartCount++; 1098 mOnBattery = true; 1099 mTrackBatteryPastUptime = 0; 1100 mTrackBatteryPastRealtime = 0; 1101 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; 1102 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; 1103 } 1104 1105 public BatteryStatsImpl(Parcel p) { 1106 mFile = mBackupFile = null; 1107 readFromParcel(p); 1108 } 1109 1110 @Override 1111 public int getStartCount() { 1112 return mStartCount; 1113 } 1114 1115 public boolean isOnBattery() { 1116 return mOnBattery; 1117 } 1118 1119 public void setOnBattery(boolean onBattery) { 1120 synchronized(this) { 1121 if (mOnBattery != onBattery) { 1122 long uptime = SystemClock.uptimeMillis() * 1000; 1123 long mSecRealtime = SystemClock.elapsedRealtime(); 1124 long realtime = mSecRealtime * 1000; 1125 if (onBattery) { 1126 mTrackBatteryUptimeStart = uptime; 1127 mTrackBatteryRealtimeStart = realtime; 1128 unplugTimers(); 1129 } else { 1130 mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; 1131 mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; 1132 } 1133 mOnBattery = onBattery; 1134 if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) { 1135 if (mFile != null) { 1136 writeLocked(); 1137 } 1138 } 1139 } 1140 } 1141 } 1142 1143 public long getAwakeTimeBattery() { 1144 return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT); 1145 } 1146 1147 public long getAwakeTimePlugged() { 1148 return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery(); 1149 } 1150 1151 @Override 1152 public long computeUptime(long curTime, int which) { 1153 switch (which) { 1154 case STATS_TOTAL: return mUptime + (curTime-mUptimeStart); 1155 case STATS_LAST: return mLastUptime; 1156 case STATS_CURRENT: return (curTime-mUptimeStart); 1157 case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart); 1158 } 1159 return 0; 1160 } 1161 1162 @Override 1163 public long computeRealtime(long curTime, int which) { 1164 switch (which) { 1165 case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart); 1166 case STATS_LAST: return mLastRealtime; 1167 case STATS_CURRENT: return (curTime-mRealtimeStart); 1168 case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart); 1169 } 1170 return 0; 1171 } 1172 1173 @Override 1174 public long computeBatteryUptime(long curTime, int which) { 1175 switch (which) { 1176 case STATS_TOTAL: 1177 return mBatteryUptime + getBatteryUptime(curTime); 1178 case STATS_LAST: 1179 return mBatteryLastUptime; 1180 case STATS_CURRENT: 1181 case STATS_UNPLUGGED: 1182 return getBatteryUptime(curTime); 1183 } 1184 return 0; 1185 } 1186 1187 @Override 1188 public long computeBatteryRealtime(long curTime, int which) { 1189 switch (which) { 1190 case STATS_TOTAL: 1191 return mBatteryRealtime + getBatteryRealtimeLocked(curTime); 1192 case STATS_LAST: 1193 return mBatteryLastRealtime; 1194 case STATS_CURRENT: 1195 case STATS_UNPLUGGED: 1196 return getBatteryRealtimeLocked(curTime); 1197 } 1198 return 0; 1199 } 1200 1201 long getBatteryUptimeLocked(long curTime) { 1202 long time = mTrackBatteryPastUptime; 1203 if (mOnBattery) { 1204 time += curTime - mTrackBatteryUptimeStart; 1205 } 1206 return time; 1207 } 1208 1209 long getBatteryUptimeLocked() { 1210 return getBatteryUptime(SystemClock.uptimeMillis() * 1000); 1211 } 1212 1213 @Override 1214 public long getBatteryUptime(long curTime) { 1215 return getBatteryUptimeLocked(curTime); 1216 } 1217 1218 long getBatteryRealtimeLocked(long curTime) { 1219 long time = mTrackBatteryPastRealtime; 1220 if (mOnBattery) { 1221 time += curTime - mTrackBatteryRealtimeStart; 1222 } 1223 return time; 1224 } 1225 1226 @Override 1227 public long getBatteryRealtime(long curTime) { 1228 return getBatteryRealtimeLocked(curTime); 1229 } 1230 1231 /** 1232 * Retrieve the statistics object for a particular uid, creating if needed. 1233 */ 1234 public Uid getUidStatsLocked(int uid) { 1235 Uid u = mUidStats.get(uid); 1236 if (u == null) { 1237 u = new Uid(); 1238 mUidStats.put(uid, u); 1239 } 1240 return u; 1241 } 1242 1243 /** 1244 * Remove the statistics object for a particular uid. 1245 */ 1246 public void removeUidStatsLocked(int uid) { 1247 mUidStats.remove(uid); 1248 } 1249 1250 /** 1251 * Retrieve the statistics object for a particular process, creating 1252 * if needed. 1253 */ 1254 public Uid.Proc getProcessStatsLocked(int uid, String name) { 1255 Uid u = getUidStatsLocked(uid); 1256 return u.getProcessStatsLocked(name); 1257 } 1258 1259 /** 1260 * Retrieve the statistics object for a particular process, creating 1261 * if needed. 1262 */ 1263 public Uid.Pkg getPackageStatsLocked(int uid, String pkg) { 1264 Uid u = getUidStatsLocked(uid); 1265 return u.getPackageStatsLocked(pkg); 1266 } 1267 1268 /** 1269 * Retrieve the statistics object for a particular service, creating 1270 * if needed. 1271 */ 1272 public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) { 1273 Uid u = getUidStatsLocked(uid); 1274 return u.getServiceStatsLocked(pkg, name); 1275 } 1276 1277 public void writeLocked() { 1278 if ((mFile == null) || (mBackupFile == null)) { 1279 Log.w("BatteryStats", "writeLocked: no file associated with this instance"); 1280 return; 1281 } 1282 1283 // Keep the old file around until we know the new one has 1284 // been successfully written. 1285 if (mFile.exists()) { 1286 if (mBackupFile.exists()) { 1287 mBackupFile.delete(); 1288 } 1289 mFile.renameTo(mBackupFile); 1290 } 1291 1292 try { 1293 FileOutputStream stream = new FileOutputStream(mFile); 1294 Parcel out = Parcel.obtain(); 1295 writeSummaryToParcel(out); 1296 stream.write(out.marshall()); 1297 out.recycle(); 1298 1299 stream.flush(); 1300 stream.close(); 1301 mBackupFile.delete(); 1302 1303 mLastWriteTime = SystemClock.elapsedRealtime(); 1304 } catch (IOException e) { 1305 Log.e("BatteryStats", "Error writing battery statistics", e); 1306 } 1307 } 1308 1309 static byte[] readFully(FileInputStream stream) throws java.io.IOException { 1310 int pos = 0; 1311 int avail = stream.available(); 1312 byte[] data = new byte[avail]; 1313 while (true) { 1314 int amt = stream.read(data, pos, data.length-pos); 1315 //Log.i("foo", "Read " + amt + " bytes at " + pos 1316 // + " of avail " + data.length); 1317 if (amt <= 0) { 1318 //Log.i("foo", "**** FINISHED READING: pos=" + pos 1319 // + " len=" + data.length); 1320 return data; 1321 } 1322 pos += amt; 1323 avail = stream.available(); 1324 if (avail > data.length-pos) { 1325 byte[] newData = new byte[pos+avail]; 1326 System.arraycopy(data, 0, newData, 0, pos); 1327 data = newData; 1328 } 1329 } 1330 } 1331 1332 public void readLocked() { 1333 if ((mFile == null) || (mBackupFile == null)) { 1334 Log.w("BatteryStats", "readLocked: no file associated with this instance"); 1335 return; 1336 } 1337 1338 mUidStats.clear(); 1339 1340 FileInputStream stream = null; 1341 if (mBackupFile.exists()) { 1342 try { 1343 stream = new FileInputStream(mBackupFile); 1344 } catch (java.io.IOException e) { 1345 // We'll try for the normal settings file. 1346 } 1347 } 1348 1349 try { 1350 if (stream == null) { 1351 if (!mFile.exists()) { 1352 return; 1353 } 1354 stream = new FileInputStream(mFile); 1355 } 1356 1357 byte[] raw = readFully(stream); 1358 Parcel in = Parcel.obtain(); 1359 in.unmarshall(raw, 0, raw.length); 1360 in.setDataPosition(0); 1361 stream.close(); 1362 1363 readSummaryFromParcel(in); 1364 } catch(java.io.IOException e) { 1365 Log.e("BatteryStats", "Error reading battery statistics", e); 1366 } 1367 } 1368 1369 public int describeContents() { 1370 return 0; 1371 } 1372 1373 private void readSummaryFromParcel(Parcel in) { 1374 final int version = in.readInt(); 1375 if (version != VERSION) { 1376 Log.e("BatteryStats", "readFromParcel: version got " + version 1377 + ", expected " + VERSION); 1378 return; 1379 } 1380 1381 mStartCount = in.readInt(); 1382 mBatteryUptime = in.readLong(); 1383 mBatteryLastUptime = in.readLong(); 1384 mBatteryRealtime = in.readLong(); 1385 mBatteryLastRealtime = in.readLong(); 1386 mUptime = in.readLong(); 1387 mLastUptime = in.readLong(); 1388 mRealtime = in.readLong(); 1389 mLastRealtime = in.readLong(); 1390 mStartCount++; 1391 1392 final int NU = in.readInt(); 1393 for (int iu=0; iu<NU; iu++) { 1394 int uid = in.readInt(); 1395 Uid u = new Uid(); 1396 mUidStats.put(uid, u); 1397 1398 int NW = in.readInt(); 1399 for (int iw=0; iw<NW; iw++) { 1400 String wlName = in.readString(); 1401 if (in.readInt() != 0) { 1402 u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in); 1403 } 1404 if (in.readInt() != 0) { 1405 u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in); 1406 } 1407 if (in.readInt() != 0) { 1408 u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in); 1409 } 1410 } 1411 1412 if (version >= 12) { 1413 int NSE = in.readInt(); 1414 for (int is=0; is<NSE; is++) { 1415 int seNumber = in.readInt(); 1416 if (in.readInt() != 0) { 1417 u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in); 1418 } 1419 } 1420 } 1421 1422 int NP = in.readInt(); 1423 for (int ip=0; ip<NP; ip++) { 1424 String procName = in.readString(); 1425 Uid.Proc p = u.getProcessStatsLocked(procName); 1426 p.mUserTime = p.mLoadedUserTime = in.readLong(); 1427 p.mLastUserTime = in.readLong(); 1428 p.mSystemTime = p.mLoadedSystemTime = in.readLong(); 1429 p.mLastSystemTime = in.readLong(); 1430 p.mStarts = p.mLoadedStarts = in.readInt(); 1431 p.mLastStarts = in.readInt(); 1432 } 1433 1434 NP = in.readInt(); 1435 for (int ip=0; ip<NP; ip++) { 1436 String pkgName = in.readString(); 1437 Uid.Pkg p = u.getPackageStatsLocked(pkgName); 1438 p.mWakeups = p.mLoadedWakeups = in.readInt(); 1439 p.mLastWakeups = in.readInt(); 1440 final int NS = in.readInt(); 1441 for (int is=0; is<NS; is++) { 1442 String servName = in.readString(); 1443 Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName); 1444 s.mStartTime = s.mLoadedStartTime = in.readLong(); 1445 s.mLastStartTime = in.readLong(); 1446 s.mStarts = s.mLoadedStarts = in.readInt(); 1447 s.mLastStarts = in.readInt(); 1448 s.mLaunches = s.mLoadedLaunches = in.readInt(); 1449 s.mLastLaunches = in.readInt(); 1450 } 1451 } 1452 } 1453 } 1454 1455 /** 1456 * Writes a summary of the statistics to a Parcel, in a format suitable to be written to 1457 * disk. This format does not allow a lossless round-trip. 1458 * 1459 * @param out the Parcel to be written to. 1460 */ 1461 public void writeSummaryToParcel(Parcel out) { 1462 final long NOW = getBatteryUptimeLocked(); 1463 final long NOW_SYS = SystemClock.uptimeMillis() * 1000; 1464 final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; 1465 1466 out.writeInt(VERSION); 1467 1468 out.writeInt(mStartCount); 1469 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_TOTAL)); 1470 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT)); 1471 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_TOTAL)); 1472 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT)); 1473 out.writeLong(computeUptime(NOW_SYS, STATS_TOTAL)); 1474 out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT)); 1475 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL)); 1476 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT)); 1477 1478 final int NU = mUidStats.size(); 1479 out.writeInt(NU); 1480 for (int iu=0; iu<NU; iu++) { 1481 out.writeInt(mUidStats.keyAt(iu)); 1482 Uid u = mUidStats.valueAt(iu); 1483 1484 int NW = u.mWakelockStats.size(); 1485 out.writeInt(NW); 1486 if (NW > 0) { 1487 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent 1488 : u.mWakelockStats.entrySet()) { 1489 out.writeString(ent.getKey()); 1490 Uid.Wakelock wl = ent.getValue(); 1491 if (wl.wakeTimeFull != null) { 1492 out.writeInt(1); 1493 wl.wakeTimeFull.writeSummaryFromParcelLocked(out, NOW); 1494 } else { 1495 out.writeInt(0); 1496 } 1497 if (wl.wakeTimePartial != null) { 1498 out.writeInt(1); 1499 wl.wakeTimePartial.writeSummaryFromParcelLocked(out, NOW); 1500 } else { 1501 out.writeInt(0); 1502 } 1503 if (wl.wakeTimeWindow != null) { 1504 out.writeInt(1); 1505 wl.wakeTimeWindow.writeSummaryFromParcelLocked(out, NOW); 1506 } else { 1507 out.writeInt(0); 1508 } 1509 } 1510 } 1511 1512 int NSE = u.mSensorStats.size(); 1513 out.writeInt(NSE); 1514 if (NSE > 0) { 1515 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent 1516 : u.mSensorStats.entrySet()) { 1517 out.writeInt(ent.getKey()); 1518 Uid.Sensor se = ent.getValue(); 1519 if (se.sensorTime != null) { 1520 out.writeInt(1); 1521 se.sensorTime.writeSummaryFromParcelLocked(out, NOW); 1522 } else { 1523 out.writeInt(0); 1524 } 1525 } 1526 } 1527 1528 int NP = u.mProcessStats.size(); 1529 out.writeInt(NP); 1530 if (NP > 0) { 1531 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent 1532 : u.mProcessStats.entrySet()) { 1533 out.writeString(ent.getKey()); 1534 Uid.Proc ps = ent.getValue(); 1535 out.writeLong(ps.mUserTime); 1536 out.writeLong(ps.mUserTime - ps.mLoadedUserTime); 1537 out.writeLong(ps.mSystemTime); 1538 out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime); 1539 out.writeInt(ps.mStarts); 1540 out.writeInt(ps.mStarts - ps.mLoadedStarts); 1541 } 1542 } 1543 1544 NP = u.mPackageStats.size(); 1545 out.writeInt(NP); 1546 if (NP > 0) { 1547 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent 1548 : u.mPackageStats.entrySet()) { 1549 out.writeString(ent.getKey()); 1550 Uid.Pkg ps = ent.getValue(); 1551 out.writeInt(ps.mWakeups); 1552 out.writeInt(ps.mWakeups - ps.mLoadedWakeups); 1553 final int NS = ps.mServiceStats.size(); 1554 out.writeInt(NS); 1555 if (NS > 0) { 1556 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent 1557 : ps.mServiceStats.entrySet()) { 1558 out.writeString(sent.getKey()); 1559 BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue(); 1560 long time = ss.getStartTimeToNowLocked(NOW); 1561 out.writeLong(time); 1562 out.writeLong(time - ss.mLoadedStartTime); 1563 out.writeInt(ss.mStarts); 1564 out.writeInt(ss.mStarts - ss.mLoadedStarts); 1565 out.writeInt(ss.mLaunches); 1566 out.writeInt(ss.mLaunches - ss.mLoadedLaunches); 1567 } 1568 } 1569 } 1570 } 1571 } 1572 } 1573 1574 public void readFromParcel(Parcel in) { 1575 readFromParcelLocked(in); 1576 } 1577 1578 void readFromParcelLocked(Parcel in) { 1579 int magic = in.readInt(); 1580 if (magic != MAGIC) { 1581 throw new ParcelFormatException("Bad magic number"); 1582 } 1583 1584 mStartCount = in.readInt(); 1585 mBatteryUptime = in.readLong(); 1586 mBatteryLastUptime = in.readLong(); 1587 mBatteryRealtime = in.readLong(); 1588 mBatteryLastRealtime = in.readLong(); 1589 mUptime = in.readLong(); 1590 mUptimeStart = in.readLong(); 1591 mLastUptime = in.readLong(); 1592 mRealtime = in.readLong(); 1593 mRealtimeStart = in.readLong(); 1594 mLastRealtime = in.readLong(); 1595 mOnBattery = in.readInt() != 0; 1596 mTrackBatteryPastUptime = in.readLong(); 1597 mTrackBatteryUptimeStart = in.readLong(); 1598 mTrackBatteryPastRealtime = in.readLong(); 1599 mTrackBatteryRealtimeStart = in.readLong(); 1600 mLastWriteTime = in.readLong(); 1601 1602 mPartialTimers.clear(); 1603 mFullTimers.clear(); 1604 mWindowTimers.clear(); 1605 1606 int numUids = in.readInt(); 1607 mUidStats.clear(); 1608 for (int i = 0; i < numUids; i++) { 1609 int key = in.readInt(); 1610 Uid uid = new Uid(); 1611 uid.readFromParcelLocked(in); 1612 mUidStats.append(key, uid); 1613 } 1614 } 1615 1616 public void writeToParcel(Parcel out, int flags) { 1617 writeToParcelLocked(out, flags); 1618 } 1619 1620 @SuppressWarnings("unused") 1621 void writeToParcelLocked(Parcel out, int flags) { 1622 out.writeInt(MAGIC); 1623 out.writeInt(mStartCount); 1624 out.writeLong(mBatteryUptime); 1625 out.writeLong(mBatteryLastUptime); 1626 out.writeLong(mBatteryRealtime); 1627 out.writeLong(mBatteryLastRealtime); 1628 out.writeLong(mUptime); 1629 out.writeLong(mUptimeStart); 1630 out.writeLong(mLastUptime); 1631 out.writeLong(mRealtime); 1632 out.writeLong(mRealtimeStart); 1633 out.writeLong(mLastRealtime); 1634 out.writeInt(mOnBattery ? 1 : 0); 1635 out.writeLong(mTrackBatteryPastUptime); 1636 out.writeLong(mTrackBatteryUptimeStart); 1637 out.writeLong(mTrackBatteryPastRealtime); 1638 out.writeLong(mTrackBatteryRealtimeStart); 1639 out.writeLong(mLastWriteTime); 1640 1641 int size = mUidStats.size(); 1642 out.writeInt(size); 1643 for (int i = 0; i < size; i++) { 1644 out.writeInt(mUidStats.keyAt(i)); 1645 Uid uid = mUidStats.valueAt(i); 1646 1647 uid.writeToParcelLocked(out); 1648 } 1649 } 1650 1651 public static final Parcelable.Creator<BatteryStatsImpl> CREATOR = 1652 new Parcelable.Creator<BatteryStatsImpl>() { 1653 public BatteryStatsImpl createFromParcel(Parcel in) { 1654 return new BatteryStatsImpl(in); 1655 } 1656 1657 public BatteryStatsImpl[] newArray(int size) { 1658 return new BatteryStatsImpl[size]; 1659 } 1660 }; 1661} 1662