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