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