BatteryStatsImpl.java revision 2098eadfba7aba5d667579222f0fac76d1235ff0
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 com.android.internal.util.JournaledFile; 20 21import android.bluetooth.BluetoothHeadset; 22import android.net.TrafficStats; 23import android.os.BatteryStats; 24import android.os.Parcel; 25import android.os.ParcelFormatException; 26import android.os.Parcelable; 27import android.os.Process; 28import android.os.SystemClock; 29import android.telephony.ServiceState; 30import android.telephony.SignalStrength; 31import android.telephony.TelephonyManager; 32import android.util.Log; 33import android.util.PrintWriterPrinter; 34import android.util.Printer; 35import android.util.Slog; 36import android.util.SparseArray; 37 38import java.io.BufferedReader; 39import java.io.File; 40import java.io.FileInputStream; 41import java.io.FileOutputStream; 42import java.io.FileReader; 43import java.io.IOException; 44import java.io.PrintWriter; 45import java.util.ArrayList; 46import java.util.HashMap; 47import java.util.Iterator; 48import java.util.Map; 49import java.util.concurrent.atomic.AtomicInteger; 50 51/** 52 * All information we are collecting about things that can happen that impact 53 * battery life. All times are represented in microseconds except where indicated 54 * otherwise. 55 */ 56public final class BatteryStatsImpl extends BatteryStats { 57 private static final String TAG = "BatteryStatsImpl"; 58 private static final boolean DEBUG = false; 59 60 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data 61 private static final int MAGIC = 0xBA757475; // 'BATSTATS' 62 63 // Current on-disk Parcel version 64 private static final int VERSION = 43; 65 66 // The maximum number of names wakelocks we will keep track of 67 // per uid; once the limit is reached, we batch the remaining wakelocks 68 // in to one common name. 69 private static final int MAX_WAKELOCKS_PER_UID = 20; 70 71 private static final String BATCHED_WAKELOCK_NAME = "*overflow*"; 72 73 private static int sNumSpeedSteps; 74 75 private final JournaledFile mFile; 76 77 /** 78 * The statistics we have collected organized by uids. 79 */ 80 final SparseArray<BatteryStatsImpl.Uid> mUidStats = 81 new SparseArray<BatteryStatsImpl.Uid>(); 82 83 // A set of pools of currently active timers. When a timer is queried, we will divide the 84 // elapsed time by the number of active timers to arrive at that timer's share of the time. 85 // In order to do this, we must refresh each timer whenever the number of active timers 86 // changes. 87 final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>(); 88 final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>(); 89 final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>(); 90 final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers 91 = new SparseArray<ArrayList<StopwatchTimer>>(); 92 93 // These are the objects that will want to do something when the device 94 // is unplugged from power. 95 final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>(); 96 97 int mStartCount; 98 99 long mBatteryUptime; 100 long mBatteryLastUptime; 101 long mBatteryRealtime; 102 long mBatteryLastRealtime; 103 104 long mUptime; 105 long mUptimeStart; 106 long mLastUptime; 107 long mRealtime; 108 long mRealtimeStart; 109 long mLastRealtime; 110 111 boolean mScreenOn; 112 StopwatchTimer mScreenOnTimer; 113 114 int mScreenBrightnessBin = -1; 115 final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS]; 116 117 Counter mInputEventCounter; 118 119 boolean mPhoneOn; 120 StopwatchTimer mPhoneOnTimer; 121 122 boolean mAudioOn; 123 StopwatchTimer mAudioOnTimer; 124 125 boolean mVideoOn; 126 StopwatchTimer mVideoOnTimer; 127 128 int mPhoneSignalStrengthBin = -1; 129 final StopwatchTimer[] mPhoneSignalStrengthsTimer = 130 new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS]; 131 132 StopwatchTimer mPhoneSignalScanningTimer; 133 134 int mPhoneDataConnectionType = -1; 135 final StopwatchTimer[] mPhoneDataConnectionsTimer = 136 new StopwatchTimer[NUM_DATA_CONNECTION_TYPES]; 137 138 boolean mWifiOn; 139 StopwatchTimer mWifiOnTimer; 140 int mWifiOnUid = -1; 141 142 boolean mWifiRunning; 143 StopwatchTimer mWifiRunningTimer; 144 145 boolean mBluetoothOn; 146 StopwatchTimer mBluetoothOnTimer; 147 148 /** Bluetooth headset object */ 149 BluetoothHeadset mBtHeadset; 150 151 /** 152 * These provide time bases that discount the time the device is plugged 153 * in to power. 154 */ 155 boolean mOnBattery; 156 boolean mOnBatteryInternal; 157 long mTrackBatteryPastUptime; 158 long mTrackBatteryUptimeStart; 159 long mTrackBatteryPastRealtime; 160 long mTrackBatteryRealtimeStart; 161 162 long mUnpluggedBatteryUptime; 163 long mUnpluggedBatteryRealtime; 164 165 /* 166 * These keep track of battery levels (1-100) at the last plug event and the last unplug event. 167 */ 168 int mDischargeStartLevel; 169 int mDischargeCurrentLevel; 170 171 long mLastWriteTime = 0; // Milliseconds 172 173 // Mobile data transferred while on battery 174 private long[] mMobileDataTx = new long[4]; 175 private long[] mMobileDataRx = new long[4]; 176 private long[] mTotalDataTx = new long[4]; 177 private long[] mTotalDataRx = new long[4]; 178 179 private long mRadioDataUptime; 180 private long mRadioDataStart; 181 182 private int mBluetoothPingCount; 183 private int mBluetoothPingStart = -1; 184 185 private int mPhoneServiceState = -1; 186 187 /* 188 * Holds a SamplingTimer associated with each kernel wakelock name being tracked. 189 */ 190 private final HashMap<String, SamplingTimer> mKernelWakelockStats = 191 new HashMap<String, SamplingTimer>(); 192 193 public Map<String, ? extends SamplingTimer> getKernelWakelockStats() { 194 return mKernelWakelockStats; 195 } 196 197 private static int sKernelWakelockUpdateVersion = 0; 198 199 private static final int[] PROC_WAKELOCKS_FORMAT = new int[] { 200 Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name 201 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count 202 Process.PROC_TAB_TERM, 203 Process.PROC_TAB_TERM, 204 Process.PROC_TAB_TERM, 205 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime 206 }; 207 208 private final String[] mProcWakelocksName = new String[3]; 209 private final long[] mProcWakelocksData = new long[3]; 210 211 /* 212 * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added 213 * to mKernelWakelockStats. 214 */ 215 private final Map<String, KernelWakelockStats> mProcWakelockFileStats = 216 new HashMap<String, KernelWakelockStats>(); 217 218 private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>(); 219 220 // For debugging 221 public BatteryStatsImpl() { 222 mFile = null; 223 } 224 225 public static interface Unpluggable { 226 void unplug(long batteryUptime, long batteryRealtime); 227 void plug(long batteryUptime, long batteryRealtime); 228 } 229 230 /** 231 * State for keeping track of counting information. 232 */ 233 public static class Counter extends BatteryStats.Counter implements Unpluggable { 234 final AtomicInteger mCount = new AtomicInteger(); 235 int mLoadedCount; 236 int mLastCount; 237 int mUnpluggedCount; 238 int mPluggedCount; 239 240 Counter(ArrayList<Unpluggable> unpluggables, Parcel in) { 241 mPluggedCount = in.readInt(); 242 mCount.set(mPluggedCount); 243 mLoadedCount = in.readInt(); 244 mLastCount = in.readInt(); 245 mUnpluggedCount = in.readInt(); 246 unpluggables.add(this); 247 } 248 249 Counter(ArrayList<Unpluggable> unpluggables) { 250 unpluggables.add(this); 251 } 252 253 public void writeToParcel(Parcel out) { 254 out.writeInt(mCount.get()); 255 out.writeInt(mLoadedCount); 256 out.writeInt(mLastCount); 257 out.writeInt(mUnpluggedCount); 258 } 259 260 public void unplug(long batteryUptime, long batteryRealtime) { 261 mUnpluggedCount = mPluggedCount; 262 mCount.set(mPluggedCount); 263 } 264 265 public void plug(long batteryUptime, long batteryRealtime) { 266 mPluggedCount = mCount.get(); 267 } 268 269 /** 270 * Writes a possibly null Counter to a Parcel. 271 * 272 * @param out the Parcel to be written to. 273 * @param counter a Counter, or null. 274 */ 275 public static void writeCounterToParcel(Parcel out, Counter counter) { 276 if (counter == null) { 277 out.writeInt(0); // indicates null 278 return; 279 } 280 out.writeInt(1); // indicates non-null 281 282 counter.writeToParcel(out); 283 } 284 285 @Override 286 public int getCountLocked(int which) { 287 int val; 288 if (which == STATS_LAST) { 289 val = mLastCount; 290 } else { 291 val = mCount.get(); 292 if (which == STATS_UNPLUGGED) { 293 val -= mUnpluggedCount; 294 } else if (which != STATS_TOTAL) { 295 val -= mLoadedCount; 296 } 297 } 298 299 return val; 300 } 301 302 public void logState(Printer pw, String prefix) { 303 pw.println(prefix + "mCount=" + mCount.get() 304 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 305 + " mUnpluggedCount=" + mUnpluggedCount 306 + " mPluggedCount=" + mPluggedCount); 307 } 308 309 void stepAtomic() { 310 mCount.incrementAndGet(); 311 } 312 313 void writeSummaryFromParcelLocked(Parcel out) { 314 int count = mCount.get(); 315 out.writeInt(count); 316 out.writeInt(count - mLoadedCount); 317 } 318 319 void readSummaryFromParcelLocked(Parcel in) { 320 mLoadedCount = in.readInt(); 321 mCount.set(mLoadedCount); 322 mLastCount = in.readInt(); 323 mUnpluggedCount = mPluggedCount = mLoadedCount; 324 } 325 } 326 327 public static class SamplingCounter extends Counter { 328 329 SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) { 330 super(unpluggables, in); 331 } 332 333 SamplingCounter(ArrayList<Unpluggable> unpluggables) { 334 super(unpluggables); 335 } 336 337 public void addCountAtomic(long count) { 338 mCount.addAndGet((int)count); 339 } 340 } 341 342 /** 343 * State for keeping track of timing information. 344 */ 345 public static abstract class Timer extends BatteryStats.Timer implements Unpluggable { 346 final int mType; 347 348 349 int mCount; 350 int mLoadedCount; 351 int mLastCount; 352 int mUnpluggedCount; 353 354 // Times are in microseconds for better accuracy when dividing by the 355 // lock count, and are in "battery realtime" units. 356 357 /** 358 * The total time we have accumulated since the start of the original 359 * boot, to the last time something interesting happened in the 360 * current run. 361 */ 362 long mTotalTime; 363 364 /** 365 * The total time we loaded for the previous runs. Subtract this from 366 * mTotalTime to find the time for the current run of the system. 367 */ 368 long mLoadedTime; 369 370 /** 371 * The run time of the last run of the system, as loaded from the 372 * saved data. 373 */ 374 long mLastTime; 375 376 /** 377 * The value of mTotalTime when unplug() was last called. Subtract 378 * this from mTotalTime to find the time since the last unplug from 379 * power. 380 */ 381 long mUnpluggedTime; 382 383 /** 384 * Constructs from a parcel. 385 * @param type 386 * @param unpluggables 387 * @param powerType 388 * @param in 389 */ 390 Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) { 391 mType = type; 392 393 mCount = in.readInt(); 394 mLoadedCount = in.readInt(); 395 mLastCount = in.readInt(); 396 mUnpluggedCount = in.readInt(); 397 mTotalTime = in.readLong(); 398 mLoadedTime = in.readLong(); 399 mLastTime = in.readLong(); 400 mUnpluggedTime = in.readLong(); 401 unpluggables.add(this); 402 } 403 404 Timer(int type, ArrayList<Unpluggable> unpluggables) { 405 mType = type; 406 unpluggables.add(this); 407 } 408 409 protected abstract long computeRunTimeLocked(long curBatteryRealtime); 410 411 protected abstract int computeCurrentCountLocked(); 412 413 414 public void writeToParcel(Parcel out, long batteryRealtime) { 415 out.writeInt(mCount); 416 out.writeInt(mLoadedCount); 417 out.writeInt(mLastCount); 418 out.writeInt(mUnpluggedCount); 419 out.writeLong(computeRunTimeLocked(batteryRealtime)); 420 out.writeLong(mLoadedTime); 421 out.writeLong(mLastTime); 422 out.writeLong(mUnpluggedTime); 423 } 424 425 public void unplug(long batteryUptime, long batteryRealtime) { 426 if (DEBUG && mType < 0) { 427 Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime 428 + " old mUnpluggedTime=" + mUnpluggedTime 429 + " old mUnpluggedCount=" + mUnpluggedCount); 430 } 431 mUnpluggedTime = computeRunTimeLocked(batteryRealtime); 432 mUnpluggedCount = mCount; 433 if (DEBUG && mType < 0) { 434 Log.v(TAG, "unplug #" + mType 435 + ": new mUnpluggedTime=" + mUnpluggedTime 436 + " new mUnpluggedCount=" + mUnpluggedCount); 437 } 438 } 439 440 public void plug(long batteryUptime, long batteryRealtime) { 441 if (DEBUG && mType < 0) { 442 Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime 443 + " old mTotalTime=" + mTotalTime); 444 } 445 mTotalTime = computeRunTimeLocked(batteryRealtime); 446 mCount = computeCurrentCountLocked(); 447 if (DEBUG && mType < 0) { 448 Log.v(TAG, "plug #" + mType 449 + ": new mTotalTime=" + mTotalTime); 450 } 451 } 452 453 /** 454 * Writes a possibly null Timer to a Parcel. 455 * 456 * @param out the Parcel to be written to. 457 * @param timer a Timer, or null. 458 */ 459 public static void writeTimerToParcel(Parcel out, Timer timer, 460 long batteryRealtime) { 461 if (timer == null) { 462 out.writeInt(0); // indicates null 463 return; 464 } 465 out.writeInt(1); // indicates non-null 466 467 timer.writeToParcel(out, batteryRealtime); 468 } 469 470 @Override 471 public long getTotalTimeLocked(long batteryRealtime, int which) { 472 long val; 473 if (which == STATS_LAST) { 474 val = mLastTime; 475 } else { 476 val = computeRunTimeLocked(batteryRealtime); 477 if (which == STATS_UNPLUGGED) { 478 val -= mUnpluggedTime; 479 } else if (which != STATS_TOTAL) { 480 val -= mLoadedTime; 481 } 482 } 483 484 return val; 485 } 486 487 @Override 488 public int getCountLocked(int which) { 489 int val; 490 if (which == STATS_LAST) { 491 val = mLastCount; 492 } else { 493 val = computeCurrentCountLocked(); 494 if (which == STATS_UNPLUGGED) { 495 val -= mUnpluggedCount; 496 } else if (which != STATS_TOTAL) { 497 val -= mLoadedCount; 498 } 499 } 500 501 return val; 502 } 503 504 public void logState(Printer pw, String prefix) { 505 pw.println(prefix + " mCount=" + mCount 506 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 507 + " mUnpluggedCount=" + mUnpluggedCount); 508 pw.println(prefix + "mTotalTime=" + mTotalTime 509 + " mLoadedTime=" + mLoadedTime); 510 pw.println(prefix + "mLastTime=" + mLastTime 511 + " mUnpluggedTime=" + mUnpluggedTime); 512 } 513 514 515 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 516 long runTime = computeRunTimeLocked(batteryRealtime); 517 // Divide by 1000 for backwards compatibility 518 out.writeLong((runTime + 500) / 1000); 519 out.writeLong(((runTime - mLoadedTime) + 500) / 1000); 520 out.writeInt(mCount); 521 out.writeInt(mCount - mLoadedCount); 522 } 523 524 void readSummaryFromParcelLocked(Parcel in) { 525 // Multiply by 1000 for backwards compatibility 526 mTotalTime = mLoadedTime = in.readLong() * 1000; 527 mLastTime = in.readLong() * 1000; 528 mUnpluggedTime = mTotalTime; 529 mCount = mLoadedCount = in.readInt(); 530 mLastCount = in.readInt(); 531 mUnpluggedCount = mCount; 532 } 533 } 534 535 public static final class SamplingTimer extends Timer { 536 537 /** 538 * The most recent reported count from /proc/wakelocks. 539 */ 540 int mCurrentReportedCount; 541 542 /** 543 * The reported count from /proc/wakelocks when unplug() was last 544 * called. 545 */ 546 int mUnpluggedReportedCount; 547 548 /** 549 * The most recent reported total_time from /proc/wakelocks. 550 */ 551 long mCurrentReportedTotalTime; 552 553 554 /** 555 * The reported total_time from /proc/wakelocks when unplug() was last 556 * called. 557 */ 558 long mUnpluggedReportedTotalTime; 559 560 /** 561 * Whether we are currently in a discharge cycle. 562 */ 563 boolean mInDischarge; 564 565 /** 566 * Whether we are currently recording reported values. 567 */ 568 boolean mTrackingReportedValues; 569 570 /* 571 * A sequnce counter, incremented once for each update of the stats. 572 */ 573 int mUpdateVersion; 574 575 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) { 576 super(0, unpluggables, in); 577 mCurrentReportedCount = in.readInt(); 578 mUnpluggedReportedCount = in.readInt(); 579 mCurrentReportedTotalTime = in.readLong(); 580 mUnpluggedReportedTotalTime = in.readLong(); 581 mTrackingReportedValues = in.readInt() == 1; 582 mInDischarge = inDischarge; 583 } 584 585 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, 586 boolean trackReportedValues) { 587 super(0, unpluggables); 588 mTrackingReportedValues = trackReportedValues; 589 mInDischarge = inDischarge; 590 } 591 592 public void setStale() { 593 mTrackingReportedValues = false; 594 mUnpluggedReportedTotalTime = 0; 595 mUnpluggedReportedCount = 0; 596 } 597 598 public void setUpdateVersion(int version) { 599 mUpdateVersion = version; 600 } 601 602 public int getUpdateVersion() { 603 return mUpdateVersion; 604 } 605 606 public void updateCurrentReportedCount(int count) { 607 if (mInDischarge && mUnpluggedReportedCount == 0) { 608 // Updating the reported value for the first time. 609 mUnpluggedReportedCount = count; 610 // If we are receiving an update update mTrackingReportedValues; 611 mTrackingReportedValues = true; 612 } 613 mCurrentReportedCount = count; 614 } 615 616 public void updateCurrentReportedTotalTime(long totalTime) { 617 if (mInDischarge && mUnpluggedReportedTotalTime == 0) { 618 // Updating the reported value for the first time. 619 mUnpluggedReportedTotalTime = totalTime; 620 // If we are receiving an update update mTrackingReportedValues; 621 mTrackingReportedValues = true; 622 } 623 mCurrentReportedTotalTime = totalTime; 624 } 625 626 public void unplug(long batteryUptime, long batteryRealtime) { 627 super.unplug(batteryUptime, batteryRealtime); 628 if (mTrackingReportedValues) { 629 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime; 630 mUnpluggedReportedCount = mCurrentReportedCount; 631 } 632 mInDischarge = true; 633 } 634 635 public void plug(long batteryUptime, long batteryRealtime) { 636 super.plug(batteryUptime, batteryRealtime); 637 mInDischarge = false; 638 } 639 640 public void logState(Printer pw, String prefix) { 641 super.logState(pw, prefix); 642 pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount 643 + " mUnpluggedReportedCount=" + mUnpluggedReportedCount 644 + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime 645 + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime); 646 } 647 648 protected long computeRunTimeLocked(long curBatteryRealtime) { 649 return mTotalTime + (mInDischarge && mTrackingReportedValues 650 ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0); 651 } 652 653 protected int computeCurrentCountLocked() { 654 return mCount + (mInDischarge && mTrackingReportedValues 655 ? mCurrentReportedCount - mUnpluggedReportedCount : 0); 656 } 657 658 public void writeToParcel(Parcel out, long batteryRealtime) { 659 super.writeToParcel(out, batteryRealtime); 660 out.writeInt(mCurrentReportedCount); 661 out.writeInt(mUnpluggedReportedCount); 662 out.writeLong(mCurrentReportedTotalTime); 663 out.writeLong(mUnpluggedReportedTotalTime); 664 out.writeInt(mTrackingReportedValues ? 1 : 0); 665 } 666 667 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 668 super.writeSummaryFromParcelLocked(out, batteryRealtime); 669 out.writeLong(mCurrentReportedTotalTime); 670 out.writeInt(mCurrentReportedCount); 671 out.writeInt(mTrackingReportedValues ? 1 : 0); 672 } 673 674 void readSummaryFromParcelLocked(Parcel in) { 675 super.readSummaryFromParcelLocked(in); 676 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong(); 677 mUnpluggedReportedCount = mCurrentReportedCount = in.readInt(); 678 mTrackingReportedValues = in.readInt() == 1; 679 } 680 } 681 682 /** 683 * State for keeping track of timing information. 684 */ 685 public static final class StopwatchTimer extends Timer { 686 final ArrayList<StopwatchTimer> mTimerPool; 687 int mNesting; 688 689 690 /** 691 * The last time at which we updated the timer. If mNesting is > 0, 692 * subtract this from the current battery time to find the amount of 693 * time we have been running since we last computed an update. 694 */ 695 long mUpdateTime; 696 697 /** 698 * The total time at which the timer was acquired, to determine if 699 * was actually held for an interesting duration. 700 */ 701 long mAcquireTime; 702 703 long mTimeout; 704 705 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, 706 ArrayList<Unpluggable> unpluggables, Parcel in) { 707 super(type, unpluggables, in); 708 mTimerPool = timerPool; 709 mUpdateTime = in.readLong(); 710 } 711 712 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, 713 ArrayList<Unpluggable> unpluggables) { 714 super(type, unpluggables); 715 mTimerPool = timerPool; 716 } 717 718 void setTimeout(long timeout) { 719 mTimeout = timeout; 720 } 721 722 public void writeToParcel(Parcel out, long batteryRealtime) { 723 super.writeToParcel(out, batteryRealtime); 724 out.writeLong(mUpdateTime); 725 } 726 727 public void plug(long batteryUptime, long batteryRealtime) { 728 if (mNesting > 0) { 729 if (DEBUG && mType < 0) { 730 Log.v(TAG, "old mUpdateTime=" + mUpdateTime); 731 } 732 super.plug(batteryUptime, batteryRealtime); 733 mUpdateTime = batteryRealtime; 734 if (DEBUG && mType < 0) { 735 Log.v(TAG, "new mUpdateTime=" + mUpdateTime); 736 } 737 } 738 } 739 740 public void logState(Printer pw, String prefix) { 741 super.logState(pw, prefix); 742 pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime 743 + " mAcquireTime=" + mAcquireTime); 744 } 745 746 void startRunningLocked(BatteryStatsImpl stats) { 747 if (mNesting++ == 0) { 748 mUpdateTime = stats.getBatteryRealtimeLocked( 749 SystemClock.elapsedRealtime() * 1000); 750 if (mTimerPool != null) { 751 // Accumulate time to all currently active timers before adding 752 // this new one to the pool. 753 refreshTimersLocked(stats, mTimerPool); 754 // Add this timer to the active pool 755 mTimerPool.add(this); 756 } 757 // Increment the count 758 mCount++; 759 mAcquireTime = mTotalTime; 760 if (DEBUG && mType < 0) { 761 Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime 762 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 763 + " mAcquireTime=" + mAcquireTime); 764 } 765 } 766 } 767 768 boolean isRunningLocked() { 769 return mNesting > 0; 770 } 771 772 void stopRunningLocked(BatteryStatsImpl stats) { 773 // Ignore attempt to stop a timer that isn't running 774 if (mNesting == 0) { 775 return; 776 } 777 if (--mNesting == 0) { 778 if (mTimerPool != null) { 779 // Accumulate time to all active counters, scaled by the total 780 // active in the pool, before taking this one out of the pool. 781 refreshTimersLocked(stats, mTimerPool); 782 // Remove this timer from the active pool 783 mTimerPool.remove(this); 784 } else { 785 final long realtime = SystemClock.elapsedRealtime() * 1000; 786 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 787 mNesting = 1; 788 mTotalTime = computeRunTimeLocked(batteryRealtime); 789 mNesting = 0; 790 } 791 792 if (DEBUG && mType < 0) { 793 Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime 794 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 795 + " mAcquireTime=" + mAcquireTime); 796 } 797 798 if (mTotalTime == mAcquireTime) { 799 // If there was no change in the time, then discard this 800 // count. A somewhat cheezy strategy, but hey. 801 mCount--; 802 } 803 } 804 } 805 806 // Update the total time for all other running Timers with the same type as this Timer 807 // due to a change in timer count 808 private static void refreshTimersLocked(final BatteryStatsImpl stats, 809 final ArrayList<StopwatchTimer> pool) { 810 final long realtime = SystemClock.elapsedRealtime() * 1000; 811 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 812 final int N = pool.size(); 813 for (int i=N-1; i>= 0; i--) { 814 final StopwatchTimer t = pool.get(i); 815 long heldTime = batteryRealtime - t.mUpdateTime; 816 if (heldTime > 0) { 817 t.mTotalTime += heldTime / N; 818 } 819 t.mUpdateTime = batteryRealtime; 820 } 821 } 822 823 @Override 824 protected long computeRunTimeLocked(long curBatteryRealtime) { 825 if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) { 826 curBatteryRealtime = mUpdateTime + mTimeout; 827 } 828 return mTotalTime + (mNesting > 0 829 ? (curBatteryRealtime - mUpdateTime) 830 / (mTimerPool != null ? mTimerPool.size() : 1) 831 : 0); 832 } 833 834 @Override 835 protected int computeCurrentCountLocked() { 836 return mCount; 837 } 838 839 void readSummaryFromParcelLocked(Parcel in) { 840 super.readSummaryFromParcelLocked(in); 841 mNesting = 0; 842 } 843 } 844 845 private final Map<String, KernelWakelockStats> readKernelWakelockStats() { 846 847 byte[] buffer = new byte[4096]; 848 int len; 849 850 try { 851 FileInputStream is = new FileInputStream("/proc/wakelocks"); 852 len = is.read(buffer); 853 is.close(); 854 855 if (len > 0) { 856 int i; 857 for (i=0; i<len; i++) { 858 if (buffer[i] == '\0') { 859 len = i; 860 break; 861 } 862 } 863 } 864 } catch (java.io.FileNotFoundException e) { 865 return null; 866 } catch (java.io.IOException e) { 867 return null; 868 } 869 870 return parseProcWakelocks(buffer, len); 871 } 872 873 private final Map<String, KernelWakelockStats> parseProcWakelocks( 874 byte[] wlBuffer, int len) { 875 String name; 876 int count; 877 long totalTime; 878 int startIndex, endIndex; 879 int numUpdatedWlNames = 0; 880 881 // Advance past the first line. 882 int i; 883 for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++); 884 startIndex = endIndex = i + 1; 885 886 synchronized(this) { 887 Map<String, KernelWakelockStats> m = mProcWakelockFileStats; 888 889 sKernelWakelockUpdateVersion++; 890 while (endIndex < len) { 891 for (endIndex=startIndex; 892 endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0'; 893 endIndex++); 894 endIndex++; // endIndex is an exclusive upper bound. 895 896 String[] nameStringArray = mProcWakelocksName; 897 long[] wlData = mProcWakelocksData; 898 // Stomp out any bad characters since this is from a circular buffer 899 // A corruption is seen sometimes that results in the vm crashing 900 // This should prevent crashes and the line will probably fail to parse 901 for (int j = startIndex; j < endIndex; j++) { 902 if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?'; 903 } 904 boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex, 905 PROC_WAKELOCKS_FORMAT, nameStringArray, wlData, null); 906 907 name = nameStringArray[0]; 908 count = (int) wlData[1]; 909 // convert nanoseconds to microseconds with rounding. 910 totalTime = (wlData[2] + 500) / 1000; 911 912 if (parsed && name.length() > 0) { 913 if (!m.containsKey(name)) { 914 m.put(name, new KernelWakelockStats(count, totalTime, 915 sKernelWakelockUpdateVersion)); 916 numUpdatedWlNames++; 917 } else { 918 KernelWakelockStats kwlStats = m.get(name); 919 if (kwlStats.mVersion == sKernelWakelockUpdateVersion) { 920 kwlStats.mCount += count; 921 kwlStats.mTotalTime += totalTime; 922 } else { 923 kwlStats.mCount = count; 924 kwlStats.mTotalTime = totalTime; 925 kwlStats.mVersion = sKernelWakelockUpdateVersion; 926 numUpdatedWlNames++; 927 } 928 } 929 } 930 startIndex = endIndex; 931 } 932 933 if (m.size() != numUpdatedWlNames) { 934 // Don't report old data. 935 Iterator<KernelWakelockStats> itr = m.values().iterator(); 936 while (itr.hasNext()) { 937 if (itr.next().mVersion != sKernelWakelockUpdateVersion) { 938 itr.remove(); 939 } 940 } 941 } 942 return m; 943 } 944 } 945 946 private class KernelWakelockStats { 947 public int mCount; 948 public long mTotalTime; 949 public int mVersion; 950 951 KernelWakelockStats(int count, long totalTime, int version) { 952 mCount = count; 953 mTotalTime = totalTime; 954 mVersion = version; 955 } 956 } 957 958 /* 959 * Get the KernelWakelockTimer associated with name, and create a new one if one 960 * doesn't already exist. 961 */ 962 public SamplingTimer getKernelWakelockTimerLocked(String name) { 963 SamplingTimer kwlt = mKernelWakelockStats.get(name); 964 if (kwlt == null) { 965 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 966 true /* track reported values */); 967 mKernelWakelockStats.put(name, kwlt); 968 } 969 return kwlt; 970 } 971 972 private void doDataPlug(long[] dataTransfer, long currentBytes) { 973 dataTransfer[STATS_LAST] = dataTransfer[STATS_UNPLUGGED]; 974 dataTransfer[STATS_UNPLUGGED] = -1; 975 } 976 977 private void doDataUnplug(long[] dataTransfer, long currentBytes) { 978 dataTransfer[STATS_UNPLUGGED] = currentBytes; 979 } 980 981 /** 982 * Radio uptime in microseconds when transferring data. This value is very approximate. 983 * @return 984 */ 985 private long getCurrentRadioDataUptime() { 986 try { 987 File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms"); 988 if (!awakeTimeFile.exists()) return 0; 989 BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile)); 990 String line = br.readLine(); 991 br.close(); 992 return Long.parseLong(line) * 1000; 993 } catch (NumberFormatException nfe) { 994 // Nothing 995 } catch (IOException ioe) { 996 // Nothing 997 } 998 return 0; 999 } 1000 1001 /** 1002 * @deprecated use getRadioDataUptime 1003 */ 1004 public long getRadioDataUptimeMs() { 1005 return getRadioDataUptime() / 1000; 1006 } 1007 1008 /** 1009 * Returns the duration that the cell radio was up for data transfers. 1010 */ 1011 public long getRadioDataUptime() { 1012 if (mRadioDataStart == -1) { 1013 return mRadioDataUptime; 1014 } else { 1015 return getCurrentRadioDataUptime() - mRadioDataStart; 1016 } 1017 } 1018 1019 private int getCurrentBluetoothPingCount() { 1020 if (mBtHeadset != null) { 1021 return mBtHeadset.getBatteryUsageHint(); 1022 } 1023 return -1; 1024 } 1025 1026 public int getBluetoothPingCount() { 1027 if (mBluetoothPingStart == -1) { 1028 return mBluetoothPingCount; 1029 } else if (mBtHeadset != null) { 1030 return getCurrentBluetoothPingCount() - mBluetoothPingStart; 1031 } 1032 return 0; 1033 } 1034 1035 public void setBtHeadset(BluetoothHeadset headset) { 1036 if (headset != null && mBtHeadset == null && isOnBattery() && mBluetoothPingStart == -1) { 1037 mBluetoothPingStart = getCurrentBluetoothPingCount(); 1038 } 1039 mBtHeadset = headset; 1040 } 1041 1042 public void doUnplug(long batteryUptime, long batteryRealtime) { 1043 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 1044 Uid u = mUidStats.valueAt(iu); 1045 u.mStartedTcpBytesReceived = TrafficStats.getUidRxBytes(u.mUid); 1046 u.mStartedTcpBytesSent = TrafficStats.getUidTxBytes(u.mUid); 1047 u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived; 1048 u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent; 1049 } 1050 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 1051 mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime); 1052 } 1053 // Track total mobile data 1054 doDataUnplug(mMobileDataRx, TrafficStats.getMobileRxBytes()); 1055 doDataUnplug(mMobileDataTx, TrafficStats.getMobileTxBytes()); 1056 doDataUnplug(mTotalDataRx, TrafficStats.getTotalRxBytes()); 1057 doDataUnplug(mTotalDataTx, TrafficStats.getTotalTxBytes()); 1058 // Track radio awake time 1059 mRadioDataStart = getCurrentRadioDataUptime(); 1060 mRadioDataUptime = 0; 1061 // Track bt headset ping count 1062 mBluetoothPingStart = getCurrentBluetoothPingCount(); 1063 mBluetoothPingCount = 0; 1064 } 1065 1066 public void doPlug(long batteryUptime, long batteryRealtime) { 1067 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 1068 Uid u = mUidStats.valueAt(iu); 1069 if (u.mStartedTcpBytesReceived >= 0) { 1070 u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived(); 1071 u.mStartedTcpBytesReceived = -1; 1072 } 1073 if (u.mStartedTcpBytesSent >= 0) { 1074 u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent(); 1075 u.mStartedTcpBytesSent = -1; 1076 } 1077 } 1078 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 1079 mUnpluggables.get(i).plug(batteryUptime, batteryRealtime); 1080 } 1081 doDataPlug(mMobileDataRx, TrafficStats.getMobileRxBytes()); 1082 doDataPlug(mMobileDataTx, TrafficStats.getMobileTxBytes()); 1083 doDataPlug(mTotalDataRx, TrafficStats.getTotalRxBytes()); 1084 doDataPlug(mTotalDataTx, TrafficStats.getTotalTxBytes()); 1085 // Track radio awake time 1086 mRadioDataUptime = getRadioDataUptime(); 1087 mRadioDataStart = -1; 1088 1089 // Track bt headset ping count 1090 mBluetoothPingCount = getBluetoothPingCount(); 1091 mBluetoothPingStart = -1; 1092 } 1093 1094 public void noteStartGps(int uid) { 1095 getUidStatsLocked(uid).noteStartGps(); 1096 } 1097 1098 public void noteStopGps(int uid) { 1099 getUidStatsLocked(uid).noteStopGps(); 1100 } 1101 1102 public void noteScreenOnLocked() { 1103 if (!mScreenOn) { 1104 mScreenOn = true; 1105 mScreenOnTimer.startRunningLocked(this); 1106 if (mScreenBrightnessBin >= 0) { 1107 mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this); 1108 } 1109 } 1110 } 1111 1112 public void noteScreenOffLocked() { 1113 if (mScreenOn) { 1114 mScreenOn = false; 1115 mScreenOnTimer.stopRunningLocked(this); 1116 if (mScreenBrightnessBin >= 0) { 1117 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this); 1118 } 1119 } 1120 } 1121 1122 public void noteScreenBrightnessLocked(int brightness) { 1123 // Bin the brightness. 1124 int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS); 1125 if (bin < 0) bin = 0; 1126 else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1; 1127 if (mScreenBrightnessBin != bin) { 1128 if (mScreenOn) { 1129 if (mScreenBrightnessBin >= 0) { 1130 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this); 1131 } 1132 mScreenBrightnessTimer[bin].startRunningLocked(this); 1133 } 1134 mScreenBrightnessBin = bin; 1135 } 1136 } 1137 1138 public void noteInputEventAtomic() { 1139 mInputEventCounter.stepAtomic(); 1140 } 1141 1142 public void noteUserActivityLocked(int uid, int event) { 1143 getUidStatsLocked(uid).noteUserActivityLocked(event); 1144 } 1145 1146 public void notePhoneOnLocked() { 1147 if (!mPhoneOn) { 1148 mPhoneOn = true; 1149 mPhoneOnTimer.startRunningLocked(this); 1150 } 1151 } 1152 1153 public void notePhoneOffLocked() { 1154 if (mPhoneOn) { 1155 mPhoneOn = false; 1156 mPhoneOnTimer.stopRunningLocked(this); 1157 } 1158 } 1159 1160 /** 1161 * Telephony stack updates the phone state. 1162 * @param state phone state from ServiceState.getState() 1163 */ 1164 public void notePhoneStateLocked(int state) { 1165 int bin = mPhoneSignalStrengthBin; 1166 boolean isAirplaneMode = state == ServiceState.STATE_POWER_OFF; 1167 // Stop all timers 1168 if (isAirplaneMode || state == ServiceState.STATE_OUT_OF_SERVICE) { 1169 for (int i = 0; i < NUM_SIGNAL_STRENGTH_BINS; i++) { 1170 while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) { 1171 mPhoneSignalStrengthsTimer[i].stopRunningLocked(this); 1172 } 1173 } 1174 } 1175 // Stop Signal Scanning timer, in case we're going into service 1176 while (mPhoneSignalScanningTimer.isRunningLocked()) { 1177 mPhoneSignalScanningTimer.stopRunningLocked(this); 1178 } 1179 1180 // If we're back in service or continuing in service, restart the old timer. 1181 if (state == ServiceState.STATE_IN_SERVICE) { 1182 if (bin == -1) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1183 if (!mPhoneSignalStrengthsTimer[bin].isRunningLocked()) { 1184 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this); 1185 } 1186 } else if (state == ServiceState.STATE_OUT_OF_SERVICE) { 1187 mPhoneSignalStrengthBin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1188 if (!mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].isRunningLocked()) { 1189 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].startRunningLocked(this); 1190 } 1191 if (!mPhoneSignalScanningTimer.isRunningLocked()) { 1192 mPhoneSignalScanningTimer.startRunningLocked(this); 1193 } 1194 } 1195 mPhoneServiceState = state; 1196 } 1197 1198 public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) { 1199 // Bin the strength. 1200 int bin; 1201 if (mPhoneServiceState == ServiceState.STATE_POWER_OFF 1202 || mPhoneServiceState == ServiceState.STATE_OUT_OF_SERVICE) { 1203 // Ignore any signal strength changes when radio was turned off or out of service. 1204 return; 1205 } 1206 if (!signalStrength.isGsm()) { 1207 int dBm = signalStrength.getCdmaDbm(); 1208 if (dBm >= -75) bin = SIGNAL_STRENGTH_GREAT; 1209 else if (dBm >= -85) bin = SIGNAL_STRENGTH_GOOD; 1210 else if (dBm >= -95) bin = SIGNAL_STRENGTH_MODERATE; 1211 else if (dBm >= -100) bin = SIGNAL_STRENGTH_POOR; 1212 else bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1213 } else { 1214 int asu = signalStrength.getGsmSignalStrength(); 1215 if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1216 else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT; 1217 else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD; 1218 else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE; 1219 else bin = SIGNAL_STRENGTH_POOR; 1220 } 1221 if (mPhoneSignalStrengthBin != bin) { 1222 if (mPhoneSignalStrengthBin >= 0) { 1223 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this); 1224 } 1225 mPhoneSignalStrengthBin = bin; 1226 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this); 1227 } 1228 } 1229 1230 public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) { 1231 int bin = DATA_CONNECTION_NONE; 1232 if (hasData) { 1233 switch (dataType) { 1234 case TelephonyManager.NETWORK_TYPE_EDGE: 1235 bin = DATA_CONNECTION_EDGE; 1236 break; 1237 case TelephonyManager.NETWORK_TYPE_GPRS: 1238 bin = DATA_CONNECTION_GPRS; 1239 break; 1240 case TelephonyManager.NETWORK_TYPE_UMTS: 1241 bin = DATA_CONNECTION_UMTS; 1242 break; 1243 default: 1244 bin = DATA_CONNECTION_OTHER; 1245 break; 1246 } 1247 } 1248 if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData); 1249 if (mPhoneDataConnectionType != bin) { 1250 if (mPhoneDataConnectionType >= 0) { 1251 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this); 1252 } 1253 mPhoneDataConnectionType = bin; 1254 mPhoneDataConnectionsTimer[bin].startRunningLocked(this); 1255 } 1256 } 1257 1258 public void noteWifiOnLocked(int uid) { 1259 if (!mWifiOn) { 1260 mWifiOn = true; 1261 mWifiOnTimer.startRunningLocked(this); 1262 } 1263 if (mWifiOnUid != uid) { 1264 if (mWifiOnUid >= 0) { 1265 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked(); 1266 } 1267 mWifiOnUid = uid; 1268 getUidStatsLocked(uid).noteWifiTurnedOnLocked(); 1269 } 1270 } 1271 1272 public void noteWifiOffLocked(int uid) { 1273 if (mWifiOn) { 1274 mWifiOn = false; 1275 mWifiOnTimer.stopRunningLocked(this); 1276 } 1277 if (mWifiOnUid >= 0) { 1278 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked(); 1279 mWifiOnUid = -1; 1280 } 1281 } 1282 1283 public void noteAudioOnLocked(int uid) { 1284 if (!mAudioOn) { 1285 mAudioOn = true; 1286 mAudioOnTimer.startRunningLocked(this); 1287 } 1288 getUidStatsLocked(uid).noteAudioTurnedOnLocked(); 1289 } 1290 1291 public void noteAudioOffLocked(int uid) { 1292 if (mAudioOn) { 1293 mAudioOn = false; 1294 mAudioOnTimer.stopRunningLocked(this); 1295 } 1296 getUidStatsLocked(uid).noteAudioTurnedOffLocked(); 1297 } 1298 1299 public void noteVideoOnLocked(int uid) { 1300 if (!mVideoOn) { 1301 mVideoOn = true; 1302 mVideoOnTimer.startRunningLocked(this); 1303 } 1304 getUidStatsLocked(uid).noteVideoTurnedOnLocked(); 1305 } 1306 1307 public void noteVideoOffLocked(int uid) { 1308 if (mVideoOn) { 1309 mVideoOn = false; 1310 mVideoOnTimer.stopRunningLocked(this); 1311 } 1312 getUidStatsLocked(uid).noteVideoTurnedOffLocked(); 1313 } 1314 1315 public void noteWifiRunningLocked() { 1316 if (!mWifiRunning) { 1317 mWifiRunning = true; 1318 mWifiRunningTimer.startRunningLocked(this); 1319 } 1320 } 1321 1322 public void noteWifiStoppedLocked() { 1323 if (mWifiRunning) { 1324 mWifiRunning = false; 1325 mWifiRunningTimer.stopRunningLocked(this); 1326 } 1327 } 1328 1329 public void noteBluetoothOnLocked() { 1330 if (!mBluetoothOn) { 1331 mBluetoothOn = true; 1332 mBluetoothOnTimer.startRunningLocked(this); 1333 } 1334 } 1335 1336 public void noteBluetoothOffLocked() { 1337 if (mBluetoothOn) { 1338 mBluetoothOn = false; 1339 mBluetoothOnTimer.stopRunningLocked(this); 1340 } 1341 } 1342 1343 public void noteFullWifiLockAcquiredLocked(int uid) { 1344 getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(); 1345 } 1346 1347 public void noteFullWifiLockReleasedLocked(int uid) { 1348 getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(); 1349 } 1350 1351 public void noteScanWifiLockAcquiredLocked(int uid) { 1352 getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked(); 1353 } 1354 1355 public void noteScanWifiLockReleasedLocked(int uid) { 1356 getUidStatsLocked(uid).noteScanWifiLockReleasedLocked(); 1357 } 1358 1359 public void noteWifiMulticastEnabledLocked(int uid) { 1360 getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(); 1361 } 1362 1363 public void noteWifiMulticastDisabledLocked(int uid) { 1364 getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(); 1365 } 1366 1367 @Override public long getScreenOnTime(long batteryRealtime, int which) { 1368 return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which); 1369 } 1370 1371 @Override public long getScreenBrightnessTime(int brightnessBin, 1372 long batteryRealtime, int which) { 1373 return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked( 1374 batteryRealtime, which); 1375 } 1376 1377 @Override public int getInputEventCount(int which) { 1378 return mInputEventCounter.getCountLocked(which); 1379 } 1380 1381 @Override public long getPhoneOnTime(long batteryRealtime, int which) { 1382 return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which); 1383 } 1384 1385 @Override public long getPhoneSignalStrengthTime(int strengthBin, 1386 long batteryRealtime, int which) { 1387 return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked( 1388 batteryRealtime, which); 1389 } 1390 1391 @Override public long getPhoneSignalScanningTime( 1392 long batteryRealtime, int which) { 1393 return mPhoneSignalScanningTimer.getTotalTimeLocked( 1394 batteryRealtime, which); 1395 } 1396 1397 @Override public int getPhoneSignalStrengthCount(int dataType, int which) { 1398 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1399 } 1400 1401 @Override public long getPhoneDataConnectionTime(int dataType, 1402 long batteryRealtime, int which) { 1403 return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked( 1404 batteryRealtime, which); 1405 } 1406 1407 @Override public int getPhoneDataConnectionCount(int dataType, int which) { 1408 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1409 } 1410 1411 @Override public long getWifiOnTime(long batteryRealtime, int which) { 1412 return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which); 1413 } 1414 1415 @Override public long getWifiRunningTime(long batteryRealtime, int which) { 1416 return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which); 1417 } 1418 1419 @Override public long getBluetoothOnTime(long batteryRealtime, int which) { 1420 return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which); 1421 } 1422 1423 @Override public boolean getIsOnBattery() { 1424 return mOnBattery; 1425 } 1426 1427 @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() { 1428 return mUidStats; 1429 } 1430 1431 /** 1432 * The statistics associated with a particular uid. 1433 */ 1434 public final class Uid extends BatteryStats.Uid { 1435 1436 final int mUid; 1437 long mLoadedTcpBytesReceived; 1438 long mLoadedTcpBytesSent; 1439 long mCurrentTcpBytesReceived; 1440 long mCurrentTcpBytesSent; 1441 long mTcpBytesReceivedAtLastUnplug; 1442 long mTcpBytesSentAtLastUnplug; 1443 1444 // These are not saved/restored when parcelling, since we want 1445 // to return from the parcel with a snapshot of the state. 1446 long mStartedTcpBytesReceived = -1; 1447 long mStartedTcpBytesSent = -1; 1448 1449 boolean mWifiTurnedOn; 1450 StopwatchTimer mWifiTurnedOnTimer; 1451 1452 boolean mFullWifiLockOut; 1453 StopwatchTimer mFullWifiLockTimer; 1454 1455 boolean mScanWifiLockOut; 1456 StopwatchTimer mScanWifiLockTimer; 1457 1458 boolean mWifiMulticastEnabled; 1459 StopwatchTimer mWifiMulticastTimer; 1460 1461 boolean mAudioTurnedOn; 1462 StopwatchTimer mAudioTurnedOnTimer; 1463 1464 boolean mVideoTurnedOn; 1465 StopwatchTimer mVideoTurnedOnTimer; 1466 1467 Counter[] mUserActivityCounters; 1468 1469 /** 1470 * The statistics we have collected for this uid's wake locks. 1471 */ 1472 final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>(); 1473 1474 /** 1475 * The statistics we have collected for this uid's sensor activations. 1476 */ 1477 final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>(); 1478 1479 /** 1480 * The statistics we have collected for this uid's processes. 1481 */ 1482 final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>(); 1483 1484 /** 1485 * The statistics we have collected for this uid's processes. 1486 */ 1487 final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>(); 1488 1489 public Uid(int uid) { 1490 mUid = uid; 1491 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables); 1492 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables); 1493 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables); 1494 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1495 null, mUnpluggables); 1496 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables); 1497 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables); 1498 } 1499 1500 @Override 1501 public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() { 1502 return mWakelockStats; 1503 } 1504 1505 @Override 1506 public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() { 1507 return mSensorStats; 1508 } 1509 1510 @Override 1511 public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() { 1512 return mProcessStats; 1513 } 1514 1515 @Override 1516 public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { 1517 return mPackageStats; 1518 } 1519 1520 @Override 1521 public int getUid() { 1522 return mUid; 1523 } 1524 1525 @Override 1526 public long getTcpBytesReceived(int which) { 1527 if (which == STATS_LAST) { 1528 return mLoadedTcpBytesReceived; 1529 } else { 1530 long current = computeCurrentTcpBytesReceived(); 1531 if (which == STATS_UNPLUGGED) { 1532 current -= mTcpBytesReceivedAtLastUnplug; 1533 } else if (which == STATS_TOTAL) { 1534 current += mLoadedTcpBytesReceived; 1535 } 1536 return current; 1537 } 1538 } 1539 1540 public long computeCurrentTcpBytesReceived() { 1541 return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0 1542 ? (TrafficStats.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0); 1543 } 1544 1545 @Override 1546 public long getTcpBytesSent(int which) { 1547 if (which == STATS_LAST) { 1548 return mLoadedTcpBytesSent; 1549 } else { 1550 long current = computeCurrentTcpBytesSent(); 1551 if (which == STATS_UNPLUGGED) { 1552 current -= mTcpBytesSentAtLastUnplug; 1553 } else if (which == STATS_TOTAL) { 1554 current += mLoadedTcpBytesSent; 1555 } 1556 return current; 1557 } 1558 } 1559 1560 @Override 1561 public void noteWifiTurnedOnLocked() { 1562 if (!mWifiTurnedOn) { 1563 mWifiTurnedOn = true; 1564 mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1565 } 1566 } 1567 1568 @Override 1569 public void noteWifiTurnedOffLocked() { 1570 if (mWifiTurnedOn) { 1571 mWifiTurnedOn = false; 1572 mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1573 } 1574 } 1575 1576 @Override 1577 public void noteFullWifiLockAcquiredLocked() { 1578 if (!mFullWifiLockOut) { 1579 mFullWifiLockOut = true; 1580 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 1581 } 1582 } 1583 1584 @Override 1585 public void noteVideoTurnedOnLocked() { 1586 if (!mVideoTurnedOn) { 1587 mVideoTurnedOn = true; 1588 mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1589 } 1590 } 1591 1592 @Override 1593 public void noteVideoTurnedOffLocked() { 1594 if (mVideoTurnedOn) { 1595 mVideoTurnedOn = false; 1596 mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1597 } 1598 } 1599 1600 @Override 1601 public void noteAudioTurnedOnLocked() { 1602 if (!mAudioTurnedOn) { 1603 mAudioTurnedOn = true; 1604 mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1605 } 1606 } 1607 1608 @Override 1609 public void noteAudioTurnedOffLocked() { 1610 if (mAudioTurnedOn) { 1611 mAudioTurnedOn = false; 1612 mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1613 } 1614 } 1615 1616 @Override 1617 public void noteFullWifiLockReleasedLocked() { 1618 if (mFullWifiLockOut) { 1619 mFullWifiLockOut = false; 1620 mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 1621 } 1622 } 1623 1624 @Override 1625 public void noteScanWifiLockAcquiredLocked() { 1626 if (!mScanWifiLockOut) { 1627 mScanWifiLockOut = true; 1628 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 1629 } 1630 } 1631 1632 @Override 1633 public void noteScanWifiLockReleasedLocked() { 1634 if (mScanWifiLockOut) { 1635 mScanWifiLockOut = false; 1636 mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 1637 } 1638 } 1639 1640 @Override 1641 public void noteWifiMulticastEnabledLocked() { 1642 if (!mWifiMulticastEnabled) { 1643 mWifiMulticastEnabled = true; 1644 mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this); 1645 } 1646 } 1647 1648 @Override 1649 public void noteWifiMulticastDisabledLocked() { 1650 if (mWifiMulticastEnabled) { 1651 mWifiMulticastEnabled = false; 1652 mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this); 1653 } 1654 } 1655 1656 @Override 1657 public long getWifiTurnedOnTime(long batteryRealtime, int which) { 1658 return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1659 } 1660 1661 @Override 1662 public long getAudioTurnedOnTime(long batteryRealtime, int which) { 1663 return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1664 } 1665 1666 @Override 1667 public long getVideoTurnedOnTime(long batteryRealtime, int which) { 1668 return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1669 } 1670 1671 @Override 1672 public long getFullWifiLockTime(long batteryRealtime, int which) { 1673 return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 1674 } 1675 1676 @Override 1677 public long getScanWifiLockTime(long batteryRealtime, int which) { 1678 return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 1679 } 1680 1681 @Override 1682 public long getWifiMulticastTime(long batteryRealtime, int which) { 1683 return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime, 1684 which); 1685 } 1686 1687 @Override 1688 public void noteUserActivityLocked(int type) { 1689 if (mUserActivityCounters == null) { 1690 initUserActivityLocked(); 1691 } 1692 if (type < 0) type = 0; 1693 else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1; 1694 mUserActivityCounters[type].stepAtomic(); 1695 } 1696 1697 @Override 1698 public boolean hasUserActivity() { 1699 return mUserActivityCounters != null; 1700 } 1701 1702 @Override 1703 public int getUserActivityCount(int type, int which) { 1704 if (mUserActivityCounters == null) { 1705 return 0; 1706 } 1707 return mUserActivityCounters[type].getCountLocked(which); 1708 } 1709 1710 void initUserActivityLocked() { 1711 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 1712 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1713 mUserActivityCounters[i] = new Counter(mUnpluggables); 1714 } 1715 } 1716 1717 public long computeCurrentTcpBytesSent() { 1718 return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0 1719 ? (TrafficStats.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0); 1720 } 1721 1722 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1723 out.writeInt(mWakelockStats.size()); 1724 for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) { 1725 out.writeString(wakelockEntry.getKey()); 1726 Uid.Wakelock wakelock = wakelockEntry.getValue(); 1727 wakelock.writeToParcelLocked(out, batteryRealtime); 1728 } 1729 1730 out.writeInt(mSensorStats.size()); 1731 for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) { 1732 out.writeInt(sensorEntry.getKey()); 1733 Uid.Sensor sensor = sensorEntry.getValue(); 1734 sensor.writeToParcelLocked(out, batteryRealtime); 1735 } 1736 1737 out.writeInt(mProcessStats.size()); 1738 for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) { 1739 out.writeString(procEntry.getKey()); 1740 Uid.Proc proc = procEntry.getValue(); 1741 proc.writeToParcelLocked(out); 1742 } 1743 1744 out.writeInt(mPackageStats.size()); 1745 for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) { 1746 out.writeString(pkgEntry.getKey()); 1747 Uid.Pkg pkg = pkgEntry.getValue(); 1748 pkg.writeToParcelLocked(out); 1749 } 1750 1751 out.writeLong(mLoadedTcpBytesReceived); 1752 out.writeLong(mLoadedTcpBytesSent); 1753 out.writeLong(computeCurrentTcpBytesReceived()); 1754 out.writeLong(computeCurrentTcpBytesSent()); 1755 out.writeLong(mTcpBytesReceivedAtLastUnplug); 1756 out.writeLong(mTcpBytesSentAtLastUnplug); 1757 mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime); 1758 mFullWifiLockTimer.writeToParcel(out, batteryRealtime); 1759 mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime); 1760 mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime); 1761 mScanWifiLockTimer.writeToParcel(out, batteryRealtime); 1762 mWifiMulticastTimer.writeToParcel(out, batteryRealtime); 1763 if (mUserActivityCounters == null) { 1764 out.writeInt(0); 1765 } else { 1766 out.writeInt(1); 1767 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1768 mUserActivityCounters[i].writeToParcel(out); 1769 } 1770 } 1771 } 1772 1773 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1774 int numWakelocks = in.readInt(); 1775 mWakelockStats.clear(); 1776 for (int j = 0; j < numWakelocks; j++) { 1777 String wakelockName = in.readString(); 1778 Uid.Wakelock wakelock = new Wakelock(); 1779 wakelock.readFromParcelLocked(unpluggables, in); 1780 if (mWakelockStats.size() < MAX_WAKELOCKS_PER_UID) { 1781 // We will just drop some random set of wakelocks if 1782 // the previous run of the system was an older version 1783 // that didn't impose a limit. 1784 mWakelockStats.put(wakelockName, wakelock); 1785 } 1786 } 1787 1788 int numSensors = in.readInt(); 1789 mSensorStats.clear(); 1790 for (int k = 0; k < numSensors; k++) { 1791 int sensorNumber = in.readInt(); 1792 Uid.Sensor sensor = new Sensor(sensorNumber); 1793 sensor.readFromParcelLocked(mUnpluggables, in); 1794 mSensorStats.put(sensorNumber, sensor); 1795 } 1796 1797 int numProcs = in.readInt(); 1798 mProcessStats.clear(); 1799 for (int k = 0; k < numProcs; k++) { 1800 String processName = in.readString(); 1801 Uid.Proc proc = new Proc(); 1802 proc.readFromParcelLocked(in); 1803 mProcessStats.put(processName, proc); 1804 } 1805 1806 int numPkgs = in.readInt(); 1807 mPackageStats.clear(); 1808 for (int l = 0; l < numPkgs; l++) { 1809 String packageName = in.readString(); 1810 Uid.Pkg pkg = new Pkg(); 1811 pkg.readFromParcelLocked(in); 1812 mPackageStats.put(packageName, pkg); 1813 } 1814 1815 mLoadedTcpBytesReceived = in.readLong(); 1816 mLoadedTcpBytesSent = in.readLong(); 1817 mCurrentTcpBytesReceived = in.readLong(); 1818 mCurrentTcpBytesSent = in.readLong(); 1819 mTcpBytesReceivedAtLastUnplug = in.readLong(); 1820 mTcpBytesSentAtLastUnplug = in.readLong(); 1821 mWifiTurnedOn = false; 1822 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables, in); 1823 mFullWifiLockOut = false; 1824 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in); 1825 mAudioTurnedOn = false; 1826 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables, in); 1827 mVideoTurnedOn = false; 1828 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables, in); 1829 mScanWifiLockOut = false; 1830 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in); 1831 mWifiMulticastEnabled = false; 1832 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1833 null, mUnpluggables, in); 1834 if (in.readInt() == 0) { 1835 mUserActivityCounters = null; 1836 } else { 1837 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 1838 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1839 mUserActivityCounters[i] = new Counter(mUnpluggables, in); 1840 } 1841 } 1842 } 1843 1844 /** 1845 * The statistics associated with a particular wake lock. 1846 */ 1847 public final class Wakelock extends BatteryStats.Uid.Wakelock { 1848 /** 1849 * How long (in ms) this uid has been keeping the device partially awake. 1850 */ 1851 StopwatchTimer mTimerPartial; 1852 1853 /** 1854 * How long (in ms) this uid has been keeping the device fully awake. 1855 */ 1856 StopwatchTimer mTimerFull; 1857 1858 /** 1859 * How long (in ms) this uid has had a window keeping the device awake. 1860 */ 1861 StopwatchTimer mTimerWindow; 1862 1863 /** 1864 * Reads a possibly null Timer from a Parcel. The timer is associated with the 1865 * proper timer pool from the given BatteryStatsImpl object. 1866 * 1867 * @param in the Parcel to be read from. 1868 * return a new Timer, or null. 1869 */ 1870 private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, 1871 ArrayList<Unpluggable> unpluggables, Parcel in) { 1872 if (in.readInt() == 0) { 1873 return null; 1874 } 1875 1876 return new StopwatchTimer(type, pool, unpluggables, in); 1877 } 1878 1879 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1880 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL, 1881 mPartialTimers, unpluggables, in); 1882 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, 1883 mFullTimers, unpluggables, in); 1884 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, 1885 mWindowTimers, unpluggables, in); 1886 } 1887 1888 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1889 Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime); 1890 Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime); 1891 Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime); 1892 } 1893 1894 @Override 1895 public Timer getWakeTime(int type) { 1896 switch (type) { 1897 case WAKE_TYPE_FULL: return mTimerFull; 1898 case WAKE_TYPE_PARTIAL: return mTimerPartial; 1899 case WAKE_TYPE_WINDOW: return mTimerWindow; 1900 default: throw new IllegalArgumentException("type = " + type); 1901 } 1902 } 1903 } 1904 1905 public final class Sensor extends BatteryStats.Uid.Sensor { 1906 final int mHandle; 1907 StopwatchTimer mTimer; 1908 1909 public Sensor(int handle) { 1910 mHandle = handle; 1911 } 1912 1913 private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables, 1914 Parcel in) { 1915 if (in.readInt() == 0) { 1916 return null; 1917 } 1918 1919 ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle); 1920 if (pool == null) { 1921 pool = new ArrayList<StopwatchTimer>(); 1922 mSensorTimers.put(mHandle, pool); 1923 } 1924 return new StopwatchTimer(0, pool, unpluggables, in); 1925 } 1926 1927 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1928 mTimer = readTimerFromParcel(unpluggables, in); 1929 } 1930 1931 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1932 Timer.writeTimerToParcel(out, mTimer, batteryRealtime); 1933 } 1934 1935 @Override 1936 public Timer getSensorTime() { 1937 return mTimer; 1938 } 1939 1940 @Override 1941 public int getHandle() { 1942 return mHandle; 1943 } 1944 } 1945 1946 /** 1947 * The statistics associated with a particular process. 1948 */ 1949 public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable { 1950 /** 1951 * Total time (in 1/100 sec) spent executing in user code. 1952 */ 1953 long mUserTime; 1954 1955 /** 1956 * Total time (in 1/100 sec) spent executing in kernel code. 1957 */ 1958 long mSystemTime; 1959 1960 /** 1961 * Number of times the process has been started. 1962 */ 1963 int mStarts; 1964 1965 /** 1966 * Amount of time the process was running in the foreground. 1967 */ 1968 long mForegroundTime; 1969 1970 /** 1971 * The amount of user time loaded from a previous save. 1972 */ 1973 long mLoadedUserTime; 1974 1975 /** 1976 * The amount of system time loaded from a previous save. 1977 */ 1978 long mLoadedSystemTime; 1979 1980 /** 1981 * The number of times the process has started from a previous save. 1982 */ 1983 int mLoadedStarts; 1984 1985 /** 1986 * The amount of foreground time loaded from a previous save. 1987 */ 1988 long mLoadedForegroundTime; 1989 1990 /** 1991 * The amount of user time loaded from the previous run. 1992 */ 1993 long mLastUserTime; 1994 1995 /** 1996 * The amount of system time loaded from the previous run. 1997 */ 1998 long mLastSystemTime; 1999 2000 /** 2001 * The number of times the process has started from the previous run. 2002 */ 2003 int mLastStarts; 2004 2005 /** 2006 * The amount of foreground time loaded from the previous run 2007 */ 2008 long mLastForegroundTime; 2009 2010 /** 2011 * The amount of user time when last unplugged. 2012 */ 2013 long mUnpluggedUserTime; 2014 2015 /** 2016 * The amount of system time when last unplugged. 2017 */ 2018 long mUnpluggedSystemTime; 2019 2020 /** 2021 * The number of times the process has started before unplugged. 2022 */ 2023 int mUnpluggedStarts; 2024 2025 /** 2026 * The amount of foreground time since unplugged. 2027 */ 2028 long mUnpluggedForegroundTime; 2029 2030 SamplingCounter[] mSpeedBins; 2031 2032 Proc() { 2033 mUnpluggables.add(this); 2034 mSpeedBins = new SamplingCounter[getCpuSpeedSteps()]; 2035 for (int i = 0; i < mSpeedBins.length; i++) { 2036 mSpeedBins[i] = new SamplingCounter(mUnpluggables); 2037 } 2038 } 2039 2040 public void unplug(long batteryUptime, long batteryRealtime) { 2041 mUnpluggedUserTime = mUserTime; 2042 mUnpluggedSystemTime = mSystemTime; 2043 mUnpluggedStarts = mStarts; 2044 mUnpluggedForegroundTime = mForegroundTime; 2045 } 2046 2047 public void plug(long batteryUptime, long batteryRealtime) { 2048 } 2049 2050 void writeToParcelLocked(Parcel out) { 2051 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 2052 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 2053 2054 out.writeLong(mUserTime); 2055 out.writeLong(mSystemTime); 2056 out.writeLong(mForegroundTime); 2057 out.writeInt(mStarts); 2058 out.writeLong(mLoadedUserTime); 2059 out.writeLong(mLoadedSystemTime); 2060 out.writeLong(mLoadedForegroundTime); 2061 out.writeInt(mLoadedStarts); 2062 out.writeLong(mLastUserTime); 2063 out.writeLong(mLastSystemTime); 2064 out.writeLong(mLastForegroundTime); 2065 out.writeInt(mLastStarts); 2066 out.writeLong(mUnpluggedUserTime); 2067 out.writeLong(mUnpluggedSystemTime); 2068 out.writeLong(mUnpluggedForegroundTime); 2069 out.writeInt(mUnpluggedStarts); 2070 2071 out.writeInt(mSpeedBins.length); 2072 for (int i = 0; i < mSpeedBins.length; i++) { 2073 mSpeedBins[i].writeToParcel(out); 2074 } 2075 } 2076 2077 void readFromParcelLocked(Parcel in) { 2078 mUserTime = in.readLong(); 2079 mSystemTime = in.readLong(); 2080 mForegroundTime = in.readLong(); 2081 mStarts = in.readInt(); 2082 mLoadedUserTime = in.readLong(); 2083 mLoadedSystemTime = in.readLong(); 2084 mLoadedForegroundTime = in.readLong(); 2085 mLoadedStarts = in.readInt(); 2086 mLastUserTime = in.readLong(); 2087 mLastSystemTime = in.readLong(); 2088 mLastForegroundTime = in.readLong(); 2089 mLastStarts = in.readInt(); 2090 mUnpluggedUserTime = in.readLong(); 2091 mUnpluggedSystemTime = in.readLong(); 2092 mUnpluggedForegroundTime = in.readLong(); 2093 mUnpluggedStarts = in.readInt(); 2094 2095 int bins = in.readInt(); 2096 mSpeedBins = new SamplingCounter[bins]; 2097 for (int i = 0; i < bins; i++) { 2098 mSpeedBins[i] = new SamplingCounter(mUnpluggables, in); 2099 } 2100 } 2101 2102 public BatteryStatsImpl getBatteryStats() { 2103 return BatteryStatsImpl.this; 2104 } 2105 2106 public void addCpuTimeLocked(int utime, int stime) { 2107 mUserTime += utime; 2108 mSystemTime += stime; 2109 } 2110 2111 public void addForegroundTimeLocked(long ttime) { 2112 mForegroundTime += ttime; 2113 } 2114 2115 public void incStartsLocked() { 2116 mStarts++; 2117 } 2118 2119 @Override 2120 public long getUserTime(int which) { 2121 long val; 2122 if (which == STATS_LAST) { 2123 val = mLastUserTime; 2124 } else { 2125 val = mUserTime; 2126 if (which == STATS_CURRENT) { 2127 val -= mLoadedUserTime; 2128 } else if (which == STATS_UNPLUGGED) { 2129 val -= mUnpluggedUserTime; 2130 } 2131 } 2132 return val; 2133 } 2134 2135 @Override 2136 public long getSystemTime(int which) { 2137 long val; 2138 if (which == STATS_LAST) { 2139 val = mLastSystemTime; 2140 } else { 2141 val = mSystemTime; 2142 if (which == STATS_CURRENT) { 2143 val -= mLoadedSystemTime; 2144 } else if (which == STATS_UNPLUGGED) { 2145 val -= mUnpluggedSystemTime; 2146 } 2147 } 2148 return val; 2149 } 2150 2151 @Override 2152 public long getForegroundTime(int which) { 2153 long val; 2154 if (which == STATS_LAST) { 2155 val = mLastForegroundTime; 2156 } else { 2157 val = mForegroundTime; 2158 if (which == STATS_CURRENT) { 2159 val -= mLoadedForegroundTime; 2160 } else if (which == STATS_UNPLUGGED) { 2161 val -= mUnpluggedForegroundTime; 2162 } 2163 } 2164 return val; 2165 } 2166 2167 @Override 2168 public int getStarts(int which) { 2169 int val; 2170 if (which == STATS_LAST) { 2171 val = mLastStarts; 2172 } else { 2173 val = mStarts; 2174 if (which == STATS_CURRENT) { 2175 val -= mLoadedStarts; 2176 } else if (which == STATS_UNPLUGGED) { 2177 val -= mUnpluggedStarts; 2178 } 2179 } 2180 return val; 2181 } 2182 2183 /* Called by ActivityManagerService when CPU times are updated. */ 2184 public void addSpeedStepTimes(long[] values) { 2185 for (int i = 0; i < mSpeedBins.length && i < values.length; i++) { 2186 mSpeedBins[i].addCountAtomic(values[i]); 2187 } 2188 } 2189 2190 @Override 2191 public long getTimeAtCpuSpeedStep(int speedStep, int which) { 2192 if (speedStep < mSpeedBins.length) { 2193 return mSpeedBins[speedStep].getCountLocked(which); 2194 } else { 2195 return 0; 2196 } 2197 } 2198 } 2199 2200 /** 2201 * The statistics associated with a particular package. 2202 */ 2203 public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable { 2204 /** 2205 * Number of times this package has done something that could wake up the 2206 * device from sleep. 2207 */ 2208 int mWakeups; 2209 2210 /** 2211 * Number of things that could wake up the device loaded from a 2212 * previous save. 2213 */ 2214 int mLoadedWakeups; 2215 2216 /** 2217 * Number of things that could wake up the device as of the 2218 * last run. 2219 */ 2220 int mLastWakeups; 2221 2222 /** 2223 * Number of things that could wake up the device as of the 2224 * last run. 2225 */ 2226 int mUnpluggedWakeups; 2227 2228 /** 2229 * The statics we have collected for this package's services. 2230 */ 2231 final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>(); 2232 2233 Pkg() { 2234 mUnpluggables.add(this); 2235 } 2236 2237 public void unplug(long batteryUptime, long batteryRealtime) { 2238 mUnpluggedWakeups = mWakeups; 2239 } 2240 2241 public void plug(long batteryUptime, long batteryRealtime) { 2242 } 2243 2244 void readFromParcelLocked(Parcel in) { 2245 mWakeups = in.readInt(); 2246 mLoadedWakeups = in.readInt(); 2247 mLastWakeups = in.readInt(); 2248 mUnpluggedWakeups = in.readInt(); 2249 2250 int numServs = in.readInt(); 2251 mServiceStats.clear(); 2252 for (int m = 0; m < numServs; m++) { 2253 String serviceName = in.readString(); 2254 Uid.Pkg.Serv serv = new Serv(); 2255 mServiceStats.put(serviceName, serv); 2256 2257 serv.readFromParcelLocked(in); 2258 } 2259 } 2260 2261 void writeToParcelLocked(Parcel out) { 2262 out.writeInt(mWakeups); 2263 out.writeInt(mLoadedWakeups); 2264 out.writeInt(mLastWakeups); 2265 out.writeInt(mUnpluggedWakeups); 2266 2267 out.writeInt(mServiceStats.size()); 2268 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) { 2269 out.writeString(servEntry.getKey()); 2270 Uid.Pkg.Serv serv = servEntry.getValue(); 2271 2272 serv.writeToParcelLocked(out); 2273 } 2274 } 2275 2276 @Override 2277 public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() { 2278 return mServiceStats; 2279 } 2280 2281 @Override 2282 public int getWakeups(int which) { 2283 int val; 2284 if (which == STATS_LAST) { 2285 val = mLastWakeups; 2286 } else { 2287 val = mWakeups; 2288 if (which == STATS_CURRENT) { 2289 val -= mLoadedWakeups; 2290 } else if (which == STATS_UNPLUGGED) { 2291 val -= mUnpluggedWakeups; 2292 } 2293 } 2294 2295 return val; 2296 } 2297 2298 /** 2299 * The statistics associated with a particular service. 2300 */ 2301 public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable { 2302 /** 2303 * Total time (ms in battery uptime) the service has been left started. 2304 */ 2305 long mStartTime; 2306 2307 /** 2308 * If service has been started and not yet stopped, this is 2309 * when it was started. 2310 */ 2311 long mRunningSince; 2312 2313 /** 2314 * True if we are currently running. 2315 */ 2316 boolean mRunning; 2317 2318 /** 2319 * Total number of times startService() has been called. 2320 */ 2321 int mStarts; 2322 2323 /** 2324 * Total time (ms in battery uptime) the service has been left launched. 2325 */ 2326 long mLaunchedTime; 2327 2328 /** 2329 * If service has been launched and not yet exited, this is 2330 * when it was launched (ms in battery uptime). 2331 */ 2332 long mLaunchedSince; 2333 2334 /** 2335 * True if we are currently launched. 2336 */ 2337 boolean mLaunched; 2338 2339 /** 2340 * Total number times the service has been launched. 2341 */ 2342 int mLaunches; 2343 2344 /** 2345 * The amount of time spent started loaded from a previous save 2346 * (ms in battery uptime). 2347 */ 2348 long mLoadedStartTime; 2349 2350 /** 2351 * The number of starts loaded from a previous save. 2352 */ 2353 int mLoadedStarts; 2354 2355 /** 2356 * The number of launches loaded from a previous save. 2357 */ 2358 int mLoadedLaunches; 2359 2360 /** 2361 * The amount of time spent started as of the last run (ms 2362 * in battery uptime). 2363 */ 2364 long mLastStartTime; 2365 2366 /** 2367 * The number of starts as of the last run. 2368 */ 2369 int mLastStarts; 2370 2371 /** 2372 * The number of launches as of the last run. 2373 */ 2374 int mLastLaunches; 2375 2376 /** 2377 * The amount of time spent started when last unplugged (ms 2378 * in battery uptime). 2379 */ 2380 long mUnpluggedStartTime; 2381 2382 /** 2383 * The number of starts when last unplugged. 2384 */ 2385 int mUnpluggedStarts; 2386 2387 /** 2388 * The number of launches when last unplugged. 2389 */ 2390 int mUnpluggedLaunches; 2391 2392 Serv() { 2393 mUnpluggables.add(this); 2394 } 2395 2396 public void unplug(long batteryUptime, long batteryRealtime) { 2397 mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime); 2398 mUnpluggedStarts = mStarts; 2399 mUnpluggedLaunches = mLaunches; 2400 } 2401 2402 public void plug(long batteryUptime, long batteryRealtime) { 2403 } 2404 2405 void readFromParcelLocked(Parcel in) { 2406 mStartTime = in.readLong(); 2407 mRunningSince = in.readLong(); 2408 mRunning = in.readInt() != 0; 2409 mStarts = in.readInt(); 2410 mLaunchedTime = in.readLong(); 2411 mLaunchedSince = in.readLong(); 2412 mLaunched = in.readInt() != 0; 2413 mLaunches = in.readInt(); 2414 mLoadedStartTime = in.readLong(); 2415 mLoadedStarts = in.readInt(); 2416 mLoadedLaunches = in.readInt(); 2417 mLastStartTime = in.readLong(); 2418 mLastStarts = in.readInt(); 2419 mLastLaunches = in.readInt(); 2420 mUnpluggedStartTime = in.readLong(); 2421 mUnpluggedStarts = in.readInt(); 2422 mUnpluggedLaunches = in.readInt(); 2423 } 2424 2425 void writeToParcelLocked(Parcel out) { 2426 out.writeLong(mStartTime); 2427 out.writeLong(mRunningSince); 2428 out.writeInt(mRunning ? 1 : 0); 2429 out.writeInt(mStarts); 2430 out.writeLong(mLaunchedTime); 2431 out.writeLong(mLaunchedSince); 2432 out.writeInt(mLaunched ? 1 : 0); 2433 out.writeInt(mLaunches); 2434 out.writeLong(mLoadedStartTime); 2435 out.writeInt(mLoadedStarts); 2436 out.writeInt(mLoadedLaunches); 2437 out.writeLong(mLastStartTime); 2438 out.writeInt(mLastStarts); 2439 out.writeInt(mLastLaunches); 2440 out.writeLong(mUnpluggedStartTime); 2441 out.writeInt(mUnpluggedStarts); 2442 out.writeInt(mUnpluggedLaunches); 2443 } 2444 2445 long getLaunchTimeToNowLocked(long batteryUptime) { 2446 if (!mLaunched) return mLaunchedTime; 2447 return mLaunchedTime + batteryUptime - mLaunchedSince; 2448 } 2449 2450 long getStartTimeToNowLocked(long batteryUptime) { 2451 if (!mRunning) return mStartTime; 2452 return mStartTime + batteryUptime - mRunningSince; 2453 } 2454 2455 public void startLaunchedLocked() { 2456 if (!mLaunched) { 2457 mLaunches++; 2458 mLaunchedSince = getBatteryUptimeLocked(); 2459 mLaunched = true; 2460 } 2461 } 2462 2463 public void stopLaunchedLocked() { 2464 if (mLaunched) { 2465 long time = getBatteryUptimeLocked() - mLaunchedSince; 2466 if (time > 0) { 2467 mLaunchedTime += time; 2468 } else { 2469 mLaunches--; 2470 } 2471 mLaunched = false; 2472 } 2473 } 2474 2475 public void startRunningLocked() { 2476 if (!mRunning) { 2477 mStarts++; 2478 mRunningSince = getBatteryUptimeLocked(); 2479 mRunning = true; 2480 } 2481 } 2482 2483 public void stopRunningLocked() { 2484 if (mRunning) { 2485 long time = getBatteryUptimeLocked() - mRunningSince; 2486 if (time > 0) { 2487 mStartTime += time; 2488 } else { 2489 mStarts--; 2490 } 2491 mRunning = false; 2492 } 2493 } 2494 2495 public BatteryStatsImpl getBatteryStats() { 2496 return BatteryStatsImpl.this; 2497 } 2498 2499 @Override 2500 public int getLaunches(int which) { 2501 int val; 2502 2503 if (which == STATS_LAST) { 2504 val = mLastLaunches; 2505 } else { 2506 val = mLaunches; 2507 if (which == STATS_CURRENT) { 2508 val -= mLoadedLaunches; 2509 } else if (which == STATS_UNPLUGGED) { 2510 val -= mUnpluggedLaunches; 2511 } 2512 } 2513 2514 return val; 2515 } 2516 2517 @Override 2518 public long getStartTime(long now, int which) { 2519 long val; 2520 if (which == STATS_LAST) { 2521 val = mLastStartTime; 2522 } else { 2523 val = getStartTimeToNowLocked(now); 2524 if (which == STATS_CURRENT) { 2525 val -= mLoadedStartTime; 2526 } else if (which == STATS_UNPLUGGED) { 2527 val -= mUnpluggedStartTime; 2528 } 2529 } 2530 2531 return val; 2532 } 2533 2534 @Override 2535 public int getStarts(int which) { 2536 int val; 2537 if (which == STATS_LAST) { 2538 val = mLastStarts; 2539 } else { 2540 val = mStarts; 2541 if (which == STATS_CURRENT) { 2542 val -= mLoadedStarts; 2543 } else if (which == STATS_UNPLUGGED) { 2544 val -= mUnpluggedStarts; 2545 } 2546 } 2547 2548 return val; 2549 } 2550 } 2551 2552 public BatteryStatsImpl getBatteryStats() { 2553 return BatteryStatsImpl.this; 2554 } 2555 2556 public void incWakeupsLocked() { 2557 mWakeups++; 2558 } 2559 2560 final Serv newServiceStatsLocked() { 2561 return new Serv(); 2562 } 2563 } 2564 2565 /** 2566 * Retrieve the statistics object for a particular process, creating 2567 * if needed. 2568 */ 2569 public Proc getProcessStatsLocked(String name) { 2570 Proc ps = mProcessStats.get(name); 2571 if (ps == null) { 2572 ps = new Proc(); 2573 mProcessStats.put(name, ps); 2574 } 2575 2576 return ps; 2577 } 2578 2579 /** 2580 * Retrieve the statistics object for a particular service, creating 2581 * if needed. 2582 */ 2583 public Pkg getPackageStatsLocked(String name) { 2584 Pkg ps = mPackageStats.get(name); 2585 if (ps == null) { 2586 ps = new Pkg(); 2587 mPackageStats.put(name, ps); 2588 } 2589 2590 return ps; 2591 } 2592 2593 /** 2594 * Retrieve the statistics object for a particular service, creating 2595 * if needed. 2596 */ 2597 public Pkg.Serv getServiceStatsLocked(String pkg, String serv) { 2598 Pkg ps = getPackageStatsLocked(pkg); 2599 Pkg.Serv ss = ps.mServiceStats.get(serv); 2600 if (ss == null) { 2601 ss = ps.newServiceStatsLocked(); 2602 ps.mServiceStats.put(serv, ss); 2603 } 2604 2605 return ss; 2606 } 2607 2608 public StopwatchTimer getWakeTimerLocked(String name, int type) { 2609 Wakelock wl = mWakelockStats.get(name); 2610 if (wl == null) { 2611 if (mWakelockStats.size() > MAX_WAKELOCKS_PER_UID) { 2612 name = BATCHED_WAKELOCK_NAME; 2613 wl = mWakelockStats.get(name); 2614 } 2615 if (wl == null) { 2616 wl = new Wakelock(); 2617 mWakelockStats.put(name, wl); 2618 } 2619 } 2620 StopwatchTimer t = null; 2621 switch (type) { 2622 case WAKE_TYPE_PARTIAL: 2623 t = wl.mTimerPartial; 2624 if (t == null) { 2625 t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables); 2626 wl.mTimerPartial = t; 2627 } 2628 return t; 2629 case WAKE_TYPE_FULL: 2630 t = wl.mTimerFull; 2631 if (t == null) { 2632 t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables); 2633 wl.mTimerFull = t; 2634 } 2635 return t; 2636 case WAKE_TYPE_WINDOW: 2637 t = wl.mTimerWindow; 2638 if (t == null) { 2639 t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables); 2640 wl.mTimerWindow = t; 2641 } 2642 return t; 2643 default: 2644 throw new IllegalArgumentException("type=" + type); 2645 } 2646 } 2647 2648 public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) { 2649 Sensor se = mSensorStats.get(sensor); 2650 if (se == null) { 2651 if (!create) { 2652 return null; 2653 } 2654 se = new Sensor(sensor); 2655 mSensorStats.put(sensor, se); 2656 } 2657 StopwatchTimer t = se.mTimer; 2658 if (t != null) { 2659 return t; 2660 } 2661 ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor); 2662 if (timers == null) { 2663 timers = new ArrayList<StopwatchTimer>(); 2664 mSensorTimers.put(sensor, timers); 2665 } 2666 t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables); 2667 se.mTimer = t; 2668 return t; 2669 } 2670 2671 public void noteStartWakeLocked(String name, int type) { 2672 StopwatchTimer t = getWakeTimerLocked(name, type); 2673 if (t != null) { 2674 t.startRunningLocked(BatteryStatsImpl.this); 2675 } 2676 } 2677 2678 public void noteStopWakeLocked(String name, int type) { 2679 StopwatchTimer t = getWakeTimerLocked(name, type); 2680 if (t != null) { 2681 t.stopRunningLocked(BatteryStatsImpl.this); 2682 } 2683 } 2684 2685 public void noteStartSensor(int sensor) { 2686 StopwatchTimer t = getSensorTimerLocked(sensor, true); 2687 if (t != null) { 2688 t.startRunningLocked(BatteryStatsImpl.this); 2689 } 2690 } 2691 2692 public void noteStopSensor(int sensor) { 2693 // Don't create a timer if one doesn't already exist 2694 StopwatchTimer t = getSensorTimerLocked(sensor, false); 2695 if (t != null) { 2696 t.stopRunningLocked(BatteryStatsImpl.this); 2697 } 2698 } 2699 2700 public void noteStartGps() { 2701 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true); 2702 if (t != null) { 2703 t.startRunningLocked(BatteryStatsImpl.this); 2704 } 2705 } 2706 2707 public void noteStopGps() { 2708 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false); 2709 if (t != null) { 2710 t.stopRunningLocked(BatteryStatsImpl.this); 2711 } 2712 } 2713 2714 public BatteryStatsImpl getBatteryStats() { 2715 return BatteryStatsImpl.this; 2716 } 2717 } 2718 2719 public BatteryStatsImpl(String filename) { 2720 mFile = new JournaledFile(new File(filename), new File(filename + ".tmp")); 2721 mStartCount++; 2722 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables); 2723 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 2724 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables); 2725 } 2726 mInputEventCounter = new Counter(mUnpluggables); 2727 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables); 2728 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 2729 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables); 2730 } 2731 mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables); 2732 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 2733 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables); 2734 } 2735 mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables); 2736 mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables); 2737 mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables); 2738 mAudioOnTimer = new StopwatchTimer(-6, null, mUnpluggables); 2739 mOnBattery = mOnBatteryInternal = false; 2740 mTrackBatteryPastUptime = 0; 2741 mTrackBatteryPastRealtime = 0; 2742 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; 2743 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; 2744 mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); 2745 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); 2746 mDischargeStartLevel = 0; 2747 mDischargeCurrentLevel = 0; 2748 } 2749 2750 public BatteryStatsImpl(Parcel p) { 2751 mFile = null; 2752 readFromParcel(p); 2753 } 2754 2755 public void setNumSpeedSteps(int steps) { 2756 if (sNumSpeedSteps == 0) sNumSpeedSteps = steps; 2757 } 2758 2759 public void setRadioScanningTimeout(long timeout) { 2760 if (mPhoneSignalScanningTimer != null) { 2761 mPhoneSignalScanningTimer.setTimeout(timeout); 2762 } 2763 } 2764 2765 @Override 2766 public int getStartCount() { 2767 return mStartCount; 2768 } 2769 2770 public boolean isOnBattery() { 2771 return mOnBattery; 2772 } 2773 2774 public void setOnBattery(boolean onBattery, int level) { 2775 synchronized(this) { 2776 updateKernelWakelocksLocked(); 2777 if (mOnBattery != onBattery) { 2778 mOnBattery = mOnBatteryInternal = onBattery; 2779 2780 long uptime = SystemClock.uptimeMillis() * 1000; 2781 long mSecRealtime = SystemClock.elapsedRealtime(); 2782 long realtime = mSecRealtime * 1000; 2783 if (onBattery) { 2784 mTrackBatteryUptimeStart = uptime; 2785 mTrackBatteryRealtimeStart = realtime; 2786 mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); 2787 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); 2788 mDischargeCurrentLevel = mDischargeStartLevel = level; 2789 doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); 2790 } else { 2791 mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; 2792 mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; 2793 mDischargeCurrentLevel = level; 2794 doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); 2795 } 2796 if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) { 2797 if (mFile != null) { 2798 writeLocked(); 2799 } 2800 } 2801 } 2802 } 2803 } 2804 2805 public void recordCurrentLevel(int level) { 2806 mDischargeCurrentLevel = level; 2807 } 2808 2809 public void updateKernelWakelocksLocked() { 2810 Map<String, KernelWakelockStats> m = readKernelWakelockStats(); 2811 2812 if (m == null) { 2813 // Not crashing might make board bringup easier. 2814 Slog.w(TAG, "Couldn't get kernel wake lock stats"); 2815 return; 2816 } 2817 2818 for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) { 2819 String name = ent.getKey(); 2820 KernelWakelockStats kws = ent.getValue(); 2821 2822 SamplingTimer kwlt = mKernelWakelockStats.get(name); 2823 if (kwlt == null) { 2824 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 2825 true /* track reported values */); 2826 mKernelWakelockStats.put(name, kwlt); 2827 } 2828 kwlt.updateCurrentReportedCount(kws.mCount); 2829 kwlt.updateCurrentReportedTotalTime(kws.mTotalTime); 2830 kwlt.setUpdateVersion(sKernelWakelockUpdateVersion); 2831 } 2832 2833 if (m.size() != mKernelWakelockStats.size()) { 2834 // Set timers to stale if they didn't appear in /proc/wakelocks this time. 2835 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 2836 SamplingTimer st = ent.getValue(); 2837 if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) { 2838 st.setStale(); 2839 } 2840 } 2841 } 2842 } 2843 2844 public long getAwakeTimeBattery() { 2845 return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT); 2846 } 2847 2848 public long getAwakeTimePlugged() { 2849 return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery(); 2850 } 2851 2852 @Override 2853 public long computeUptime(long curTime, int which) { 2854 switch (which) { 2855 case STATS_TOTAL: return mUptime + (curTime-mUptimeStart); 2856 case STATS_LAST: return mLastUptime; 2857 case STATS_CURRENT: return (curTime-mUptimeStart); 2858 case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart); 2859 } 2860 return 0; 2861 } 2862 2863 @Override 2864 public long computeRealtime(long curTime, int which) { 2865 switch (which) { 2866 case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart); 2867 case STATS_LAST: return mLastRealtime; 2868 case STATS_CURRENT: return (curTime-mRealtimeStart); 2869 case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart); 2870 } 2871 return 0; 2872 } 2873 2874 @Override 2875 public long computeBatteryUptime(long curTime, int which) { 2876 switch (which) { 2877 case STATS_TOTAL: 2878 return mBatteryUptime + getBatteryUptime(curTime); 2879 case STATS_LAST: 2880 return mBatteryLastUptime; 2881 case STATS_CURRENT: 2882 return getBatteryUptime(curTime); 2883 case STATS_UNPLUGGED: 2884 return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime; 2885 } 2886 return 0; 2887 } 2888 2889 @Override 2890 public long computeBatteryRealtime(long curTime, int which) { 2891 switch (which) { 2892 case STATS_TOTAL: 2893 return mBatteryRealtime + getBatteryRealtimeLocked(curTime); 2894 case STATS_LAST: 2895 return mBatteryLastRealtime; 2896 case STATS_CURRENT: 2897 return getBatteryRealtimeLocked(curTime); 2898 case STATS_UNPLUGGED: 2899 return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime; 2900 } 2901 return 0; 2902 } 2903 2904 long getBatteryUptimeLocked(long curTime) { 2905 long time = mTrackBatteryPastUptime; 2906 if (mOnBatteryInternal) { 2907 time += curTime - mTrackBatteryUptimeStart; 2908 } 2909 return time; 2910 } 2911 2912 long getBatteryUptimeLocked() { 2913 return getBatteryUptime(SystemClock.uptimeMillis() * 1000); 2914 } 2915 2916 @Override 2917 public long getBatteryUptime(long curTime) { 2918 return getBatteryUptimeLocked(curTime); 2919 } 2920 2921 long getBatteryRealtimeLocked(long curTime) { 2922 long time = mTrackBatteryPastRealtime; 2923 if (mOnBatteryInternal) { 2924 time += curTime - mTrackBatteryRealtimeStart; 2925 } 2926 return time; 2927 } 2928 2929 @Override 2930 public long getBatteryRealtime(long curTime) { 2931 return getBatteryRealtimeLocked(curTime); 2932 } 2933 2934 private long getTcpBytes(long current, long[] dataBytes, int which) { 2935 if (which == STATS_LAST) { 2936 return dataBytes[STATS_LAST]; 2937 } else { 2938 if (which == STATS_UNPLUGGED) { 2939 if (dataBytes[STATS_UNPLUGGED] < 0) { 2940 return dataBytes[STATS_LAST]; 2941 } else { 2942 return current - dataBytes[STATS_UNPLUGGED]; 2943 } 2944 } else if (which == STATS_TOTAL) { 2945 return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_TOTAL]; 2946 } 2947 return current - dataBytes[STATS_CURRENT]; 2948 } 2949 } 2950 2951 /** Only STATS_UNPLUGGED works properly */ 2952 public long getMobileTcpBytesSent(int which) { 2953 return getTcpBytes(TrafficStats.getMobileTxBytes(), mMobileDataTx, which); 2954 } 2955 2956 /** Only STATS_UNPLUGGED works properly */ 2957 public long getMobileTcpBytesReceived(int which) { 2958 return getTcpBytes(TrafficStats.getMobileRxBytes(), mMobileDataRx, which); 2959 } 2960 2961 /** Only STATS_UNPLUGGED works properly */ 2962 public long getTotalTcpBytesSent(int which) { 2963 return getTcpBytes(TrafficStats.getTotalTxBytes(), mTotalDataTx, which); 2964 } 2965 2966 /** Only STATS_UNPLUGGED works properly */ 2967 public long getTotalTcpBytesReceived(int which) { 2968 return getTcpBytes(TrafficStats.getTotalRxBytes(), mTotalDataRx, which); 2969 } 2970 2971 @Override 2972 public int getDischargeStartLevel() { 2973 synchronized(this) { 2974 return getDischargeStartLevelLocked(); 2975 } 2976 } 2977 2978 public int getDischargeStartLevelLocked() { 2979 return mDischargeStartLevel; 2980 } 2981 2982 @Override 2983 public int getDischargeCurrentLevel() { 2984 synchronized(this) { 2985 return getDischargeCurrentLevelLocked(); 2986 } 2987 } 2988 2989 public int getDischargeCurrentLevelLocked() { 2990 return mDischargeCurrentLevel; 2991 } 2992 2993 @Override 2994 public int getCpuSpeedSteps() { 2995 return sNumSpeedSteps; 2996 } 2997 2998 /** 2999 * Retrieve the statistics object for a particular uid, creating if needed. 3000 */ 3001 public Uid getUidStatsLocked(int uid) { 3002 Uid u = mUidStats.get(uid); 3003 if (u == null) { 3004 u = new Uid(uid); 3005 mUidStats.put(uid, u); 3006 } 3007 return u; 3008 } 3009 3010 /** 3011 * Remove the statistics object for a particular uid. 3012 */ 3013 public void removeUidStatsLocked(int uid) { 3014 mUidStats.remove(uid); 3015 } 3016 3017 /** 3018 * Retrieve the statistics object for a particular process, creating 3019 * if needed. 3020 */ 3021 public Uid.Proc getProcessStatsLocked(int uid, String name) { 3022 Uid u = getUidStatsLocked(uid); 3023 return u.getProcessStatsLocked(name); 3024 } 3025 3026 /** 3027 * Retrieve the statistics object for a particular process, given 3028 * the name of the process. 3029 * @param name process name 3030 * @return the statistics object for the process 3031 */ 3032 public Uid.Proc getProcessStatsLocked(String name, int pid) { 3033 int uid; 3034 if (mUidCache.containsKey(name)) { 3035 uid = mUidCache.get(name); 3036 } else { 3037 uid = Process.getUidForPid(pid); 3038 mUidCache.put(name, uid); 3039 } 3040 Uid u = getUidStatsLocked(uid); 3041 return u.getProcessStatsLocked(name); 3042 } 3043 3044 /** 3045 * Retrieve the statistics object for a particular process, creating 3046 * if needed. 3047 */ 3048 public Uid.Pkg getPackageStatsLocked(int uid, String pkg) { 3049 Uid u = getUidStatsLocked(uid); 3050 return u.getPackageStatsLocked(pkg); 3051 } 3052 3053 /** 3054 * Retrieve the statistics object for a particular service, creating 3055 * if needed. 3056 */ 3057 public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) { 3058 Uid u = getUidStatsLocked(uid); 3059 return u.getServiceStatsLocked(pkg, name); 3060 } 3061 3062 private static JournaledFile makeJournaledFile() { 3063 final String base = "/data/system/device_policies.xml"; 3064 return new JournaledFile(new File(base), new File(base + ".tmp")); 3065 } 3066 3067 public void writeLocked() { 3068 if (mFile == null) { 3069 Slog.w("BatteryStats", "writeLocked: no file associated with this instance"); 3070 return; 3071 } 3072 3073 try { 3074 FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite()); 3075 Parcel out = Parcel.obtain(); 3076 writeSummaryToParcel(out); 3077 stream.write(out.marshall()); 3078 out.recycle(); 3079 3080 stream.flush(); 3081 stream.close(); 3082 mFile.commit(); 3083 3084 mLastWriteTime = SystemClock.elapsedRealtime(); 3085 return; 3086 } catch (IOException e) { 3087 Slog.w("BatteryStats", "Error writing battery statistics", e); 3088 } 3089 mFile.rollback(); 3090 } 3091 3092 static byte[] readFully(FileInputStream stream) throws java.io.IOException { 3093 int pos = 0; 3094 int avail = stream.available(); 3095 byte[] data = new byte[avail]; 3096 while (true) { 3097 int amt = stream.read(data, pos, data.length-pos); 3098 //Log.i("foo", "Read " + amt + " bytes at " + pos 3099 // + " of avail " + data.length); 3100 if (amt <= 0) { 3101 //Log.i("foo", "**** FINISHED READING: pos=" + pos 3102 // + " len=" + data.length); 3103 return data; 3104 } 3105 pos += amt; 3106 avail = stream.available(); 3107 if (avail > data.length-pos) { 3108 byte[] newData = new byte[pos+avail]; 3109 System.arraycopy(data, 0, newData, 0, pos); 3110 data = newData; 3111 } 3112 } 3113 } 3114 3115 public void readLocked() { 3116 if (mFile == null) { 3117 Slog.w("BatteryStats", "readLocked: no file associated with this instance"); 3118 return; 3119 } 3120 3121 mUidStats.clear(); 3122 3123 try { 3124 File file = mFile.chooseForRead(); 3125 if (!file.exists()) { 3126 return; 3127 } 3128 FileInputStream stream = new FileInputStream(file); 3129 3130 byte[] raw = readFully(stream); 3131 Parcel in = Parcel.obtain(); 3132 in.unmarshall(raw, 0, raw.length); 3133 in.setDataPosition(0); 3134 stream.close(); 3135 3136 readSummaryFromParcel(in); 3137 } catch(java.io.IOException e) { 3138 Slog.e("BatteryStats", "Error reading battery statistics", e); 3139 } 3140 } 3141 3142 public int describeContents() { 3143 return 0; 3144 } 3145 3146 private void readSummaryFromParcel(Parcel in) { 3147 final int version = in.readInt(); 3148 if (version != VERSION) { 3149 Slog.w("BatteryStats", "readFromParcel: version got " + version 3150 + ", expected " + VERSION + "; erasing old stats"); 3151 return; 3152 } 3153 3154 mStartCount = in.readInt(); 3155 mBatteryUptime = in.readLong(); 3156 mBatteryLastUptime = in.readLong(); 3157 mBatteryRealtime = in.readLong(); 3158 mBatteryLastRealtime = in.readLong(); 3159 mUptime = in.readLong(); 3160 mLastUptime = in.readLong(); 3161 mRealtime = in.readLong(); 3162 mLastRealtime = in.readLong(); 3163 mDischargeStartLevel = in.readInt(); 3164 mDischargeCurrentLevel = in.readInt(); 3165 3166 mStartCount++; 3167 3168 mScreenOn = false; 3169 mScreenOnTimer.readSummaryFromParcelLocked(in); 3170 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3171 mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in); 3172 } 3173 mInputEventCounter.readSummaryFromParcelLocked(in); 3174 mPhoneOn = false; 3175 mPhoneOnTimer.readSummaryFromParcelLocked(in); 3176 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3177 mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in); 3178 } 3179 mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in); 3180 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3181 mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in); 3182 } 3183 mWifiOn = false; 3184 mWifiOnTimer.readSummaryFromParcelLocked(in); 3185 mWifiRunning = false; 3186 mWifiRunningTimer.readSummaryFromParcelLocked(in); 3187 mBluetoothOn = false; 3188 mBluetoothOnTimer.readSummaryFromParcelLocked(in); 3189 3190 int NKW = in.readInt(); 3191 if (NKW > 10000) { 3192 Slog.w(TAG, "File corrupt: too many kernel wake locks " + NKW); 3193 return; 3194 } 3195 for (int ikw = 0; ikw < NKW; ikw++) { 3196 if (in.readInt() != 0) { 3197 String kwltName = in.readString(); 3198 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in); 3199 } 3200 } 3201 3202 sNumSpeedSteps = in.readInt(); 3203 3204 final int NU = in.readInt(); 3205 if (NU > 10000) { 3206 Slog.w(TAG, "File corrupt: too many uids " + NU); 3207 return; 3208 } 3209 for (int iu = 0; iu < NU; iu++) { 3210 int uid = in.readInt(); 3211 Uid u = new Uid(uid); 3212 mUidStats.put(uid, u); 3213 3214 u.mWifiTurnedOn = false; 3215 u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in); 3216 u.mFullWifiLockOut = false; 3217 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); 3218 u.mAudioTurnedOn = false; 3219 u.mAudioTurnedOnTimer.readSummaryFromParcelLocked(in); 3220 u.mVideoTurnedOn = false; 3221 u.mVideoTurnedOnTimer.readSummaryFromParcelLocked(in); 3222 u.mScanWifiLockOut = false; 3223 u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); 3224 u.mWifiMulticastEnabled = false; 3225 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in); 3226 3227 if (in.readInt() != 0) { 3228 if (u.mUserActivityCounters == null) { 3229 u.initUserActivityLocked(); 3230 } 3231 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 3232 u.mUserActivityCounters[i].readSummaryFromParcelLocked(in); 3233 } 3234 } 3235 3236 int NW = in.readInt(); 3237 if (NW > 10000) { 3238 Slog.w(TAG, "File corrupt: too many wake locks " + NW); 3239 return; 3240 } 3241 for (int iw = 0; iw < NW; iw++) { 3242 String wlName = in.readString(); 3243 if (in.readInt() != 0) { 3244 u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in); 3245 } 3246 if (in.readInt() != 0) { 3247 u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in); 3248 } 3249 if (in.readInt() != 0) { 3250 u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in); 3251 } 3252 } 3253 3254 int NP = in.readInt(); 3255 if (NP > 10000) { 3256 Slog.w(TAG, "File corrupt: too many sensors " + NP); 3257 return; 3258 } 3259 for (int is = 0; is < NP; is++) { 3260 int seNumber = in.readInt(); 3261 if (in.readInt() != 0) { 3262 u.getSensorTimerLocked(seNumber, true) 3263 .readSummaryFromParcelLocked(in); 3264 } 3265 } 3266 3267 NP = in.readInt(); 3268 if (NP > 10000) { 3269 Slog.w(TAG, "File corrupt: too many processes " + NP); 3270 return; 3271 } 3272 for (int ip = 0; ip < NP; ip++) { 3273 String procName = in.readString(); 3274 Uid.Proc p = u.getProcessStatsLocked(procName); 3275 p.mUserTime = p.mLoadedUserTime = in.readLong(); 3276 p.mLastUserTime = in.readLong(); 3277 p.mSystemTime = p.mLoadedSystemTime = in.readLong(); 3278 p.mLastSystemTime = in.readLong(); 3279 p.mStarts = p.mLoadedStarts = in.readInt(); 3280 p.mLastStarts = in.readInt(); 3281 } 3282 3283 NP = in.readInt(); 3284 if (NP > 10000) { 3285 Slog.w(TAG, "File corrupt: too many packages " + NP); 3286 return; 3287 } 3288 for (int ip = 0; ip < NP; ip++) { 3289 String pkgName = in.readString(); 3290 Uid.Pkg p = u.getPackageStatsLocked(pkgName); 3291 p.mWakeups = p.mLoadedWakeups = in.readInt(); 3292 p.mLastWakeups = in.readInt(); 3293 final int NS = in.readInt(); 3294 for (int is = 0; is < NS; is++) { 3295 String servName = in.readString(); 3296 Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName); 3297 s.mStartTime = s.mLoadedStartTime = in.readLong(); 3298 s.mLastStartTime = in.readLong(); 3299 s.mStarts = s.mLoadedStarts = in.readInt(); 3300 s.mLastStarts = in.readInt(); 3301 s.mLaunches = s.mLoadedLaunches = in.readInt(); 3302 s.mLastLaunches = in.readInt(); 3303 } 3304 } 3305 3306 u.mLoadedTcpBytesReceived = in.readLong(); 3307 u.mLoadedTcpBytesSent = in.readLong(); 3308 } 3309 } 3310 3311 /** 3312 * Writes a summary of the statistics to a Parcel, in a format suitable to be written to 3313 * disk. This format does not allow a lossless round-trip. 3314 * 3315 * @param out the Parcel to be written to. 3316 */ 3317 public void writeSummaryToParcel(Parcel out) { 3318 final long NOW_SYS = SystemClock.uptimeMillis() * 1000; 3319 final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; 3320 final long NOW = getBatteryUptimeLocked(NOW_SYS); 3321 final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS); 3322 3323 out.writeInt(VERSION); 3324 3325 out.writeInt(mStartCount); 3326 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_TOTAL)); 3327 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT)); 3328 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_TOTAL)); 3329 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT)); 3330 out.writeLong(computeUptime(NOW_SYS, STATS_TOTAL)); 3331 out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT)); 3332 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL)); 3333 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT)); 3334 out.writeInt(mDischargeStartLevel); 3335 out.writeInt(mDischargeCurrentLevel); 3336 3337 3338 mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3339 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3340 mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 3341 } 3342 mInputEventCounter.writeSummaryFromParcelLocked(out); 3343 mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3344 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3345 mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 3346 } 3347 mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3348 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3349 mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 3350 } 3351 mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3352 mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3353 mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3354 3355 out.writeInt(mKernelWakelockStats.size()); 3356 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 3357 Timer kwlt = ent.getValue(); 3358 if (kwlt != null) { 3359 out.writeInt(1); 3360 out.writeString(ent.getKey()); 3361 ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL); 3362 } else { 3363 out.writeInt(0); 3364 } 3365 } 3366 3367 out.writeInt(sNumSpeedSteps); 3368 final int NU = mUidStats.size(); 3369 out.writeInt(NU); 3370 for (int iu = 0; iu < NU; iu++) { 3371 out.writeInt(mUidStats.keyAt(iu)); 3372 Uid u = mUidStats.valueAt(iu); 3373 3374 u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3375 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3376 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3377 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3378 u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3379 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3380 3381 if (u.mUserActivityCounters == null) { 3382 out.writeInt(0); 3383 } else { 3384 out.writeInt(1); 3385 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 3386 u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out); 3387 } 3388 } 3389 3390 int NW = u.mWakelockStats.size(); 3391 out.writeInt(NW); 3392 if (NW > 0) { 3393 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent 3394 : u.mWakelockStats.entrySet()) { 3395 out.writeString(ent.getKey()); 3396 Uid.Wakelock wl = ent.getValue(); 3397 if (wl.mTimerFull != null) { 3398 out.writeInt(1); 3399 wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL); 3400 } else { 3401 out.writeInt(0); 3402 } 3403 if (wl.mTimerPartial != null) { 3404 out.writeInt(1); 3405 wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL); 3406 } else { 3407 out.writeInt(0); 3408 } 3409 if (wl.mTimerWindow != null) { 3410 out.writeInt(1); 3411 wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL); 3412 } else { 3413 out.writeInt(0); 3414 } 3415 } 3416 } 3417 3418 int NSE = u.mSensorStats.size(); 3419 out.writeInt(NSE); 3420 if (NSE > 0) { 3421 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent 3422 : u.mSensorStats.entrySet()) { 3423 out.writeInt(ent.getKey()); 3424 Uid.Sensor se = ent.getValue(); 3425 if (se.mTimer != null) { 3426 out.writeInt(1); 3427 se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3428 } else { 3429 out.writeInt(0); 3430 } 3431 } 3432 } 3433 3434 int NP = u.mProcessStats.size(); 3435 out.writeInt(NP); 3436 if (NP > 0) { 3437 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent 3438 : u.mProcessStats.entrySet()) { 3439 out.writeString(ent.getKey()); 3440 Uid.Proc ps = ent.getValue(); 3441 out.writeLong(ps.mUserTime); 3442 out.writeLong(ps.mUserTime - ps.mLoadedUserTime); 3443 out.writeLong(ps.mSystemTime); 3444 out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime); 3445 out.writeInt(ps.mStarts); 3446 out.writeInt(ps.mStarts - ps.mLoadedStarts); 3447 } 3448 } 3449 3450 NP = u.mPackageStats.size(); 3451 out.writeInt(NP); 3452 if (NP > 0) { 3453 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent 3454 : u.mPackageStats.entrySet()) { 3455 out.writeString(ent.getKey()); 3456 Uid.Pkg ps = ent.getValue(); 3457 out.writeInt(ps.mWakeups); 3458 out.writeInt(ps.mWakeups - ps.mLoadedWakeups); 3459 final int NS = ps.mServiceStats.size(); 3460 out.writeInt(NS); 3461 if (NS > 0) { 3462 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent 3463 : ps.mServiceStats.entrySet()) { 3464 out.writeString(sent.getKey()); 3465 BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue(); 3466 long time = ss.getStartTimeToNowLocked(NOW); 3467 out.writeLong(time); 3468 out.writeLong(time - ss.mLoadedStartTime); 3469 out.writeInt(ss.mStarts); 3470 out.writeInt(ss.mStarts - ss.mLoadedStarts); 3471 out.writeInt(ss.mLaunches); 3472 out.writeInt(ss.mLaunches - ss.mLoadedLaunches); 3473 } 3474 } 3475 } 3476 } 3477 3478 out.writeLong(u.getTcpBytesReceived(STATS_TOTAL)); 3479 out.writeLong(u.getTcpBytesSent(STATS_TOTAL)); 3480 } 3481 } 3482 3483 public void readFromParcel(Parcel in) { 3484 readFromParcelLocked(in); 3485 } 3486 3487 void readFromParcelLocked(Parcel in) { 3488 int magic = in.readInt(); 3489 if (magic != MAGIC) { 3490 throw new ParcelFormatException("Bad magic number"); 3491 } 3492 3493 mStartCount = in.readInt(); 3494 mBatteryUptime = in.readLong(); 3495 mBatteryLastUptime = in.readLong(); 3496 mBatteryRealtime = in.readLong(); 3497 mBatteryLastRealtime = in.readLong(); 3498 mScreenOn = false; 3499 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in); 3500 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3501 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in); 3502 } 3503 mInputEventCounter = new Counter(mUnpluggables, in); 3504 mPhoneOn = false; 3505 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3506 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3507 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in); 3508 } 3509 mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables, in); 3510 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3511 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in); 3512 } 3513 mWifiOn = false; 3514 mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3515 mWifiRunning = false; 3516 mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3517 mBluetoothOn = false; 3518 mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3519 mUptime = in.readLong(); 3520 mUptimeStart = in.readLong(); 3521 mLastUptime = in.readLong(); 3522 mRealtime = in.readLong(); 3523 mRealtimeStart = in.readLong(); 3524 mLastRealtime = in.readLong(); 3525 mOnBattery = in.readInt() != 0; 3526 mOnBatteryInternal = false; // we are no longer really running. 3527 mTrackBatteryPastUptime = in.readLong(); 3528 mTrackBatteryUptimeStart = in.readLong(); 3529 mTrackBatteryPastRealtime = in.readLong(); 3530 mTrackBatteryRealtimeStart = in.readLong(); 3531 mUnpluggedBatteryUptime = in.readLong(); 3532 mUnpluggedBatteryRealtime = in.readLong(); 3533 mDischargeStartLevel = in.readInt(); 3534 mDischargeCurrentLevel = in.readInt(); 3535 mLastWriteTime = in.readLong(); 3536 3537 mMobileDataRx[STATS_LAST] = in.readLong(); 3538 mMobileDataRx[STATS_UNPLUGGED] = -1; 3539 mMobileDataTx[STATS_LAST] = in.readLong(); 3540 mMobileDataTx[STATS_UNPLUGGED] = -1; 3541 mTotalDataRx[STATS_LAST] = in.readLong(); 3542 mTotalDataRx[STATS_UNPLUGGED] = -1; 3543 mTotalDataTx[STATS_LAST] = in.readLong(); 3544 mTotalDataTx[STATS_UNPLUGGED] = -1; 3545 3546 mRadioDataUptime = in.readLong(); 3547 mRadioDataStart = -1; 3548 3549 mBluetoothPingCount = in.readInt(); 3550 mBluetoothPingStart = -1; 3551 3552 mKernelWakelockStats.clear(); 3553 int NKW = in.readInt(); 3554 for (int ikw = 0; ikw < NKW; ikw++) { 3555 if (in.readInt() != 0) { 3556 String wakelockName = in.readString(); 3557 in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel 3558 SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in); 3559 mKernelWakelockStats.put(wakelockName, kwlt); 3560 } 3561 } 3562 3563 mPartialTimers.clear(); 3564 mFullTimers.clear(); 3565 mWindowTimers.clear(); 3566 3567 sNumSpeedSteps = in.readInt(); 3568 3569 int numUids = in.readInt(); 3570 mUidStats.clear(); 3571 for (int i = 0; i < numUids; i++) { 3572 int uid = in.readInt(); 3573 Uid u = new Uid(uid); 3574 u.readFromParcelLocked(mUnpluggables, in); 3575 mUidStats.append(uid, u); 3576 } 3577 } 3578 3579 public void writeToParcel(Parcel out, int flags) { 3580 writeToParcelLocked(out, flags); 3581 } 3582 3583 @SuppressWarnings("unused") 3584 void writeToParcelLocked(Parcel out, int flags) { 3585 final long uSecUptime = SystemClock.uptimeMillis() * 1000; 3586 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 3587 final long batteryUptime = getBatteryUptimeLocked(uSecUptime); 3588 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 3589 3590 out.writeInt(MAGIC); 3591 out.writeInt(mStartCount); 3592 out.writeLong(mBatteryUptime); 3593 out.writeLong(mBatteryLastUptime); 3594 out.writeLong(mBatteryRealtime); 3595 out.writeLong(mBatteryLastRealtime); 3596 mScreenOnTimer.writeToParcel(out, batteryRealtime); 3597 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3598 mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime); 3599 } 3600 mInputEventCounter.writeToParcel(out); 3601 mPhoneOnTimer.writeToParcel(out, batteryRealtime); 3602 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3603 mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime); 3604 } 3605 mPhoneSignalScanningTimer.writeToParcel(out, batteryRealtime); 3606 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3607 mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime); 3608 } 3609 mWifiOnTimer.writeToParcel(out, batteryRealtime); 3610 mWifiRunningTimer.writeToParcel(out, batteryRealtime); 3611 mBluetoothOnTimer.writeToParcel(out, batteryRealtime); 3612 out.writeLong(mUptime); 3613 out.writeLong(mUptimeStart); 3614 out.writeLong(mLastUptime); 3615 out.writeLong(mRealtime); 3616 out.writeLong(mRealtimeStart); 3617 out.writeLong(mLastRealtime); 3618 out.writeInt(mOnBattery ? 1 : 0); 3619 out.writeLong(batteryUptime); 3620 out.writeLong(mTrackBatteryUptimeStart); 3621 out.writeLong(batteryRealtime); 3622 out.writeLong(mTrackBatteryRealtimeStart); 3623 out.writeLong(mUnpluggedBatteryUptime); 3624 out.writeLong(mUnpluggedBatteryRealtime); 3625 out.writeInt(mDischargeStartLevel); 3626 out.writeInt(mDischargeCurrentLevel); 3627 out.writeLong(mLastWriteTime); 3628 3629 out.writeLong(getMobileTcpBytesReceived(STATS_UNPLUGGED)); 3630 out.writeLong(getMobileTcpBytesSent(STATS_UNPLUGGED)); 3631 out.writeLong(getTotalTcpBytesReceived(STATS_UNPLUGGED)); 3632 out.writeLong(getTotalTcpBytesSent(STATS_UNPLUGGED)); 3633 3634 // Write radio uptime for data 3635 out.writeLong(getRadioDataUptime()); 3636 3637 out.writeInt(getBluetoothPingCount()); 3638 3639 out.writeInt(mKernelWakelockStats.size()); 3640 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 3641 SamplingTimer kwlt = ent.getValue(); 3642 if (kwlt != null) { 3643 out.writeInt(1); 3644 out.writeString(ent.getKey()); 3645 Timer.writeTimerToParcel(out, kwlt, batteryRealtime); 3646 } else { 3647 out.writeInt(0); 3648 } 3649 } 3650 3651 out.writeInt(sNumSpeedSteps); 3652 3653 int size = mUidStats.size(); 3654 out.writeInt(size); 3655 for (int i = 0; i < size; i++) { 3656 out.writeInt(mUidStats.keyAt(i)); 3657 Uid uid = mUidStats.valueAt(i); 3658 3659 uid.writeToParcelLocked(out, batteryRealtime); 3660 } 3661 } 3662 3663 public static final Parcelable.Creator<BatteryStatsImpl> CREATOR = 3664 new Parcelable.Creator<BatteryStatsImpl>() { 3665 public BatteryStatsImpl createFromParcel(Parcel in) { 3666 return new BatteryStatsImpl(in); 3667 } 3668 3669 public BatteryStatsImpl[] newArray(int size) { 3670 return new BatteryStatsImpl[size]; 3671 } 3672 }; 3673 3674 public void dumpLocked(PrintWriter pw) { 3675 if (DEBUG) { 3676 Printer pr = new PrintWriterPrinter(pw); 3677 pr.println("*** Screen timer:"); 3678 mScreenOnTimer.logState(pr, " "); 3679 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3680 pr.println("*** Screen brightness #" + i + ":"); 3681 mScreenBrightnessTimer[i].logState(pr, " "); 3682 } 3683 pr.println("*** Input event counter:"); 3684 mInputEventCounter.logState(pr, " "); 3685 pr.println("*** Phone timer:"); 3686 mPhoneOnTimer.logState(pr, " "); 3687 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3688 pr.println("*** Signal strength #" + i + ":"); 3689 mPhoneSignalStrengthsTimer[i].logState(pr, " "); 3690 } 3691 pr.println("*** Signal scanning :"); 3692 mPhoneSignalScanningTimer.logState(pr, " "); 3693 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3694 pr.println("*** Data connection type #" + i + ":"); 3695 mPhoneDataConnectionsTimer[i].logState(pr, " "); 3696 } 3697 pr.println("*** Wifi timer:"); 3698 mWifiOnTimer.logState(pr, " "); 3699 pr.println("*** WifiRunning timer:"); 3700 mWifiRunningTimer.logState(pr, " "); 3701 pr.println("*** Bluetooth timer:"); 3702 mBluetoothOnTimer.logState(pr, " "); 3703 } 3704 super.dumpLocked(pw); 3705 } 3706} 3707