BatteryStatsImpl.java revision b5e3165129a5871cf679a67d9e9323ffad3d4902
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.BatteryManager; 24import android.os.BatteryStats; 25import android.os.Parcel; 26import android.os.ParcelFormatException; 27import android.os.Parcelable; 28import android.os.Process; 29import android.os.SystemClock; 30import android.telephony.ServiceState; 31import android.telephony.SignalStrength; 32import android.telephony.TelephonyManager; 33import android.util.Log; 34import android.util.PrintWriterPrinter; 35import android.util.Printer; 36import android.util.Slog; 37import android.util.SparseArray; 38 39import java.io.BufferedReader; 40import java.io.File; 41import java.io.FileInputStream; 42import java.io.FileOutputStream; 43import java.io.FileReader; 44import java.io.IOException; 45import java.io.PrintWriter; 46import java.util.ArrayList; 47import java.util.HashMap; 48import java.util.Iterator; 49import java.util.Map; 50import java.util.concurrent.atomic.AtomicInteger; 51 52/** 53 * All information we are collecting about things that can happen that impact 54 * battery life. All times are represented in microseconds except where indicated 55 * otherwise. 56 */ 57public final class BatteryStatsImpl extends BatteryStats { 58 private static final String TAG = "BatteryStatsImpl"; 59 private static final boolean DEBUG = false; 60 private static final boolean DEBUG_HISTORY = false; 61 62 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data 63 private static final int MAGIC = 0xBA757475; // 'BATSTATS' 64 65 // Current on-disk Parcel version 66 private static final int VERSION = 50; 67 68 // Maximum number of items we will record in the history. 69 private static final int MAX_HISTORY_ITEMS = 1000; 70 71 // The maximum number of names wakelocks we will keep track of 72 // per uid; once the limit is reached, we batch the remaining wakelocks 73 // in to one common name. 74 private static final int MAX_WAKELOCKS_PER_UID = 20; 75 76 private static final String BATCHED_WAKELOCK_NAME = "*overflow*"; 77 78 private static int sNumSpeedSteps; 79 80 private final JournaledFile mFile; 81 82 /** 83 * The statistics we have collected organized by uids. 84 */ 85 final SparseArray<BatteryStatsImpl.Uid> mUidStats = 86 new SparseArray<BatteryStatsImpl.Uid>(); 87 88 // A set of pools of currently active timers. When a timer is queried, we will divide the 89 // elapsed time by the number of active timers to arrive at that timer's share of the time. 90 // In order to do this, we must refresh each timer whenever the number of active timers 91 // changes. 92 final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>(); 93 final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>(); 94 final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>(); 95 final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers 96 = new SparseArray<ArrayList<StopwatchTimer>>(); 97 98 // These are the objects that will want to do something when the device 99 // is unplugged from power. 100 final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>(); 101 102 boolean mShuttingDown; 103 104 long mHistoryBaseTime; 105 boolean mHaveBatteryLevel = false; 106 boolean mRecordingHistory = true; 107 int mNumHistoryItems; 108 HistoryItem mHistory; 109 HistoryItem mHistoryEnd; 110 HistoryItem mHistoryLastEnd; 111 HistoryItem mHistoryCache; 112 final HistoryItem mHistoryCur = new HistoryItem(); 113 114 int mStartCount; 115 116 long mBatteryUptime; 117 long mBatteryLastUptime; 118 long mBatteryRealtime; 119 long mBatteryLastRealtime; 120 121 long mUptime; 122 long mUptimeStart; 123 long mLastUptime; 124 long mRealtime; 125 long mRealtimeStart; 126 long mLastRealtime; 127 128 boolean mScreenOn; 129 StopwatchTimer mScreenOnTimer; 130 131 int mScreenBrightnessBin = -1; 132 final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS]; 133 134 Counter mInputEventCounter; 135 136 boolean mPhoneOn; 137 StopwatchTimer mPhoneOnTimer; 138 139 boolean mAudioOn; 140 StopwatchTimer mAudioOnTimer; 141 142 boolean mVideoOn; 143 StopwatchTimer mVideoOnTimer; 144 145 int mPhoneSignalStrengthBin = -1; 146 final StopwatchTimer[] mPhoneSignalStrengthsTimer = 147 new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS]; 148 149 StopwatchTimer mPhoneSignalScanningTimer; 150 151 int mPhoneDataConnectionType = -1; 152 final StopwatchTimer[] mPhoneDataConnectionsTimer = 153 new StopwatchTimer[NUM_DATA_CONNECTION_TYPES]; 154 155 boolean mWifiOn; 156 StopwatchTimer mWifiOnTimer; 157 int mWifiOnUid = -1; 158 159 boolean mWifiRunning; 160 StopwatchTimer mWifiRunningTimer; 161 162 boolean mBluetoothOn; 163 StopwatchTimer mBluetoothOnTimer; 164 165 /** Bluetooth headset object */ 166 BluetoothHeadset mBtHeadset; 167 168 /** 169 * These provide time bases that discount the time the device is plugged 170 * in to power. 171 */ 172 boolean mOnBattery; 173 boolean mOnBatteryInternal; 174 long mTrackBatteryPastUptime; 175 long mTrackBatteryUptimeStart; 176 long mTrackBatteryPastRealtime; 177 long mTrackBatteryRealtimeStart; 178 179 long mUnpluggedBatteryUptime; 180 long mUnpluggedBatteryRealtime; 181 182 /* 183 * These keep track of battery levels (1-100) at the last plug event and the last unplug event. 184 */ 185 int mDischargeStartLevel; 186 int mDischargeUnplugLevel; 187 int mDischargeCurrentLevel; 188 int mLowDischargeAmountSinceCharge; 189 int mHighDischargeAmountSinceCharge; 190 191 long mLastWriteTime = 0; // Milliseconds 192 193 // Mobile data transferred while on battery 194 private long[] mMobileDataTx = new long[4]; 195 private long[] mMobileDataRx = new long[4]; 196 private long[] mTotalDataTx = new long[4]; 197 private long[] mTotalDataRx = new long[4]; 198 199 private long mRadioDataUptime; 200 private long mRadioDataStart; 201 202 private int mBluetoothPingCount; 203 private int mBluetoothPingStart = -1; 204 205 private int mPhoneServiceState = -1; 206 207 /* 208 * Holds a SamplingTimer associated with each kernel wakelock name being tracked. 209 */ 210 private final HashMap<String, SamplingTimer> mKernelWakelockStats = 211 new HashMap<String, SamplingTimer>(); 212 213 public Map<String, ? extends SamplingTimer> getKernelWakelockStats() { 214 return mKernelWakelockStats; 215 } 216 217 private static int sKernelWakelockUpdateVersion = 0; 218 219 private static final int[] PROC_WAKELOCKS_FORMAT = new int[] { 220 Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name 221 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count 222 Process.PROC_TAB_TERM, 223 Process.PROC_TAB_TERM, 224 Process.PROC_TAB_TERM, 225 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime 226 }; 227 228 private final String[] mProcWakelocksName = new String[3]; 229 private final long[] mProcWakelocksData = new long[3]; 230 231 /* 232 * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added 233 * to mKernelWakelockStats. 234 */ 235 private final Map<String, KernelWakelockStats> mProcWakelockFileStats = 236 new HashMap<String, KernelWakelockStats>(); 237 238 private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>(); 239 240 // For debugging 241 public BatteryStatsImpl() { 242 mFile = null; 243 } 244 245 public static interface Unpluggable { 246 void unplug(long batteryUptime, long batteryRealtime); 247 void plug(long batteryUptime, long batteryRealtime); 248 } 249 250 /** 251 * State for keeping track of counting information. 252 */ 253 public static class Counter extends BatteryStats.Counter implements Unpluggable { 254 final AtomicInteger mCount = new AtomicInteger(); 255 final ArrayList<Unpluggable> mUnpluggables; 256 int mLoadedCount; 257 int mLastCount; 258 int mUnpluggedCount; 259 int mPluggedCount; 260 261 Counter(ArrayList<Unpluggable> unpluggables, Parcel in) { 262 mUnpluggables = unpluggables; 263 mPluggedCount = in.readInt(); 264 mCount.set(mPluggedCount); 265 mLoadedCount = in.readInt(); 266 mLastCount = 0; 267 mUnpluggedCount = in.readInt(); 268 unpluggables.add(this); 269 } 270 271 Counter(ArrayList<Unpluggable> unpluggables) { 272 mUnpluggables = unpluggables; 273 unpluggables.add(this); 274 } 275 276 public void writeToParcel(Parcel out) { 277 out.writeInt(mCount.get()); 278 out.writeInt(mLoadedCount); 279 out.writeInt(mUnpluggedCount); 280 } 281 282 public void unplug(long batteryUptime, long batteryRealtime) { 283 mUnpluggedCount = mPluggedCount; 284 mCount.set(mPluggedCount); 285 } 286 287 public void plug(long batteryUptime, long batteryRealtime) { 288 mPluggedCount = mCount.get(); 289 } 290 291 /** 292 * Writes a possibly null Counter to a Parcel. 293 * 294 * @param out the Parcel to be written to. 295 * @param counter a Counter, or null. 296 */ 297 public static void writeCounterToParcel(Parcel out, Counter counter) { 298 if (counter == null) { 299 out.writeInt(0); // indicates null 300 return; 301 } 302 out.writeInt(1); // indicates non-null 303 304 counter.writeToParcel(out); 305 } 306 307 @Override 308 public int getCountLocked(int which) { 309 int val; 310 if (which == STATS_LAST) { 311 val = mLastCount; 312 } else { 313 val = mCount.get(); 314 if (which == STATS_SINCE_UNPLUGGED) { 315 val -= mUnpluggedCount; 316 } else if (which != STATS_SINCE_CHARGED) { 317 val -= mLoadedCount; 318 } 319 } 320 321 return val; 322 } 323 324 public void logState(Printer pw, String prefix) { 325 pw.println(prefix + "mCount=" + mCount.get() 326 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 327 + " mUnpluggedCount=" + mUnpluggedCount 328 + " mPluggedCount=" + mPluggedCount); 329 } 330 331 void stepAtomic() { 332 mCount.incrementAndGet(); 333 } 334 335 /** 336 * Clear state of this counter. 337 */ 338 void reset(boolean detachIfReset) { 339 mCount.set(0); 340 mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0; 341 if (detachIfReset) { 342 detach(); 343 } 344 } 345 346 void detach() { 347 mUnpluggables.remove(this); 348 } 349 350 void writeSummaryFromParcelLocked(Parcel out) { 351 int count = mCount.get(); 352 out.writeInt(count); 353 } 354 355 void readSummaryFromParcelLocked(Parcel in) { 356 mLoadedCount = in.readInt(); 357 mCount.set(mLoadedCount); 358 mLastCount = 0; 359 mUnpluggedCount = mPluggedCount = mLoadedCount; 360 } 361 } 362 363 public static class SamplingCounter extends Counter { 364 365 SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) { 366 super(unpluggables, in); 367 } 368 369 SamplingCounter(ArrayList<Unpluggable> unpluggables) { 370 super(unpluggables); 371 } 372 373 public void addCountAtomic(long count) { 374 mCount.addAndGet((int)count); 375 } 376 } 377 378 /** 379 * State for keeping track of timing information. 380 */ 381 public static abstract class Timer extends BatteryStats.Timer implements Unpluggable { 382 final int mType; 383 final ArrayList<Unpluggable> mUnpluggables; 384 385 int mCount; 386 int mLoadedCount; 387 int mLastCount; 388 int mUnpluggedCount; 389 390 // Times are in microseconds for better accuracy when dividing by the 391 // lock count, and are in "battery realtime" units. 392 393 /** 394 * The total time we have accumulated since the start of the original 395 * boot, to the last time something interesting happened in the 396 * current run. 397 */ 398 long mTotalTime; 399 400 /** 401 * The total time we loaded for the previous runs. Subtract this from 402 * mTotalTime to find the time for the current run of the system. 403 */ 404 long mLoadedTime; 405 406 /** 407 * The run time of the last run of the system, as loaded from the 408 * saved data. 409 */ 410 long mLastTime; 411 412 /** 413 * The value of mTotalTime when unplug() was last called. Subtract 414 * this from mTotalTime to find the time since the last unplug from 415 * power. 416 */ 417 long mUnpluggedTime; 418 419 /** 420 * Constructs from a parcel. 421 * @param type 422 * @param unpluggables 423 * @param powerType 424 * @param in 425 */ 426 Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) { 427 mType = type; 428 mUnpluggables = unpluggables; 429 430 mCount = in.readInt(); 431 mLoadedCount = in.readInt(); 432 mLastCount = 0; 433 mUnpluggedCount = in.readInt(); 434 mTotalTime = in.readLong(); 435 mLoadedTime = in.readLong(); 436 mLastTime = 0; 437 mUnpluggedTime = in.readLong(); 438 unpluggables.add(this); 439 } 440 441 Timer(int type, ArrayList<Unpluggable> unpluggables) { 442 mType = type; 443 mUnpluggables = unpluggables; 444 unpluggables.add(this); 445 } 446 447 protected abstract long computeRunTimeLocked(long curBatteryRealtime); 448 449 protected abstract int computeCurrentCountLocked(); 450 451 /** 452 * Clear state of this timer. Returns true if the timer is inactive 453 * so can be completely dropped. 454 */ 455 boolean reset(BatteryStatsImpl stats, boolean detachIfReset) { 456 mTotalTime = mLoadedTime = mLastTime = 0; 457 mCount = mLoadedCount = mLastCount = 0; 458 if (detachIfReset) { 459 detach(); 460 } 461 return true; 462 } 463 464 void detach() { 465 mUnpluggables.remove(this); 466 } 467 468 public void writeToParcel(Parcel out, long batteryRealtime) { 469 out.writeInt(mCount); 470 out.writeInt(mLoadedCount); 471 out.writeInt(mUnpluggedCount); 472 out.writeLong(computeRunTimeLocked(batteryRealtime)); 473 out.writeLong(mLoadedTime); 474 out.writeLong(mUnpluggedTime); 475 } 476 477 public void unplug(long batteryUptime, long batteryRealtime) { 478 if (DEBUG && mType < 0) { 479 Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime 480 + " old mUnpluggedTime=" + mUnpluggedTime 481 + " old mUnpluggedCount=" + mUnpluggedCount); 482 } 483 mUnpluggedTime = computeRunTimeLocked(batteryRealtime); 484 mUnpluggedCount = mCount; 485 if (DEBUG && mType < 0) { 486 Log.v(TAG, "unplug #" + mType 487 + ": new mUnpluggedTime=" + mUnpluggedTime 488 + " new mUnpluggedCount=" + mUnpluggedCount); 489 } 490 } 491 492 public void plug(long batteryUptime, long batteryRealtime) { 493 if (DEBUG && mType < 0) { 494 Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime 495 + " old mTotalTime=" + mTotalTime); 496 } 497 mTotalTime = computeRunTimeLocked(batteryRealtime); 498 mCount = computeCurrentCountLocked(); 499 if (DEBUG && mType < 0) { 500 Log.v(TAG, "plug #" + mType 501 + ": new mTotalTime=" + mTotalTime); 502 } 503 } 504 505 /** 506 * Writes a possibly null Timer to a Parcel. 507 * 508 * @param out the Parcel to be written to. 509 * @param timer a Timer, or null. 510 */ 511 public static void writeTimerToParcel(Parcel out, Timer timer, 512 long batteryRealtime) { 513 if (timer == null) { 514 out.writeInt(0); // indicates null 515 return; 516 } 517 out.writeInt(1); // indicates non-null 518 519 timer.writeToParcel(out, batteryRealtime); 520 } 521 522 @Override 523 public long getTotalTimeLocked(long batteryRealtime, int which) { 524 long val; 525 if (which == STATS_LAST) { 526 val = mLastTime; 527 } else { 528 val = computeRunTimeLocked(batteryRealtime); 529 if (which == STATS_SINCE_UNPLUGGED) { 530 val -= mUnpluggedTime; 531 } else if (which != STATS_SINCE_CHARGED) { 532 val -= mLoadedTime; 533 } 534 } 535 536 return val; 537 } 538 539 @Override 540 public int getCountLocked(int which) { 541 int val; 542 if (which == STATS_LAST) { 543 val = mLastCount; 544 } else { 545 val = computeCurrentCountLocked(); 546 if (which == STATS_SINCE_UNPLUGGED) { 547 val -= mUnpluggedCount; 548 } else if (which != STATS_SINCE_CHARGED) { 549 val -= mLoadedCount; 550 } 551 } 552 553 return val; 554 } 555 556 public void logState(Printer pw, String prefix) { 557 pw.println(prefix + " mCount=" + mCount 558 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 559 + " mUnpluggedCount=" + mUnpluggedCount); 560 pw.println(prefix + "mTotalTime=" + mTotalTime 561 + " mLoadedTime=" + mLoadedTime); 562 pw.println(prefix + "mLastTime=" + mLastTime 563 + " mUnpluggedTime=" + mUnpluggedTime); 564 } 565 566 567 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 568 long runTime = computeRunTimeLocked(batteryRealtime); 569 // Divide by 1000 for backwards compatibility 570 out.writeLong((runTime + 500) / 1000); 571 out.writeInt(mCount); 572 } 573 574 void readSummaryFromParcelLocked(Parcel in) { 575 // Multiply by 1000 for backwards compatibility 576 mTotalTime = mLoadedTime = in.readLong() * 1000; 577 mLastTime = 0; 578 mUnpluggedTime = mTotalTime; 579 mCount = mLoadedCount = in.readInt(); 580 mLastCount = 0; 581 mUnpluggedCount = mCount; 582 } 583 } 584 585 public static final class SamplingTimer extends Timer { 586 587 /** 588 * The most recent reported count from /proc/wakelocks. 589 */ 590 int mCurrentReportedCount; 591 592 /** 593 * The reported count from /proc/wakelocks when unplug() was last 594 * called. 595 */ 596 int mUnpluggedReportedCount; 597 598 /** 599 * The most recent reported total_time from /proc/wakelocks. 600 */ 601 long mCurrentReportedTotalTime; 602 603 604 /** 605 * The reported total_time from /proc/wakelocks when unplug() was last 606 * called. 607 */ 608 long mUnpluggedReportedTotalTime; 609 610 /** 611 * Whether we are currently in a discharge cycle. 612 */ 613 boolean mInDischarge; 614 615 /** 616 * Whether we are currently recording reported values. 617 */ 618 boolean mTrackingReportedValues; 619 620 /* 621 * A sequnce counter, incremented once for each update of the stats. 622 */ 623 int mUpdateVersion; 624 625 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) { 626 super(0, unpluggables, in); 627 mCurrentReportedCount = in.readInt(); 628 mUnpluggedReportedCount = in.readInt(); 629 mCurrentReportedTotalTime = in.readLong(); 630 mUnpluggedReportedTotalTime = in.readLong(); 631 mTrackingReportedValues = in.readInt() == 1; 632 mInDischarge = inDischarge; 633 } 634 635 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, 636 boolean trackReportedValues) { 637 super(0, unpluggables); 638 mTrackingReportedValues = trackReportedValues; 639 mInDischarge = inDischarge; 640 } 641 642 public void setStale() { 643 mTrackingReportedValues = false; 644 mUnpluggedReportedTotalTime = 0; 645 mUnpluggedReportedCount = 0; 646 } 647 648 public void setUpdateVersion(int version) { 649 mUpdateVersion = version; 650 } 651 652 public int getUpdateVersion() { 653 return mUpdateVersion; 654 } 655 656 public void updateCurrentReportedCount(int count) { 657 if (mInDischarge && mUnpluggedReportedCount == 0) { 658 // Updating the reported value for the first time. 659 mUnpluggedReportedCount = count; 660 // If we are receiving an update update mTrackingReportedValues; 661 mTrackingReportedValues = true; 662 } 663 mCurrentReportedCount = count; 664 } 665 666 public void updateCurrentReportedTotalTime(long totalTime) { 667 if (mInDischarge && mUnpluggedReportedTotalTime == 0) { 668 // Updating the reported value for the first time. 669 mUnpluggedReportedTotalTime = totalTime; 670 // If we are receiving an update update mTrackingReportedValues; 671 mTrackingReportedValues = true; 672 } 673 mCurrentReportedTotalTime = totalTime; 674 } 675 676 public void unplug(long batteryUptime, long batteryRealtime) { 677 super.unplug(batteryUptime, batteryRealtime); 678 if (mTrackingReportedValues) { 679 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime; 680 mUnpluggedReportedCount = mCurrentReportedCount; 681 } 682 mInDischarge = true; 683 } 684 685 public void plug(long batteryUptime, long batteryRealtime) { 686 super.plug(batteryUptime, batteryRealtime); 687 mInDischarge = false; 688 } 689 690 public void logState(Printer pw, String prefix) { 691 super.logState(pw, prefix); 692 pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount 693 + " mUnpluggedReportedCount=" + mUnpluggedReportedCount 694 + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime 695 + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime); 696 } 697 698 protected long computeRunTimeLocked(long curBatteryRealtime) { 699 return mTotalTime + (mInDischarge && mTrackingReportedValues 700 ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0); 701 } 702 703 protected int computeCurrentCountLocked() { 704 return mCount + (mInDischarge && mTrackingReportedValues 705 ? mCurrentReportedCount - mUnpluggedReportedCount : 0); 706 } 707 708 public void writeToParcel(Parcel out, long batteryRealtime) { 709 super.writeToParcel(out, batteryRealtime); 710 out.writeInt(mCurrentReportedCount); 711 out.writeInt(mUnpluggedReportedCount); 712 out.writeLong(mCurrentReportedTotalTime); 713 out.writeLong(mUnpluggedReportedTotalTime); 714 out.writeInt(mTrackingReportedValues ? 1 : 0); 715 } 716 717 boolean reset(BatteryStatsImpl stats, boolean detachIfReset) { 718 super.reset(stats, detachIfReset); 719 setStale(); 720 return true; 721 } 722 723 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 724 super.writeSummaryFromParcelLocked(out, batteryRealtime); 725 out.writeLong(mCurrentReportedTotalTime); 726 out.writeInt(mCurrentReportedCount); 727 out.writeInt(mTrackingReportedValues ? 1 : 0); 728 } 729 730 void readSummaryFromParcelLocked(Parcel in) { 731 super.readSummaryFromParcelLocked(in); 732 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong(); 733 mUnpluggedReportedCount = mCurrentReportedCount = in.readInt(); 734 mTrackingReportedValues = in.readInt() == 1; 735 } 736 } 737 738 /** 739 * State for keeping track of timing information. 740 */ 741 public static final class StopwatchTimer extends Timer { 742 final ArrayList<StopwatchTimer> mTimerPool; 743 int mNesting; 744 745 /** 746 * The last time at which we updated the timer. If mNesting is > 0, 747 * subtract this from the current battery time to find the amount of 748 * time we have been running since we last computed an update. 749 */ 750 long mUpdateTime; 751 752 /** 753 * The total time at which the timer was acquired, to determine if it 754 * was actually held for an interesting duration. 755 */ 756 long mAcquireTime; 757 758 long mTimeout; 759 760 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, 761 ArrayList<Unpluggable> unpluggables, Parcel in) { 762 super(type, unpluggables, in); 763 mTimerPool = timerPool; 764 mUpdateTime = in.readLong(); 765 } 766 767 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, 768 ArrayList<Unpluggable> unpluggables) { 769 super(type, unpluggables); 770 mTimerPool = timerPool; 771 } 772 773 void setTimeout(long timeout) { 774 mTimeout = timeout; 775 } 776 777 public void writeToParcel(Parcel out, long batteryRealtime) { 778 super.writeToParcel(out, batteryRealtime); 779 out.writeLong(mUpdateTime); 780 } 781 782 public void plug(long batteryUptime, long batteryRealtime) { 783 if (mNesting > 0) { 784 if (DEBUG && mType < 0) { 785 Log.v(TAG, "old mUpdateTime=" + mUpdateTime); 786 } 787 super.plug(batteryUptime, batteryRealtime); 788 mUpdateTime = batteryRealtime; 789 if (DEBUG && mType < 0) { 790 Log.v(TAG, "new mUpdateTime=" + mUpdateTime); 791 } 792 } 793 } 794 795 public void logState(Printer pw, String prefix) { 796 super.logState(pw, prefix); 797 pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime 798 + " mAcquireTime=" + mAcquireTime); 799 } 800 801 void startRunningLocked(BatteryStatsImpl stats) { 802 if (mNesting++ == 0) { 803 mUpdateTime = stats.getBatteryRealtimeLocked( 804 SystemClock.elapsedRealtime() * 1000); 805 if (mTimerPool != null) { 806 // Accumulate time to all currently active timers before adding 807 // this new one to the pool. 808 refreshTimersLocked(stats, mTimerPool); 809 // Add this timer to the active pool 810 mTimerPool.add(this); 811 } 812 // Increment the count 813 mCount++; 814 mAcquireTime = mTotalTime; 815 if (DEBUG && mType < 0) { 816 Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime 817 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 818 + " mAcquireTime=" + mAcquireTime); 819 } 820 } 821 } 822 823 boolean isRunningLocked() { 824 return mNesting > 0; 825 } 826 827 void stopRunningLocked(BatteryStatsImpl stats) { 828 // Ignore attempt to stop a timer that isn't running 829 if (mNesting == 0) { 830 return; 831 } 832 if (--mNesting == 0) { 833 if (mTimerPool != null) { 834 // Accumulate time to all active counters, scaled by the total 835 // active in the pool, before taking this one out of the pool. 836 refreshTimersLocked(stats, mTimerPool); 837 // Remove this timer from the active pool 838 mTimerPool.remove(this); 839 } else { 840 final long realtime = SystemClock.elapsedRealtime() * 1000; 841 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 842 mNesting = 1; 843 mTotalTime = computeRunTimeLocked(batteryRealtime); 844 mNesting = 0; 845 } 846 847 if (DEBUG && mType < 0) { 848 Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime 849 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 850 + " mAcquireTime=" + mAcquireTime); 851 } 852 853 if (mTotalTime == mAcquireTime) { 854 // If there was no change in the time, then discard this 855 // count. A somewhat cheezy strategy, but hey. 856 mCount--; 857 } 858 } 859 } 860 861 // Update the total time for all other running Timers with the same type as this Timer 862 // due to a change in timer count 863 private static void refreshTimersLocked(final BatteryStatsImpl stats, 864 final ArrayList<StopwatchTimer> pool) { 865 final long realtime = SystemClock.elapsedRealtime() * 1000; 866 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 867 final int N = pool.size(); 868 for (int i=N-1; i>= 0; i--) { 869 final StopwatchTimer t = pool.get(i); 870 long heldTime = batteryRealtime - t.mUpdateTime; 871 if (heldTime > 0) { 872 t.mTotalTime += heldTime / N; 873 } 874 t.mUpdateTime = batteryRealtime; 875 } 876 } 877 878 @Override 879 protected long computeRunTimeLocked(long curBatteryRealtime) { 880 if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) { 881 curBatteryRealtime = mUpdateTime + mTimeout; 882 } 883 return mTotalTime + (mNesting > 0 884 ? (curBatteryRealtime - mUpdateTime) 885 / (mTimerPool != null ? mTimerPool.size() : 1) 886 : 0); 887 } 888 889 @Override 890 protected int computeCurrentCountLocked() { 891 return mCount; 892 } 893 894 boolean reset(BatteryStatsImpl stats, boolean detachIfReset) { 895 boolean canDetach = mNesting <= 0; 896 super.reset(stats, canDetach && detachIfReset); 897 if (mNesting > 0) { 898 mUpdateTime = stats.getBatteryRealtimeLocked( 899 SystemClock.elapsedRealtime() * 1000); 900 } 901 mAcquireTime = mTotalTime; 902 return canDetach; 903 } 904 905 void detach() { 906 super.detach(); 907 if (mTimerPool != null) { 908 mTimerPool.remove(this); 909 } 910 } 911 912 void readSummaryFromParcelLocked(Parcel in) { 913 super.readSummaryFromParcelLocked(in); 914 mNesting = 0; 915 } 916 } 917 918 private final Map<String, KernelWakelockStats> readKernelWakelockStats() { 919 920 byte[] buffer = new byte[4096]; 921 int len; 922 923 try { 924 FileInputStream is = new FileInputStream("/proc/wakelocks"); 925 len = is.read(buffer); 926 is.close(); 927 928 if (len > 0) { 929 int i; 930 for (i=0; i<len; i++) { 931 if (buffer[i] == '\0') { 932 len = i; 933 break; 934 } 935 } 936 } 937 } catch (java.io.FileNotFoundException e) { 938 return null; 939 } catch (java.io.IOException e) { 940 return null; 941 } 942 943 return parseProcWakelocks(buffer, len); 944 } 945 946 private final Map<String, KernelWakelockStats> parseProcWakelocks( 947 byte[] wlBuffer, int len) { 948 String name; 949 int count; 950 long totalTime; 951 int startIndex, endIndex; 952 int numUpdatedWlNames = 0; 953 954 // Advance past the first line. 955 int i; 956 for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++); 957 startIndex = endIndex = i + 1; 958 959 synchronized(this) { 960 Map<String, KernelWakelockStats> m = mProcWakelockFileStats; 961 962 sKernelWakelockUpdateVersion++; 963 while (endIndex < len) { 964 for (endIndex=startIndex; 965 endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0'; 966 endIndex++); 967 // Don't go over the end of the buffer 968 if (endIndex < len) { 969 endIndex++; // endIndex is an exclusive upper bound. 970 } 971 972 String[] nameStringArray = mProcWakelocksName; 973 long[] wlData = mProcWakelocksData; 974 // Stomp out any bad characters since this is from a circular buffer 975 // A corruption is seen sometimes that results in the vm crashing 976 // This should prevent crashes and the line will probably fail to parse 977 for (int j = startIndex; j < endIndex; j++) { 978 if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?'; 979 } 980 boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex, 981 PROC_WAKELOCKS_FORMAT, nameStringArray, wlData, null); 982 983 name = nameStringArray[0]; 984 count = (int) wlData[1]; 985 // convert nanoseconds to microseconds with rounding. 986 totalTime = (wlData[2] + 500) / 1000; 987 988 if (parsed && name.length() > 0) { 989 if (!m.containsKey(name)) { 990 m.put(name, new KernelWakelockStats(count, totalTime, 991 sKernelWakelockUpdateVersion)); 992 numUpdatedWlNames++; 993 } else { 994 KernelWakelockStats kwlStats = m.get(name); 995 if (kwlStats.mVersion == sKernelWakelockUpdateVersion) { 996 kwlStats.mCount += count; 997 kwlStats.mTotalTime += totalTime; 998 } else { 999 kwlStats.mCount = count; 1000 kwlStats.mTotalTime = totalTime; 1001 kwlStats.mVersion = sKernelWakelockUpdateVersion; 1002 numUpdatedWlNames++; 1003 } 1004 } 1005 } 1006 startIndex = endIndex; 1007 } 1008 1009 if (m.size() != numUpdatedWlNames) { 1010 // Don't report old data. 1011 Iterator<KernelWakelockStats> itr = m.values().iterator(); 1012 while (itr.hasNext()) { 1013 if (itr.next().mVersion != sKernelWakelockUpdateVersion) { 1014 itr.remove(); 1015 } 1016 } 1017 } 1018 return m; 1019 } 1020 } 1021 1022 private class KernelWakelockStats { 1023 public int mCount; 1024 public long mTotalTime; 1025 public int mVersion; 1026 1027 KernelWakelockStats(int count, long totalTime, int version) { 1028 mCount = count; 1029 mTotalTime = totalTime; 1030 mVersion = version; 1031 } 1032 } 1033 1034 /* 1035 * Get the KernelWakelockTimer associated with name, and create a new one if one 1036 * doesn't already exist. 1037 */ 1038 public SamplingTimer getKernelWakelockTimerLocked(String name) { 1039 SamplingTimer kwlt = mKernelWakelockStats.get(name); 1040 if (kwlt == null) { 1041 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 1042 true /* track reported values */); 1043 mKernelWakelockStats.put(name, kwlt); 1044 } 1045 return kwlt; 1046 } 1047 1048 private void doDataPlug(long[] dataTransfer, long currentBytes) { 1049 dataTransfer[STATS_LAST] = dataTransfer[STATS_SINCE_UNPLUGGED]; 1050 dataTransfer[STATS_SINCE_UNPLUGGED] = -1; 1051 } 1052 1053 private void doDataUnplug(long[] dataTransfer, long currentBytes) { 1054 dataTransfer[STATS_SINCE_UNPLUGGED] = currentBytes; 1055 } 1056 1057 /** 1058 * Radio uptime in microseconds when transferring data. This value is very approximate. 1059 * @return 1060 */ 1061 private long getCurrentRadioDataUptime() { 1062 try { 1063 File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms"); 1064 if (!awakeTimeFile.exists()) return 0; 1065 BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile)); 1066 String line = br.readLine(); 1067 br.close(); 1068 return Long.parseLong(line) * 1000; 1069 } catch (NumberFormatException nfe) { 1070 // Nothing 1071 } catch (IOException ioe) { 1072 // Nothing 1073 } 1074 return 0; 1075 } 1076 1077 /** 1078 * @deprecated use getRadioDataUptime 1079 */ 1080 public long getRadioDataUptimeMs() { 1081 return getRadioDataUptime() / 1000; 1082 } 1083 1084 /** 1085 * Returns the duration that the cell radio was up for data transfers. 1086 */ 1087 public long getRadioDataUptime() { 1088 if (mRadioDataStart == -1) { 1089 return mRadioDataUptime; 1090 } else { 1091 return getCurrentRadioDataUptime() - mRadioDataStart; 1092 } 1093 } 1094 1095 private int getCurrentBluetoothPingCount() { 1096 if (mBtHeadset != null) { 1097 return mBtHeadset.getBatteryUsageHint(); 1098 } 1099 return -1; 1100 } 1101 1102 public int getBluetoothPingCount() { 1103 if (mBluetoothPingStart == -1) { 1104 return mBluetoothPingCount; 1105 } else if (mBtHeadset != null) { 1106 return getCurrentBluetoothPingCount() - mBluetoothPingStart; 1107 } 1108 return 0; 1109 } 1110 1111 public void setBtHeadset(BluetoothHeadset headset) { 1112 if (headset != null && mBtHeadset == null && isOnBattery() && mBluetoothPingStart == -1) { 1113 mBluetoothPingStart = getCurrentBluetoothPingCount(); 1114 } 1115 mBtHeadset = headset; 1116 } 1117 1118 void addHistoryRecordLocked(long curTime) { 1119 if (!mHaveBatteryLevel || !mRecordingHistory) { 1120 return; 1121 } 1122 1123 // If the current time is basically the same as the last time, 1124 // just collapse into one record. 1125 if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE 1126 && (mHistoryBaseTime+curTime) < (mHistoryEnd.time+100)) { 1127 // If the current is the same as the one before, then we no 1128 // longer need the entry. 1129 if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE 1130 && mHistoryLastEnd.same(mHistoryCur)) { 1131 mHistoryLastEnd.next = null; 1132 mHistoryEnd.next = mHistoryCache; 1133 mHistoryCache = mHistoryEnd; 1134 mHistoryEnd = mHistoryLastEnd; 1135 mHistoryLastEnd = null; 1136 } else { 1137 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, mHistoryCur); 1138 } 1139 return; 1140 } 1141 1142 if (mNumHistoryItems >= MAX_HISTORY_ITEMS) { 1143 // Once we've reached the maximum number of items, we only 1144 // record changes to the battery level. 1145 if (mHistoryEnd != null && mHistoryEnd.batteryLevel 1146 == mHistoryCur.batteryLevel) { 1147 return; 1148 } 1149 } 1150 1151 addHistoryRecordLocked(curTime, HistoryItem.CMD_UPDATE); 1152 } 1153 1154 void addHistoryRecordLocked(long curTime, byte cmd) { 1155 HistoryItem rec = mHistoryCache; 1156 if (rec != null) { 1157 mHistoryCache = rec.next; 1158 } else { 1159 rec = new HistoryItem(); 1160 } 1161 rec.setTo(mHistoryBaseTime + curTime, cmd, mHistoryCur); 1162 1163 addHistoryRecordLocked(rec); 1164 } 1165 1166 void addHistoryRecordLocked(HistoryItem rec) { 1167 mNumHistoryItems++; 1168 rec.next = null; 1169 mHistoryLastEnd = mHistoryEnd; 1170 if (mHistoryEnd != null) { 1171 mHistoryEnd.next = rec; 1172 mHistoryEnd = rec; 1173 } else { 1174 mHistory = mHistoryEnd = rec; 1175 } 1176 } 1177 1178 void clearHistoryLocked() { 1179 if (mHistory != null) { 1180 mHistoryEnd.next = mHistoryCache; 1181 mHistoryCache = mHistory; 1182 mHistory = mHistoryLastEnd = mHistoryEnd = null; 1183 } 1184 mNumHistoryItems = 0; 1185 mHistoryBaseTime = 0; 1186 } 1187 1188 public void doUnplugLocked(long batteryUptime, long batteryRealtime) { 1189 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 1190 Uid u = mUidStats.valueAt(iu); 1191 u.mStartedTcpBytesReceived = TrafficStats.getUidRxBytes(u.mUid); 1192 u.mStartedTcpBytesSent = TrafficStats.getUidTxBytes(u.mUid); 1193 u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived; 1194 u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent; 1195 } 1196 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 1197 mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime); 1198 } 1199 // Track total mobile data 1200 doDataUnplug(mMobileDataRx, TrafficStats.getMobileRxBytes()); 1201 doDataUnplug(mMobileDataTx, TrafficStats.getMobileTxBytes()); 1202 doDataUnplug(mTotalDataRx, TrafficStats.getTotalRxBytes()); 1203 doDataUnplug(mTotalDataTx, TrafficStats.getTotalTxBytes()); 1204 // Track radio awake time 1205 mRadioDataStart = getCurrentRadioDataUptime(); 1206 mRadioDataUptime = 0; 1207 // Track bt headset ping count 1208 mBluetoothPingStart = getCurrentBluetoothPingCount(); 1209 mBluetoothPingCount = 0; 1210 } 1211 1212 public void doPlugLocked(long batteryUptime, long batteryRealtime) { 1213 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 1214 Uid u = mUidStats.valueAt(iu); 1215 if (u.mStartedTcpBytesReceived >= 0) { 1216 u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived(); 1217 u.mStartedTcpBytesReceived = -1; 1218 } 1219 if (u.mStartedTcpBytesSent >= 0) { 1220 u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent(); 1221 u.mStartedTcpBytesSent = -1; 1222 } 1223 } 1224 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 1225 mUnpluggables.get(i).plug(batteryUptime, batteryRealtime); 1226 } 1227 doDataPlug(mMobileDataRx, TrafficStats.getMobileRxBytes()); 1228 doDataPlug(mMobileDataTx, TrafficStats.getMobileTxBytes()); 1229 doDataPlug(mTotalDataRx, TrafficStats.getTotalRxBytes()); 1230 doDataPlug(mTotalDataTx, TrafficStats.getTotalTxBytes()); 1231 // Track radio awake time 1232 mRadioDataUptime = getRadioDataUptime(); 1233 mRadioDataStart = -1; 1234 1235 // Track bt headset ping count 1236 mBluetoothPingCount = getBluetoothPingCount(); 1237 mBluetoothPingStart = -1; 1238 } 1239 1240 int mWakeLockNesting; 1241 1242 public void noteStartWakeLocked(int uid, int pid, String name, int type) { 1243 if (type == WAKE_TYPE_PARTIAL) { 1244 // Only care about partial wake locks, since full wake locks 1245 // will be canceled when the user puts the screen to sleep. 1246 if (mWakeLockNesting == 0) { 1247 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG; 1248 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: " 1249 + Integer.toHexString(mHistoryCur.states)); 1250 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1251 } 1252 mWakeLockNesting++; 1253 } 1254 if (uid >= 0) { 1255 getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type); 1256 } 1257 } 1258 1259 public void noteStopWakeLocked(int uid, int pid, String name, int type) { 1260 if (type == WAKE_TYPE_PARTIAL) { 1261 mWakeLockNesting--; 1262 if (mWakeLockNesting == 0) { 1263 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG; 1264 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: " 1265 + Integer.toHexString(mHistoryCur.states)); 1266 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1267 } 1268 } 1269 if (uid >= 0) { 1270 getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type); 1271 } 1272 } 1273 1274 public void noteProcessDiedLocked(int uid, int pid) { 1275 Uid u = mUidStats.get(uid); 1276 if (u != null) { 1277 u.mPids.remove(pid); 1278 } 1279 } 1280 1281 public long getProcessWakeTime(int uid, int pid, long realtime) { 1282 Uid u = mUidStats.get(uid); 1283 if (u != null) { 1284 Uid.Pid p = u.mPids.get(pid); 1285 if (p != null) { 1286 return p.mWakeSum + (p.mWakeStart != 0 ? (realtime - p.mWakeStart) : 0); 1287 } 1288 } 1289 return 0; 1290 } 1291 1292 public void reportExcessiveWakeLocked(int uid, String proc, long overTime, long usedTime) { 1293 Uid u = mUidStats.get(uid); 1294 if (u != null) { 1295 u.reportExcessiveWakeLocked(proc, overTime, usedTime); 1296 } 1297 } 1298 1299 int mSensorNesting; 1300 1301 public void noteStartSensorLocked(int uid, int sensor) { 1302 if (mSensorNesting == 0) { 1303 mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG; 1304 if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: " 1305 + Integer.toHexString(mHistoryCur.states)); 1306 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1307 } 1308 mSensorNesting++; 1309 getUidStatsLocked(uid).noteStartSensor(sensor); 1310 } 1311 1312 public void noteStopSensorLocked(int uid, int sensor) { 1313 mSensorNesting--; 1314 if (mSensorNesting == 0) { 1315 mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG; 1316 if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: " 1317 + Integer.toHexString(mHistoryCur.states)); 1318 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1319 } 1320 getUidStatsLocked(uid).noteStopSensor(sensor); 1321 } 1322 1323 int mGpsNesting; 1324 1325 public void noteStartGpsLocked(int uid) { 1326 if (mGpsNesting == 0) { 1327 mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG; 1328 if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: " 1329 + Integer.toHexString(mHistoryCur.states)); 1330 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1331 } 1332 mGpsNesting++; 1333 getUidStatsLocked(uid).noteStartGps(); 1334 } 1335 1336 public void noteStopGpsLocked(int uid) { 1337 mGpsNesting--; 1338 if (mGpsNesting == 0) { 1339 mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG; 1340 if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: " 1341 + Integer.toHexString(mHistoryCur.states)); 1342 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1343 } 1344 getUidStatsLocked(uid).noteStopGps(); 1345 } 1346 1347 public void noteScreenOnLocked() { 1348 if (!mScreenOn) { 1349 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG; 1350 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: " 1351 + Integer.toHexString(mHistoryCur.states)); 1352 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1353 mScreenOn = true; 1354 mScreenOnTimer.startRunningLocked(this); 1355 if (mScreenBrightnessBin >= 0) { 1356 mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this); 1357 } 1358 1359 // Fake a wake lock, so we consider the device waked as long 1360 // as the screen is on. 1361 noteStartWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL); 1362 } 1363 } 1364 1365 public void noteScreenOffLocked() { 1366 if (mScreenOn) { 1367 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG; 1368 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: " 1369 + Integer.toHexString(mHistoryCur.states)); 1370 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1371 mScreenOn = false; 1372 mScreenOnTimer.stopRunningLocked(this); 1373 if (mScreenBrightnessBin >= 0) { 1374 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this); 1375 } 1376 1377 noteStopWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL); 1378 } 1379 } 1380 1381 public void noteScreenBrightnessLocked(int brightness) { 1382 // Bin the brightness. 1383 int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS); 1384 if (bin < 0) bin = 0; 1385 else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1; 1386 if (mScreenBrightnessBin != bin) { 1387 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK) 1388 | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT); 1389 if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: " 1390 + Integer.toHexString(mHistoryCur.states)); 1391 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1392 if (mScreenOn) { 1393 if (mScreenBrightnessBin >= 0) { 1394 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this); 1395 } 1396 mScreenBrightnessTimer[bin].startRunningLocked(this); 1397 } 1398 mScreenBrightnessBin = bin; 1399 } 1400 } 1401 1402 public void noteInputEventAtomic() { 1403 mInputEventCounter.stepAtomic(); 1404 } 1405 1406 public void noteUserActivityLocked(int uid, int event) { 1407 getUidStatsLocked(uid).noteUserActivityLocked(event); 1408 } 1409 1410 public void notePhoneOnLocked() { 1411 if (!mPhoneOn) { 1412 mHistoryCur.states |= HistoryItem.STATE_PHONE_IN_CALL_FLAG; 1413 if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: " 1414 + Integer.toHexString(mHistoryCur.states)); 1415 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1416 mPhoneOn = true; 1417 mPhoneOnTimer.startRunningLocked(this); 1418 } 1419 } 1420 1421 public void notePhoneOffLocked() { 1422 if (mPhoneOn) { 1423 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_IN_CALL_FLAG; 1424 if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: " 1425 + Integer.toHexString(mHistoryCur.states)); 1426 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1427 mPhoneOn = false; 1428 mPhoneOnTimer.stopRunningLocked(this); 1429 } 1430 } 1431 1432 void stopAllSignalStrengthTimersLocked(int except) { 1433 for (int i = 0; i < NUM_SIGNAL_STRENGTH_BINS; i++) { 1434 if (i == except) { 1435 continue; 1436 } 1437 while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) { 1438 mPhoneSignalStrengthsTimer[i].stopRunningLocked(this); 1439 } 1440 } 1441 } 1442 1443 /** 1444 * Telephony stack updates the phone state. 1445 * @param state phone state from ServiceState.getState() 1446 */ 1447 public void notePhoneStateLocked(int state) { 1448 boolean scanning = false; 1449 1450 int bin = mPhoneSignalStrengthBin; 1451 1452 // If the phone is powered off, stop all timers. 1453 if (state == ServiceState.STATE_POWER_OFF) { 1454 stopAllSignalStrengthTimersLocked(-1); 1455 1456 // If we're back in service or continuing in service, restart the old timer. 1457 } if (state == ServiceState.STATE_IN_SERVICE) { 1458 if (bin == -1) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1459 if (!mPhoneSignalStrengthsTimer[bin].isRunningLocked()) { 1460 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this); 1461 } 1462 1463 // If we're out of service, we are in the lowest signal strength 1464 // bin and have the scanning bit set. 1465 } else if (state == ServiceState.STATE_OUT_OF_SERVICE) { 1466 scanning = true; 1467 mPhoneSignalStrengthBin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1468 stopAllSignalStrengthTimersLocked(mPhoneSignalStrengthBin); 1469 if (!mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].isRunningLocked()) { 1470 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].startRunningLocked(this); 1471 } 1472 if (!mPhoneSignalScanningTimer.isRunningLocked()) { 1473 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG; 1474 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: " 1475 + Integer.toHexString(mHistoryCur.states)); 1476 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1477 mPhoneSignalScanningTimer.startRunningLocked(this); 1478 } 1479 } 1480 1481 if (!scanning) { 1482 // If we are no longer scanning, then stop the scanning timer. 1483 if (mPhoneSignalScanningTimer.isRunningLocked()) { 1484 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG; 1485 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: " 1486 + Integer.toHexString(mHistoryCur.states)); 1487 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1488 mPhoneSignalScanningTimer.stopRunningLocked(this); 1489 } 1490 } 1491 1492 if (mPhoneServiceState != state) { 1493 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK) 1494 | (state << HistoryItem.STATE_PHONE_STATE_SHIFT); 1495 if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + bin + " to: " 1496 + Integer.toHexString(mHistoryCur.states)); 1497 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1498 mPhoneServiceState = state; 1499 } 1500 } 1501 1502 public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) { 1503 // Bin the strength. 1504 int bin; 1505 if (mPhoneServiceState == ServiceState.STATE_POWER_OFF 1506 || mPhoneServiceState == ServiceState.STATE_OUT_OF_SERVICE) { 1507 // Ignore any signal strength changes when radio was turned off or out of service. 1508 return; 1509 } 1510 if (!signalStrength.isGsm()) { 1511 int dBm = signalStrength.getCdmaDbm(); 1512 if (dBm >= -75) bin = SIGNAL_STRENGTH_GREAT; 1513 else if (dBm >= -85) bin = SIGNAL_STRENGTH_GOOD; 1514 else if (dBm >= -95) bin = SIGNAL_STRENGTH_MODERATE; 1515 else if (dBm >= -100) bin = SIGNAL_STRENGTH_POOR; 1516 else bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1517 } else { 1518 int asu = signalStrength.getGsmSignalStrength(); 1519 if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1520 else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT; 1521 else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD; 1522 else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE; 1523 else bin = SIGNAL_STRENGTH_POOR; 1524 } 1525 if (mPhoneSignalStrengthBin != bin) { 1526 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_SIGNAL_STRENGTH_MASK) 1527 | (bin << HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT); 1528 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + bin + " to: " 1529 + Integer.toHexString(mHistoryCur.states)); 1530 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1531 if (mPhoneSignalStrengthBin >= 0) { 1532 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this); 1533 } 1534 mPhoneSignalStrengthBin = bin; 1535 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this); 1536 } 1537 } 1538 1539 public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) { 1540 int bin = DATA_CONNECTION_NONE; 1541 if (hasData) { 1542 switch (dataType) { 1543 case TelephonyManager.NETWORK_TYPE_EDGE: 1544 bin = DATA_CONNECTION_EDGE; 1545 break; 1546 case TelephonyManager.NETWORK_TYPE_GPRS: 1547 bin = DATA_CONNECTION_GPRS; 1548 break; 1549 case TelephonyManager.NETWORK_TYPE_UMTS: 1550 bin = DATA_CONNECTION_UMTS; 1551 break; 1552 case TelephonyManager.NETWORK_TYPE_CDMA: 1553 bin = DATA_CONNECTION_CDMA; 1554 break; 1555 case TelephonyManager.NETWORK_TYPE_EVDO_0: 1556 bin = DATA_CONNECTION_EVDO_0; 1557 break; 1558 case TelephonyManager.NETWORK_TYPE_EVDO_A: 1559 bin = DATA_CONNECTION_EVDO_A; 1560 break; 1561 case TelephonyManager.NETWORK_TYPE_1xRTT: 1562 bin = DATA_CONNECTION_1xRTT; 1563 break; 1564 case TelephonyManager.NETWORK_TYPE_HSDPA: 1565 bin = DATA_CONNECTION_HSDPA; 1566 break; 1567 case TelephonyManager.NETWORK_TYPE_HSUPA: 1568 bin = DATA_CONNECTION_HSUPA; 1569 break; 1570 case TelephonyManager.NETWORK_TYPE_HSPA: 1571 bin = DATA_CONNECTION_HSPA; 1572 break; 1573 case TelephonyManager.NETWORK_TYPE_IDEN: 1574 bin = DATA_CONNECTION_IDEN; 1575 break; 1576 case TelephonyManager.NETWORK_TYPE_EVDO_B: 1577 bin = DATA_CONNECTION_EVDO_B; 1578 break; 1579 default: 1580 bin = DATA_CONNECTION_OTHER; 1581 break; 1582 } 1583 } 1584 if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData); 1585 if (mPhoneDataConnectionType != bin) { 1586 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK) 1587 | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT); 1588 if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: " 1589 + Integer.toHexString(mHistoryCur.states)); 1590 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1591 if (mPhoneDataConnectionType >= 0) { 1592 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this); 1593 } 1594 mPhoneDataConnectionType = bin; 1595 mPhoneDataConnectionsTimer[bin].startRunningLocked(this); 1596 } 1597 } 1598 1599 public void noteWifiOnLocked(int uid) { 1600 if (!mWifiOn) { 1601 mHistoryCur.states |= HistoryItem.STATE_WIFI_ON_FLAG; 1602 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: " 1603 + Integer.toHexString(mHistoryCur.states)); 1604 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1605 mWifiOn = true; 1606 mWifiOnTimer.startRunningLocked(this); 1607 } 1608 if (mWifiOnUid != uid) { 1609 if (mWifiOnUid >= 0) { 1610 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked(); 1611 } 1612 mWifiOnUid = uid; 1613 getUidStatsLocked(uid).noteWifiTurnedOnLocked(); 1614 } 1615 } 1616 1617 public void noteWifiOffLocked(int uid) { 1618 if (mWifiOn) { 1619 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_ON_FLAG; 1620 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: " 1621 + Integer.toHexString(mHistoryCur.states)); 1622 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1623 mWifiOn = false; 1624 mWifiOnTimer.stopRunningLocked(this); 1625 } 1626 if (mWifiOnUid >= 0) { 1627 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked(); 1628 mWifiOnUid = -1; 1629 } 1630 } 1631 1632 public void noteAudioOnLocked(int uid) { 1633 if (!mAudioOn) { 1634 mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG; 1635 if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: " 1636 + Integer.toHexString(mHistoryCur.states)); 1637 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1638 mAudioOn = true; 1639 mAudioOnTimer.startRunningLocked(this); 1640 } 1641 getUidStatsLocked(uid).noteAudioTurnedOnLocked(); 1642 } 1643 1644 public void noteAudioOffLocked(int uid) { 1645 if (mAudioOn) { 1646 mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG; 1647 if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: " 1648 + Integer.toHexString(mHistoryCur.states)); 1649 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1650 mAudioOn = false; 1651 mAudioOnTimer.stopRunningLocked(this); 1652 } 1653 getUidStatsLocked(uid).noteAudioTurnedOffLocked(); 1654 } 1655 1656 public void noteVideoOnLocked(int uid) { 1657 if (!mVideoOn) { 1658 mHistoryCur.states |= HistoryItem.STATE_VIDEO_ON_FLAG; 1659 if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: " 1660 + Integer.toHexString(mHistoryCur.states)); 1661 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1662 mVideoOn = true; 1663 mVideoOnTimer.startRunningLocked(this); 1664 } 1665 getUidStatsLocked(uid).noteVideoTurnedOnLocked(); 1666 } 1667 1668 public void noteVideoOffLocked(int uid) { 1669 if (mVideoOn) { 1670 mHistoryCur.states &= ~HistoryItem.STATE_VIDEO_ON_FLAG; 1671 if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: " 1672 + Integer.toHexString(mHistoryCur.states)); 1673 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1674 mVideoOn = false; 1675 mVideoOnTimer.stopRunningLocked(this); 1676 } 1677 getUidStatsLocked(uid).noteVideoTurnedOffLocked(); 1678 } 1679 1680 public void noteWifiRunningLocked() { 1681 if (!mWifiRunning) { 1682 mHistoryCur.states |= HistoryItem.STATE_WIFI_RUNNING_FLAG; 1683 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: " 1684 + Integer.toHexString(mHistoryCur.states)); 1685 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1686 mWifiRunning = true; 1687 mWifiRunningTimer.startRunningLocked(this); 1688 } 1689 } 1690 1691 public void noteWifiStoppedLocked() { 1692 if (mWifiRunning) { 1693 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RUNNING_FLAG; 1694 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: " 1695 + Integer.toHexString(mHistoryCur.states)); 1696 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1697 mWifiRunning = false; 1698 mWifiRunningTimer.stopRunningLocked(this); 1699 } 1700 } 1701 1702 public void noteBluetoothOnLocked() { 1703 if (!mBluetoothOn) { 1704 mHistoryCur.states |= HistoryItem.STATE_BLUETOOTH_ON_FLAG; 1705 if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth on to: " 1706 + Integer.toHexString(mHistoryCur.states)); 1707 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1708 mBluetoothOn = true; 1709 mBluetoothOnTimer.startRunningLocked(this); 1710 } 1711 } 1712 1713 public void noteBluetoothOffLocked() { 1714 if (mBluetoothOn) { 1715 mHistoryCur.states &= ~HistoryItem.STATE_BLUETOOTH_ON_FLAG; 1716 if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth off to: " 1717 + Integer.toHexString(mHistoryCur.states)); 1718 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1719 mBluetoothOn = false; 1720 mBluetoothOnTimer.stopRunningLocked(this); 1721 } 1722 } 1723 1724 int mWifiFullLockNesting = 0; 1725 1726 public void noteFullWifiLockAcquiredLocked(int uid) { 1727 if (mWifiFullLockNesting == 0) { 1728 mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG; 1729 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: " 1730 + Integer.toHexString(mHistoryCur.states)); 1731 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1732 } 1733 mWifiFullLockNesting++; 1734 getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(); 1735 } 1736 1737 public void noteFullWifiLockReleasedLocked(int uid) { 1738 mWifiFullLockNesting--; 1739 if (mWifiFullLockNesting == 0) { 1740 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG; 1741 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: " 1742 + Integer.toHexString(mHistoryCur.states)); 1743 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1744 } 1745 getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(); 1746 } 1747 1748 int mWifiScanLockNesting = 0; 1749 1750 public void noteScanWifiLockAcquiredLocked(int uid) { 1751 if (mWifiScanLockNesting == 0) { 1752 mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG; 1753 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock on to: " 1754 + Integer.toHexString(mHistoryCur.states)); 1755 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1756 } 1757 mWifiScanLockNesting++; 1758 getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked(); 1759 } 1760 1761 public void noteScanWifiLockReleasedLocked(int uid) { 1762 mWifiScanLockNesting--; 1763 if (mWifiScanLockNesting == 0) { 1764 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG; 1765 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock off to: " 1766 + Integer.toHexString(mHistoryCur.states)); 1767 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1768 } 1769 getUidStatsLocked(uid).noteScanWifiLockReleasedLocked(); 1770 } 1771 1772 int mWifiMulticastNesting = 0; 1773 1774 public void noteWifiMulticastEnabledLocked(int uid) { 1775 if (mWifiMulticastNesting == 0) { 1776 mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG; 1777 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: " 1778 + Integer.toHexString(mHistoryCur.states)); 1779 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1780 } 1781 mWifiMulticastNesting++; 1782 getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(); 1783 } 1784 1785 public void noteWifiMulticastDisabledLocked(int uid) { 1786 mWifiMulticastNesting--; 1787 if (mWifiMulticastNesting == 0) { 1788 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG; 1789 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: " 1790 + Integer.toHexString(mHistoryCur.states)); 1791 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 1792 } 1793 getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(); 1794 } 1795 1796 @Override public long getScreenOnTime(long batteryRealtime, int which) { 1797 return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which); 1798 } 1799 1800 @Override public long getScreenBrightnessTime(int brightnessBin, 1801 long batteryRealtime, int which) { 1802 return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked( 1803 batteryRealtime, which); 1804 } 1805 1806 @Override public int getInputEventCount(int which) { 1807 return mInputEventCounter.getCountLocked(which); 1808 } 1809 1810 @Override public long getPhoneOnTime(long batteryRealtime, int which) { 1811 return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which); 1812 } 1813 1814 @Override public long getPhoneSignalStrengthTime(int strengthBin, 1815 long batteryRealtime, int which) { 1816 return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked( 1817 batteryRealtime, which); 1818 } 1819 1820 @Override public long getPhoneSignalScanningTime( 1821 long batteryRealtime, int which) { 1822 return mPhoneSignalScanningTimer.getTotalTimeLocked( 1823 batteryRealtime, which); 1824 } 1825 1826 @Override public int getPhoneSignalStrengthCount(int dataType, int which) { 1827 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1828 } 1829 1830 @Override public long getPhoneDataConnectionTime(int dataType, 1831 long batteryRealtime, int which) { 1832 return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked( 1833 batteryRealtime, which); 1834 } 1835 1836 @Override public int getPhoneDataConnectionCount(int dataType, int which) { 1837 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1838 } 1839 1840 @Override public long getWifiOnTime(long batteryRealtime, int which) { 1841 return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which); 1842 } 1843 1844 @Override public long getWifiRunningTime(long batteryRealtime, int which) { 1845 return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which); 1846 } 1847 1848 @Override public long getBluetoothOnTime(long batteryRealtime, int which) { 1849 return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which); 1850 } 1851 1852 @Override public boolean getIsOnBattery() { 1853 return mOnBattery; 1854 } 1855 1856 @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() { 1857 return mUidStats; 1858 } 1859 1860 /** 1861 * The statistics associated with a particular uid. 1862 */ 1863 public final class Uid extends BatteryStats.Uid { 1864 1865 final int mUid; 1866 long mLoadedTcpBytesReceived; 1867 long mLoadedTcpBytesSent; 1868 long mCurrentTcpBytesReceived; 1869 long mCurrentTcpBytesSent; 1870 long mTcpBytesReceivedAtLastUnplug; 1871 long mTcpBytesSentAtLastUnplug; 1872 1873 // These are not saved/restored when parcelling, since we want 1874 // to return from the parcel with a snapshot of the state. 1875 long mStartedTcpBytesReceived = -1; 1876 long mStartedTcpBytesSent = -1; 1877 1878 boolean mWifiTurnedOn; 1879 StopwatchTimer mWifiTurnedOnTimer; 1880 1881 boolean mFullWifiLockOut; 1882 StopwatchTimer mFullWifiLockTimer; 1883 1884 boolean mScanWifiLockOut; 1885 StopwatchTimer mScanWifiLockTimer; 1886 1887 boolean mWifiMulticastEnabled; 1888 StopwatchTimer mWifiMulticastTimer; 1889 1890 boolean mAudioTurnedOn; 1891 StopwatchTimer mAudioTurnedOnTimer; 1892 1893 boolean mVideoTurnedOn; 1894 StopwatchTimer mVideoTurnedOnTimer; 1895 1896 Counter[] mUserActivityCounters; 1897 1898 /** 1899 * The statistics we have collected for this uid's wake locks. 1900 */ 1901 final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>(); 1902 1903 /** 1904 * The statistics we have collected for this uid's sensor activations. 1905 */ 1906 final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>(); 1907 1908 /** 1909 * The statistics we have collected for this uid's processes. 1910 */ 1911 final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>(); 1912 1913 /** 1914 * The statistics we have collected for this uid's processes. 1915 */ 1916 final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>(); 1917 1918 /** 1919 * The transient wake stats we have collected for this uid's pids. 1920 */ 1921 final SparseArray<Pid> mPids = new SparseArray<Pid>(); 1922 1923 public Uid(int uid) { 1924 mUid = uid; 1925 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables); 1926 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables); 1927 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables); 1928 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1929 null, mUnpluggables); 1930 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables); 1931 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables); 1932 } 1933 1934 @Override 1935 public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() { 1936 return mWakelockStats; 1937 } 1938 1939 @Override 1940 public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() { 1941 return mSensorStats; 1942 } 1943 1944 @Override 1945 public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() { 1946 return mProcessStats; 1947 } 1948 1949 @Override 1950 public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { 1951 return mPackageStats; 1952 } 1953 1954 @Override 1955 public int getUid() { 1956 return mUid; 1957 } 1958 1959 @Override 1960 public long getTcpBytesReceived(int which) { 1961 if (which == STATS_LAST) { 1962 return mLoadedTcpBytesReceived; 1963 } else { 1964 long current = computeCurrentTcpBytesReceived(); 1965 if (which == STATS_SINCE_UNPLUGGED) { 1966 current -= mTcpBytesReceivedAtLastUnplug; 1967 } else if (which == STATS_SINCE_CHARGED) { 1968 current += mLoadedTcpBytesReceived; 1969 } 1970 return current; 1971 } 1972 } 1973 1974 public long computeCurrentTcpBytesReceived() { 1975 return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0 1976 ? (TrafficStats.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0); 1977 } 1978 1979 @Override 1980 public long getTcpBytesSent(int which) { 1981 if (which == STATS_LAST) { 1982 return mLoadedTcpBytesSent; 1983 } else { 1984 long current = computeCurrentTcpBytesSent(); 1985 if (which == STATS_SINCE_UNPLUGGED) { 1986 current -= mTcpBytesSentAtLastUnplug; 1987 } else if (which == STATS_SINCE_CHARGED) { 1988 current += mLoadedTcpBytesSent; 1989 } 1990 return current; 1991 } 1992 } 1993 1994 @Override 1995 public void noteWifiTurnedOnLocked() { 1996 if (!mWifiTurnedOn) { 1997 mWifiTurnedOn = true; 1998 if (mWifiTurnedOnTimer == null) { 1999 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, 2000 null, mUnpluggables); 2001 } 2002 mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 2003 } 2004 } 2005 2006 @Override 2007 public void noteWifiTurnedOffLocked() { 2008 if (mWifiTurnedOn) { 2009 mWifiTurnedOn = false; 2010 mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 2011 } 2012 } 2013 2014 @Override 2015 public void noteFullWifiLockAcquiredLocked() { 2016 if (!mFullWifiLockOut) { 2017 mFullWifiLockOut = true; 2018 if (mFullWifiLockTimer == null) { 2019 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, 2020 null, mUnpluggables); 2021 } 2022 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 2023 } 2024 } 2025 2026 @Override 2027 public void noteFullWifiLockReleasedLocked() { 2028 if (mFullWifiLockOut) { 2029 mFullWifiLockOut = false; 2030 mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 2031 } 2032 } 2033 2034 @Override 2035 public void noteScanWifiLockAcquiredLocked() { 2036 if (!mScanWifiLockOut) { 2037 mScanWifiLockOut = true; 2038 if (mScanWifiLockTimer == null) { 2039 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, 2040 null, mUnpluggables); 2041 } 2042 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 2043 } 2044 } 2045 2046 @Override 2047 public void noteScanWifiLockReleasedLocked() { 2048 if (mScanWifiLockOut) { 2049 mScanWifiLockOut = false; 2050 mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 2051 } 2052 } 2053 2054 @Override 2055 public void noteWifiMulticastEnabledLocked() { 2056 if (!mWifiMulticastEnabled) { 2057 mWifiMulticastEnabled = true; 2058 if (mWifiMulticastTimer == null) { 2059 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 2060 null, mUnpluggables); 2061 } 2062 mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this); 2063 } 2064 } 2065 2066 @Override 2067 public void noteWifiMulticastDisabledLocked() { 2068 if (mWifiMulticastEnabled) { 2069 mWifiMulticastEnabled = false; 2070 mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this); 2071 } 2072 } 2073 2074 @Override 2075 public void noteAudioTurnedOnLocked() { 2076 if (!mAudioTurnedOn) { 2077 mAudioTurnedOn = true; 2078 if (mAudioTurnedOnTimer == null) { 2079 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, 2080 null, mUnpluggables); 2081 } 2082 mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 2083 } 2084 } 2085 2086 @Override 2087 public void noteAudioTurnedOffLocked() { 2088 if (mAudioTurnedOn) { 2089 mAudioTurnedOn = false; 2090 mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 2091 } 2092 } 2093 2094 @Override 2095 public void noteVideoTurnedOnLocked() { 2096 if (!mVideoTurnedOn) { 2097 mVideoTurnedOn = true; 2098 if (mVideoTurnedOnTimer == null) { 2099 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, 2100 null, mUnpluggables); 2101 } 2102 mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 2103 } 2104 } 2105 2106 @Override 2107 public void noteVideoTurnedOffLocked() { 2108 if (mVideoTurnedOn) { 2109 mVideoTurnedOn = false; 2110 mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 2111 } 2112 } 2113 2114 @Override 2115 public long getWifiTurnedOnTime(long batteryRealtime, int which) { 2116 if (mWifiTurnedOnTimer == null) { 2117 return 0; 2118 } 2119 return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 2120 } 2121 2122 @Override 2123 public long getFullWifiLockTime(long batteryRealtime, int which) { 2124 if (mFullWifiLockTimer == null) { 2125 return 0; 2126 } 2127 return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 2128 } 2129 2130 @Override 2131 public long getScanWifiLockTime(long batteryRealtime, int which) { 2132 if (mScanWifiLockTimer == null) { 2133 return 0; 2134 } 2135 return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 2136 } 2137 2138 @Override 2139 public long getWifiMulticastTime(long batteryRealtime, int which) { 2140 if (mWifiMulticastTimer == null) { 2141 return 0; 2142 } 2143 return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime, 2144 which); 2145 } 2146 2147 @Override 2148 public long getAudioTurnedOnTime(long batteryRealtime, int which) { 2149 if (mAudioTurnedOnTimer == null) { 2150 return 0; 2151 } 2152 return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 2153 } 2154 2155 @Override 2156 public long getVideoTurnedOnTime(long batteryRealtime, int which) { 2157 if (mVideoTurnedOnTimer == null) { 2158 return 0; 2159 } 2160 return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 2161 } 2162 2163 @Override 2164 public void noteUserActivityLocked(int type) { 2165 if (mUserActivityCounters == null) { 2166 initUserActivityLocked(); 2167 } 2168 if (type < 0) type = 0; 2169 else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1; 2170 mUserActivityCounters[type].stepAtomic(); 2171 } 2172 2173 @Override 2174 public boolean hasUserActivity() { 2175 return mUserActivityCounters != null; 2176 } 2177 2178 @Override 2179 public int getUserActivityCount(int type, int which) { 2180 if (mUserActivityCounters == null) { 2181 return 0; 2182 } 2183 return mUserActivityCounters[type].getCountLocked(which); 2184 } 2185 2186 void initUserActivityLocked() { 2187 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 2188 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 2189 mUserActivityCounters[i] = new Counter(mUnpluggables); 2190 } 2191 } 2192 2193 public long computeCurrentTcpBytesSent() { 2194 return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0 2195 ? (TrafficStats.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0); 2196 } 2197 2198 /** 2199 * Clear all stats for this uid. Returns true if the uid is completely 2200 * inactive so can be dropped. 2201 */ 2202 boolean reset() { 2203 boolean active = false; 2204 2205 if (mWifiTurnedOnTimer != null) { 2206 active |= !mWifiTurnedOnTimer.reset(BatteryStatsImpl.this, false); 2207 active |= mWifiTurnedOn; 2208 } 2209 if (mFullWifiLockTimer != null) { 2210 active |= !mFullWifiLockTimer.reset(BatteryStatsImpl.this, false); 2211 active |= mFullWifiLockOut; 2212 } 2213 if (mScanWifiLockTimer != null) { 2214 active |= !mScanWifiLockTimer.reset(BatteryStatsImpl.this, false); 2215 active |= mScanWifiLockOut; 2216 } 2217 if (mWifiMulticastTimer != null) { 2218 active |= !mWifiMulticastTimer.reset(BatteryStatsImpl.this, false); 2219 active |= mWifiMulticastEnabled; 2220 } 2221 if (mAudioTurnedOnTimer != null) { 2222 active |= !mAudioTurnedOnTimer.reset(BatteryStatsImpl.this, false); 2223 active |= mAudioTurnedOn; 2224 } 2225 if (mVideoTurnedOnTimer != null) { 2226 active |= !mVideoTurnedOnTimer.reset(BatteryStatsImpl.this, false); 2227 active |= mVideoTurnedOn; 2228 } 2229 2230 mLoadedTcpBytesReceived = mLoadedTcpBytesSent = 0; 2231 mCurrentTcpBytesReceived = mCurrentTcpBytesSent = 0; 2232 2233 if (mUserActivityCounters != null) { 2234 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 2235 mUserActivityCounters[i].reset(false); 2236 } 2237 } 2238 2239 if (mWakelockStats.size() > 0) { 2240 Iterator<Map.Entry<String, Wakelock>> it = mWakelockStats.entrySet().iterator(); 2241 while (it.hasNext()) { 2242 Map.Entry<String, Wakelock> wakelockEntry = it.next(); 2243 Wakelock wl = wakelockEntry.getValue(); 2244 if (wl.reset()) { 2245 it.remove(); 2246 } else { 2247 active = true; 2248 } 2249 } 2250 } 2251 if (mSensorStats.size() > 0) { 2252 Iterator<Map.Entry<Integer, Sensor>> it = mSensorStats.entrySet().iterator(); 2253 while (it.hasNext()) { 2254 Map.Entry<Integer, Sensor> sensorEntry = it.next(); 2255 Sensor s = sensorEntry.getValue(); 2256 if (s.reset()) { 2257 it.remove(); 2258 } else { 2259 active = true; 2260 } 2261 } 2262 } 2263 if (mProcessStats.size() > 0) { 2264 Iterator<Map.Entry<String, Proc>> it = mProcessStats.entrySet().iterator(); 2265 while (it.hasNext()) { 2266 Map.Entry<String, Proc> procEntry = it.next(); 2267 procEntry.getValue().detach(); 2268 } 2269 mProcessStats.clear(); 2270 } 2271 if (mPids.size() > 0) { 2272 for (int i=0; !active && i<mPids.size(); i++) { 2273 Pid pid = mPids.valueAt(i); 2274 if (pid.mWakeStart != 0) { 2275 active = true; 2276 } 2277 } 2278 } 2279 if (mPackageStats.size() > 0) { 2280 Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator(); 2281 while (it.hasNext()) { 2282 Map.Entry<String, Pkg> pkgEntry = it.next(); 2283 Pkg p = pkgEntry.getValue(); 2284 p.detach(); 2285 if (p.mServiceStats.size() > 0) { 2286 Iterator<Map.Entry<String, Pkg.Serv>> it2 2287 = p.mServiceStats.entrySet().iterator(); 2288 while (it2.hasNext()) { 2289 Map.Entry<String, Pkg.Serv> servEntry = it2.next(); 2290 servEntry.getValue().detach(); 2291 } 2292 } 2293 } 2294 mPackageStats.clear(); 2295 } 2296 2297 mPids.clear(); 2298 2299 if (!active) { 2300 if (mWifiTurnedOnTimer != null) { 2301 mWifiTurnedOnTimer.detach(); 2302 } 2303 if (mFullWifiLockTimer != null) { 2304 mFullWifiLockTimer.detach(); 2305 } 2306 if (mScanWifiLockTimer != null) { 2307 mScanWifiLockTimer.detach(); 2308 } 2309 if (mWifiMulticastTimer != null) { 2310 mWifiMulticastTimer.detach(); 2311 } 2312 if (mAudioTurnedOnTimer != null) { 2313 mAudioTurnedOnTimer.detach(); 2314 } 2315 if (mVideoTurnedOnTimer != null) { 2316 mVideoTurnedOnTimer.detach(); 2317 } 2318 if (mUserActivityCounters != null) { 2319 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 2320 mUserActivityCounters[i].detach(); 2321 } 2322 } 2323 } 2324 2325 return !active; 2326 } 2327 2328 void writeToParcelLocked(Parcel out, long batteryRealtime) { 2329 out.writeInt(mWakelockStats.size()); 2330 for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) { 2331 out.writeString(wakelockEntry.getKey()); 2332 Uid.Wakelock wakelock = wakelockEntry.getValue(); 2333 wakelock.writeToParcelLocked(out, batteryRealtime); 2334 } 2335 2336 out.writeInt(mSensorStats.size()); 2337 for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) { 2338 out.writeInt(sensorEntry.getKey()); 2339 Uid.Sensor sensor = sensorEntry.getValue(); 2340 sensor.writeToParcelLocked(out, batteryRealtime); 2341 } 2342 2343 out.writeInt(mProcessStats.size()); 2344 for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) { 2345 out.writeString(procEntry.getKey()); 2346 Uid.Proc proc = procEntry.getValue(); 2347 proc.writeToParcelLocked(out); 2348 } 2349 2350 out.writeInt(mPackageStats.size()); 2351 for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) { 2352 out.writeString(pkgEntry.getKey()); 2353 Uid.Pkg pkg = pkgEntry.getValue(); 2354 pkg.writeToParcelLocked(out); 2355 } 2356 2357 out.writeLong(mLoadedTcpBytesReceived); 2358 out.writeLong(mLoadedTcpBytesSent); 2359 out.writeLong(computeCurrentTcpBytesReceived()); 2360 out.writeLong(computeCurrentTcpBytesSent()); 2361 out.writeLong(mTcpBytesReceivedAtLastUnplug); 2362 out.writeLong(mTcpBytesSentAtLastUnplug); 2363 if (mWifiTurnedOnTimer != null) { 2364 out.writeInt(1); 2365 mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime); 2366 } else { 2367 out.writeInt(0); 2368 } 2369 if (mFullWifiLockTimer != null) { 2370 out.writeInt(1); 2371 mFullWifiLockTimer.writeToParcel(out, batteryRealtime); 2372 } else { 2373 out.writeInt(0); 2374 } 2375 if (mScanWifiLockTimer != null) { 2376 out.writeInt(1); 2377 mScanWifiLockTimer.writeToParcel(out, batteryRealtime); 2378 } else { 2379 out.writeInt(0); 2380 } 2381 if (mWifiMulticastTimer != null) { 2382 out.writeInt(1); 2383 mWifiMulticastTimer.writeToParcel(out, batteryRealtime); 2384 } else { 2385 out.writeInt(0); 2386 } 2387 if (mAudioTurnedOnTimer != null) { 2388 out.writeInt(1); 2389 mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime); 2390 } else { 2391 out.writeInt(0); 2392 } 2393 if (mVideoTurnedOnTimer != null) { 2394 out.writeInt(1); 2395 mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime); 2396 } else { 2397 out.writeInt(0); 2398 } 2399 if (mUserActivityCounters != null) { 2400 out.writeInt(1); 2401 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 2402 mUserActivityCounters[i].writeToParcel(out); 2403 } 2404 } else { 2405 out.writeInt(0); 2406 } 2407 } 2408 2409 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 2410 int numWakelocks = in.readInt(); 2411 mWakelockStats.clear(); 2412 for (int j = 0; j < numWakelocks; j++) { 2413 String wakelockName = in.readString(); 2414 Uid.Wakelock wakelock = new Wakelock(); 2415 wakelock.readFromParcelLocked(unpluggables, in); 2416 if (mWakelockStats.size() < MAX_WAKELOCKS_PER_UID) { 2417 // We will just drop some random set of wakelocks if 2418 // the previous run of the system was an older version 2419 // that didn't impose a limit. 2420 mWakelockStats.put(wakelockName, wakelock); 2421 } 2422 } 2423 2424 int numSensors = in.readInt(); 2425 mSensorStats.clear(); 2426 for (int k = 0; k < numSensors; k++) { 2427 int sensorNumber = in.readInt(); 2428 Uid.Sensor sensor = new Sensor(sensorNumber); 2429 sensor.readFromParcelLocked(mUnpluggables, in); 2430 mSensorStats.put(sensorNumber, sensor); 2431 } 2432 2433 int numProcs = in.readInt(); 2434 mProcessStats.clear(); 2435 for (int k = 0; k < numProcs; k++) { 2436 String processName = in.readString(); 2437 Uid.Proc proc = new Proc(); 2438 proc.readFromParcelLocked(in); 2439 mProcessStats.put(processName, proc); 2440 } 2441 2442 int numPkgs = in.readInt(); 2443 mPackageStats.clear(); 2444 for (int l = 0; l < numPkgs; l++) { 2445 String packageName = in.readString(); 2446 Uid.Pkg pkg = new Pkg(); 2447 pkg.readFromParcelLocked(in); 2448 mPackageStats.put(packageName, pkg); 2449 } 2450 2451 mLoadedTcpBytesReceived = in.readLong(); 2452 mLoadedTcpBytesSent = in.readLong(); 2453 mCurrentTcpBytesReceived = in.readLong(); 2454 mCurrentTcpBytesSent = in.readLong(); 2455 mTcpBytesReceivedAtLastUnplug = in.readLong(); 2456 mTcpBytesSentAtLastUnplug = in.readLong(); 2457 mWifiTurnedOn = false; 2458 if (in.readInt() != 0) { 2459 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, 2460 null, mUnpluggables, in); 2461 } else { 2462 mWifiTurnedOnTimer = null; 2463 } 2464 mFullWifiLockOut = false; 2465 if (in.readInt() != 0) { 2466 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, 2467 null, mUnpluggables, in); 2468 } else { 2469 mFullWifiLockTimer = null; 2470 } 2471 mScanWifiLockOut = false; 2472 if (in.readInt() != 0) { 2473 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, 2474 null, mUnpluggables, in); 2475 } else { 2476 mScanWifiLockTimer = null; 2477 } 2478 mWifiMulticastEnabled = false; 2479 if (in.readInt() != 0) { 2480 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 2481 null, mUnpluggables, in); 2482 } else { 2483 mWifiMulticastTimer = null; 2484 } 2485 mAudioTurnedOn = false; 2486 if (in.readInt() != 0) { 2487 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, 2488 null, mUnpluggables, in); 2489 } else { 2490 mAudioTurnedOnTimer = null; 2491 } 2492 mVideoTurnedOn = false; 2493 if (in.readInt() != 0) { 2494 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, 2495 null, mUnpluggables, in); 2496 } else { 2497 mVideoTurnedOnTimer = null; 2498 } 2499 if (in.readInt() != 0) { 2500 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 2501 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 2502 mUserActivityCounters[i] = new Counter(mUnpluggables, in); 2503 } 2504 } else { 2505 mUserActivityCounters = null; 2506 } 2507 } 2508 2509 /** 2510 * The statistics associated with a particular wake lock. 2511 */ 2512 public final class Wakelock extends BatteryStats.Uid.Wakelock { 2513 /** 2514 * How long (in ms) this uid has been keeping the device partially awake. 2515 */ 2516 StopwatchTimer mTimerPartial; 2517 2518 /** 2519 * How long (in ms) this uid has been keeping the device fully awake. 2520 */ 2521 StopwatchTimer mTimerFull; 2522 2523 /** 2524 * How long (in ms) this uid has had a window keeping the device awake. 2525 */ 2526 StopwatchTimer mTimerWindow; 2527 2528 /** 2529 * Reads a possibly null Timer from a Parcel. The timer is associated with the 2530 * proper timer pool from the given BatteryStatsImpl object. 2531 * 2532 * @param in the Parcel to be read from. 2533 * return a new Timer, or null. 2534 */ 2535 private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, 2536 ArrayList<Unpluggable> unpluggables, Parcel in) { 2537 if (in.readInt() == 0) { 2538 return null; 2539 } 2540 2541 return new StopwatchTimer(type, pool, unpluggables, in); 2542 } 2543 2544 boolean reset() { 2545 boolean wlactive = false; 2546 if (mTimerFull != null) { 2547 wlactive |= !mTimerFull.reset(BatteryStatsImpl.this, false); 2548 } 2549 if (mTimerPartial != null) { 2550 wlactive |= !mTimerPartial.reset(BatteryStatsImpl.this, false); 2551 } 2552 if (mTimerWindow != null) { 2553 wlactive |= !mTimerWindow.reset(BatteryStatsImpl.this, false); 2554 } 2555 if (!wlactive) { 2556 if (mTimerFull != null) { 2557 mTimerFull.detach(); 2558 mTimerFull = null; 2559 } 2560 if (mTimerPartial != null) { 2561 mTimerPartial.detach(); 2562 mTimerPartial = null; 2563 } 2564 if (mTimerWindow != null) { 2565 mTimerWindow.detach(); 2566 mTimerWindow = null; 2567 } 2568 } 2569 return !wlactive; 2570 } 2571 2572 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 2573 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL, 2574 mPartialTimers, unpluggables, in); 2575 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, 2576 mFullTimers, unpluggables, in); 2577 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, 2578 mWindowTimers, unpluggables, in); 2579 } 2580 2581 void writeToParcelLocked(Parcel out, long batteryRealtime) { 2582 Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime); 2583 Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime); 2584 Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime); 2585 } 2586 2587 @Override 2588 public Timer getWakeTime(int type) { 2589 switch (type) { 2590 case WAKE_TYPE_FULL: return mTimerFull; 2591 case WAKE_TYPE_PARTIAL: return mTimerPartial; 2592 case WAKE_TYPE_WINDOW: return mTimerWindow; 2593 default: throw new IllegalArgumentException("type = " + type); 2594 } 2595 } 2596 } 2597 2598 public final class Sensor extends BatteryStats.Uid.Sensor { 2599 final int mHandle; 2600 StopwatchTimer mTimer; 2601 2602 public Sensor(int handle) { 2603 mHandle = handle; 2604 } 2605 2606 private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables, 2607 Parcel in) { 2608 if (in.readInt() == 0) { 2609 return null; 2610 } 2611 2612 ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle); 2613 if (pool == null) { 2614 pool = new ArrayList<StopwatchTimer>(); 2615 mSensorTimers.put(mHandle, pool); 2616 } 2617 return new StopwatchTimer(0, pool, unpluggables, in); 2618 } 2619 2620 boolean reset() { 2621 if (mTimer.reset(BatteryStatsImpl.this, true)) { 2622 mTimer = null; 2623 return true; 2624 } 2625 return false; 2626 } 2627 2628 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 2629 mTimer = readTimerFromParcel(unpluggables, in); 2630 } 2631 2632 void writeToParcelLocked(Parcel out, long batteryRealtime) { 2633 Timer.writeTimerToParcel(out, mTimer, batteryRealtime); 2634 } 2635 2636 @Override 2637 public Timer getSensorTime() { 2638 return mTimer; 2639 } 2640 2641 @Override 2642 public int getHandle() { 2643 return mHandle; 2644 } 2645 } 2646 2647 /** 2648 * The statistics associated with a particular process. 2649 */ 2650 public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable { 2651 /** 2652 * Total time (in 1/100 sec) spent executing in user code. 2653 */ 2654 long mUserTime; 2655 2656 /** 2657 * Total time (in 1/100 sec) spent executing in kernel code. 2658 */ 2659 long mSystemTime; 2660 2661 /** 2662 * Number of times the process has been started. 2663 */ 2664 int mStarts; 2665 2666 /** 2667 * Amount of time the process was running in the foreground. 2668 */ 2669 long mForegroundTime; 2670 2671 /** 2672 * The amount of user time loaded from a previous save. 2673 */ 2674 long mLoadedUserTime; 2675 2676 /** 2677 * The amount of system time loaded from a previous save. 2678 */ 2679 long mLoadedSystemTime; 2680 2681 /** 2682 * The number of times the process has started from a previous save. 2683 */ 2684 int mLoadedStarts; 2685 2686 /** 2687 * The amount of foreground time loaded from a previous save. 2688 */ 2689 long mLoadedForegroundTime; 2690 2691 /** 2692 * The amount of user time loaded from the previous run. 2693 */ 2694 long mLastUserTime; 2695 2696 /** 2697 * The amount of system time loaded from the previous run. 2698 */ 2699 long mLastSystemTime; 2700 2701 /** 2702 * The number of times the process has started from the previous run. 2703 */ 2704 int mLastStarts; 2705 2706 /** 2707 * The amount of foreground time loaded from the previous run 2708 */ 2709 long mLastForegroundTime; 2710 2711 /** 2712 * The amount of user time when last unplugged. 2713 */ 2714 long mUnpluggedUserTime; 2715 2716 /** 2717 * The amount of system time when last unplugged. 2718 */ 2719 long mUnpluggedSystemTime; 2720 2721 /** 2722 * The number of times the process has started before unplugged. 2723 */ 2724 int mUnpluggedStarts; 2725 2726 /** 2727 * The amount of foreground time since unplugged. 2728 */ 2729 long mUnpluggedForegroundTime; 2730 2731 SamplingCounter[] mSpeedBins; 2732 2733 ArrayList<ExcessiveWake> mExcessiveWake; 2734 2735 Proc() { 2736 mUnpluggables.add(this); 2737 mSpeedBins = new SamplingCounter[getCpuSpeedSteps()]; 2738 } 2739 2740 public void unplug(long batteryUptime, long batteryRealtime) { 2741 mUnpluggedUserTime = mUserTime; 2742 mUnpluggedSystemTime = mSystemTime; 2743 mUnpluggedStarts = mStarts; 2744 mUnpluggedForegroundTime = mForegroundTime; 2745 } 2746 2747 public void plug(long batteryUptime, long batteryRealtime) { 2748 } 2749 2750 void detach() { 2751 mUnpluggables.remove(this); 2752 for (int i = 0; i < mSpeedBins.length; i++) { 2753 SamplingCounter c = mSpeedBins[i]; 2754 if (c != null) { 2755 mUnpluggables.remove(c); 2756 mSpeedBins[i] = null; 2757 } 2758 } 2759 } 2760 2761 public int countExcessiveWakes() { 2762 return mExcessiveWake != null ? mExcessiveWake.size() : 0; 2763 } 2764 2765 public ExcessiveWake getExcessiveWake(int i) { 2766 if (mExcessiveWake != null) { 2767 return mExcessiveWake.get(i); 2768 } 2769 return null; 2770 } 2771 2772 public void addExcessiveWake(long overTime, long usedTime) { 2773 if (mExcessiveWake == null) { 2774 mExcessiveWake = new ArrayList<ExcessiveWake>(); 2775 } 2776 ExcessiveWake ew = new ExcessiveWake(); 2777 ew.overTime = overTime; 2778 ew.usedTime = usedTime; 2779 mExcessiveWake.add(ew); 2780 } 2781 2782 void writeExcessiveWakeToParcelLocked(Parcel out) { 2783 if (mExcessiveWake == null) { 2784 out.writeInt(0); 2785 return; 2786 } 2787 2788 final int N = mExcessiveWake.size(); 2789 out.writeInt(N); 2790 for (int i=0; i<N; i++) { 2791 ExcessiveWake ew = mExcessiveWake.get(i); 2792 out.writeLong(ew.overTime); 2793 out.writeLong(ew.usedTime); 2794 } 2795 } 2796 2797 void readExcessiveWakeFromParcelLocked(Parcel in) { 2798 final int N = in.readInt(); 2799 if (N == 0) { 2800 mExcessiveWake = null; 2801 return; 2802 } 2803 2804 mExcessiveWake = new ArrayList<ExcessiveWake>(); 2805 for (int i=0; i<N; i++) { 2806 ExcessiveWake ew = new ExcessiveWake(); 2807 ew.overTime = in.readLong(); 2808 ew.usedTime = in.readLong(); 2809 mExcessiveWake.add(ew); 2810 } 2811 } 2812 2813 void writeToParcelLocked(Parcel out) { 2814 out.writeLong(mUserTime); 2815 out.writeLong(mSystemTime); 2816 out.writeLong(mForegroundTime); 2817 out.writeInt(mStarts); 2818 out.writeLong(mLoadedUserTime); 2819 out.writeLong(mLoadedSystemTime); 2820 out.writeLong(mLoadedForegroundTime); 2821 out.writeInt(mLoadedStarts); 2822 out.writeLong(mUnpluggedUserTime); 2823 out.writeLong(mUnpluggedSystemTime); 2824 out.writeLong(mUnpluggedForegroundTime); 2825 out.writeInt(mUnpluggedStarts); 2826 2827 out.writeInt(mSpeedBins.length); 2828 for (int i = 0; i < mSpeedBins.length; i++) { 2829 SamplingCounter c = mSpeedBins[i]; 2830 if (c != null) { 2831 out.writeInt(1); 2832 c.writeToParcel(out); 2833 } else { 2834 out.writeInt(0); 2835 } 2836 } 2837 2838 writeExcessiveWakeToParcelLocked(out); 2839 } 2840 2841 void readFromParcelLocked(Parcel in) { 2842 mUserTime = in.readLong(); 2843 mSystemTime = in.readLong(); 2844 mForegroundTime = in.readLong(); 2845 mStarts = in.readInt(); 2846 mLoadedUserTime = in.readLong(); 2847 mLoadedSystemTime = in.readLong(); 2848 mLoadedForegroundTime = in.readLong(); 2849 mLoadedStarts = in.readInt(); 2850 mLastUserTime = 0; 2851 mLastSystemTime = 0; 2852 mLastForegroundTime = 0; 2853 mLastStarts = 0; 2854 mUnpluggedUserTime = in.readLong(); 2855 mUnpluggedSystemTime = in.readLong(); 2856 mUnpluggedForegroundTime = in.readLong(); 2857 mUnpluggedStarts = in.readInt(); 2858 2859 int bins = in.readInt(); 2860 int steps = getCpuSpeedSteps(); 2861 mSpeedBins = new SamplingCounter[bins >= steps ? bins : steps]; 2862 for (int i = 0; i < bins; i++) { 2863 if (in.readInt() != 0) { 2864 mSpeedBins[i] = new SamplingCounter(mUnpluggables, in); 2865 } 2866 } 2867 2868 readExcessiveWakeFromParcelLocked(in); 2869 } 2870 2871 public BatteryStatsImpl getBatteryStats() { 2872 return BatteryStatsImpl.this; 2873 } 2874 2875 public void addCpuTimeLocked(int utime, int stime) { 2876 mUserTime += utime; 2877 mSystemTime += stime; 2878 } 2879 2880 public void addForegroundTimeLocked(long ttime) { 2881 mForegroundTime += ttime; 2882 } 2883 2884 public void incStartsLocked() { 2885 mStarts++; 2886 } 2887 2888 @Override 2889 public long getUserTime(int which) { 2890 long val; 2891 if (which == STATS_LAST) { 2892 val = mLastUserTime; 2893 } else { 2894 val = mUserTime; 2895 if (which == STATS_CURRENT) { 2896 val -= mLoadedUserTime; 2897 } else if (which == STATS_SINCE_UNPLUGGED) { 2898 val -= mUnpluggedUserTime; 2899 } 2900 } 2901 return val; 2902 } 2903 2904 @Override 2905 public long getSystemTime(int which) { 2906 long val; 2907 if (which == STATS_LAST) { 2908 val = mLastSystemTime; 2909 } else { 2910 val = mSystemTime; 2911 if (which == STATS_CURRENT) { 2912 val -= mLoadedSystemTime; 2913 } else if (which == STATS_SINCE_UNPLUGGED) { 2914 val -= mUnpluggedSystemTime; 2915 } 2916 } 2917 return val; 2918 } 2919 2920 @Override 2921 public long getForegroundTime(int which) { 2922 long val; 2923 if (which == STATS_LAST) { 2924 val = mLastForegroundTime; 2925 } else { 2926 val = mForegroundTime; 2927 if (which == STATS_CURRENT) { 2928 val -= mLoadedForegroundTime; 2929 } else if (which == STATS_SINCE_UNPLUGGED) { 2930 val -= mUnpluggedForegroundTime; 2931 } 2932 } 2933 return val; 2934 } 2935 2936 @Override 2937 public int getStarts(int which) { 2938 int val; 2939 if (which == STATS_LAST) { 2940 val = mLastStarts; 2941 } else { 2942 val = mStarts; 2943 if (which == STATS_CURRENT) { 2944 val -= mLoadedStarts; 2945 } else if (which == STATS_SINCE_UNPLUGGED) { 2946 val -= mUnpluggedStarts; 2947 } 2948 } 2949 return val; 2950 } 2951 2952 /* Called by ActivityManagerService when CPU times are updated. */ 2953 public void addSpeedStepTimes(long[] values) { 2954 for (int i = 0; i < mSpeedBins.length && i < values.length; i++) { 2955 long amt = values[i]; 2956 if (amt != 0) { 2957 SamplingCounter c = mSpeedBins[i]; 2958 if (c == null) { 2959 mSpeedBins[i] = c = new SamplingCounter(mUnpluggables); 2960 } 2961 c.addCountAtomic(values[i]); 2962 } 2963 } 2964 } 2965 2966 @Override 2967 public long getTimeAtCpuSpeedStep(int speedStep, int which) { 2968 if (speedStep < mSpeedBins.length) { 2969 SamplingCounter c = mSpeedBins[speedStep]; 2970 return c != null ? c.getCountLocked(which) : 0; 2971 } else { 2972 return 0; 2973 } 2974 } 2975 } 2976 2977 /** 2978 * The statistics associated with a particular package. 2979 */ 2980 public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable { 2981 /** 2982 * Number of times this package has done something that could wake up the 2983 * device from sleep. 2984 */ 2985 int mWakeups; 2986 2987 /** 2988 * Number of things that could wake up the device loaded from a 2989 * previous save. 2990 */ 2991 int mLoadedWakeups; 2992 2993 /** 2994 * Number of things that could wake up the device as of the 2995 * last run. 2996 */ 2997 int mLastWakeups; 2998 2999 /** 3000 * Number of things that could wake up the device as of the 3001 * last run. 3002 */ 3003 int mUnpluggedWakeups; 3004 3005 /** 3006 * The statics we have collected for this package's services. 3007 */ 3008 final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>(); 3009 3010 Pkg() { 3011 mUnpluggables.add(this); 3012 } 3013 3014 public void unplug(long batteryUptime, long batteryRealtime) { 3015 mUnpluggedWakeups = mWakeups; 3016 } 3017 3018 public void plug(long batteryUptime, long batteryRealtime) { 3019 } 3020 3021 void detach() { 3022 mUnpluggables.remove(this); 3023 } 3024 3025 void readFromParcelLocked(Parcel in) { 3026 mWakeups = in.readInt(); 3027 mLoadedWakeups = in.readInt(); 3028 mLastWakeups = 0; 3029 mUnpluggedWakeups = in.readInt(); 3030 3031 int numServs = in.readInt(); 3032 mServiceStats.clear(); 3033 for (int m = 0; m < numServs; m++) { 3034 String serviceName = in.readString(); 3035 Uid.Pkg.Serv serv = new Serv(); 3036 mServiceStats.put(serviceName, serv); 3037 3038 serv.readFromParcelLocked(in); 3039 } 3040 } 3041 3042 void writeToParcelLocked(Parcel out) { 3043 out.writeInt(mWakeups); 3044 out.writeInt(mLoadedWakeups); 3045 out.writeInt(mUnpluggedWakeups); 3046 3047 out.writeInt(mServiceStats.size()); 3048 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) { 3049 out.writeString(servEntry.getKey()); 3050 Uid.Pkg.Serv serv = servEntry.getValue(); 3051 3052 serv.writeToParcelLocked(out); 3053 } 3054 } 3055 3056 @Override 3057 public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() { 3058 return mServiceStats; 3059 } 3060 3061 @Override 3062 public int getWakeups(int which) { 3063 int val; 3064 if (which == STATS_LAST) { 3065 val = mLastWakeups; 3066 } else { 3067 val = mWakeups; 3068 if (which == STATS_CURRENT) { 3069 val -= mLoadedWakeups; 3070 } else if (which == STATS_SINCE_UNPLUGGED) { 3071 val -= mUnpluggedWakeups; 3072 } 3073 } 3074 3075 return val; 3076 } 3077 3078 /** 3079 * The statistics associated with a particular service. 3080 */ 3081 public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable { 3082 /** 3083 * Total time (ms in battery uptime) the service has been left started. 3084 */ 3085 long mStartTime; 3086 3087 /** 3088 * If service has been started and not yet stopped, this is 3089 * when it was started. 3090 */ 3091 long mRunningSince; 3092 3093 /** 3094 * True if we are currently running. 3095 */ 3096 boolean mRunning; 3097 3098 /** 3099 * Total number of times startService() has been called. 3100 */ 3101 int mStarts; 3102 3103 /** 3104 * Total time (ms in battery uptime) the service has been left launched. 3105 */ 3106 long mLaunchedTime; 3107 3108 /** 3109 * If service has been launched and not yet exited, this is 3110 * when it was launched (ms in battery uptime). 3111 */ 3112 long mLaunchedSince; 3113 3114 /** 3115 * True if we are currently launched. 3116 */ 3117 boolean mLaunched; 3118 3119 /** 3120 * Total number times the service has been launched. 3121 */ 3122 int mLaunches; 3123 3124 /** 3125 * The amount of time spent started loaded from a previous save 3126 * (ms in battery uptime). 3127 */ 3128 long mLoadedStartTime; 3129 3130 /** 3131 * The number of starts loaded from a previous save. 3132 */ 3133 int mLoadedStarts; 3134 3135 /** 3136 * The number of launches loaded from a previous save. 3137 */ 3138 int mLoadedLaunches; 3139 3140 /** 3141 * The amount of time spent started as of the last run (ms 3142 * in battery uptime). 3143 */ 3144 long mLastStartTime; 3145 3146 /** 3147 * The number of starts as of the last run. 3148 */ 3149 int mLastStarts; 3150 3151 /** 3152 * The number of launches as of the last run. 3153 */ 3154 int mLastLaunches; 3155 3156 /** 3157 * The amount of time spent started when last unplugged (ms 3158 * in battery uptime). 3159 */ 3160 long mUnpluggedStartTime; 3161 3162 /** 3163 * The number of starts when last unplugged. 3164 */ 3165 int mUnpluggedStarts; 3166 3167 /** 3168 * The number of launches when last unplugged. 3169 */ 3170 int mUnpluggedLaunches; 3171 3172 Serv() { 3173 mUnpluggables.add(this); 3174 } 3175 3176 public void unplug(long batteryUptime, long batteryRealtime) { 3177 mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime); 3178 mUnpluggedStarts = mStarts; 3179 mUnpluggedLaunches = mLaunches; 3180 } 3181 3182 public void plug(long batteryUptime, long batteryRealtime) { 3183 } 3184 3185 void detach() { 3186 mUnpluggables.remove(this); 3187 } 3188 3189 void readFromParcelLocked(Parcel in) { 3190 mStartTime = in.readLong(); 3191 mRunningSince = in.readLong(); 3192 mRunning = in.readInt() != 0; 3193 mStarts = in.readInt(); 3194 mLaunchedTime = in.readLong(); 3195 mLaunchedSince = in.readLong(); 3196 mLaunched = in.readInt() != 0; 3197 mLaunches = in.readInt(); 3198 mLoadedStartTime = in.readLong(); 3199 mLoadedStarts = in.readInt(); 3200 mLoadedLaunches = in.readInt(); 3201 mLastStartTime = 0; 3202 mLastStarts = 0; 3203 mLastLaunches = 0; 3204 mUnpluggedStartTime = in.readLong(); 3205 mUnpluggedStarts = in.readInt(); 3206 mUnpluggedLaunches = in.readInt(); 3207 } 3208 3209 void writeToParcelLocked(Parcel out) { 3210 out.writeLong(mStartTime); 3211 out.writeLong(mRunningSince); 3212 out.writeInt(mRunning ? 1 : 0); 3213 out.writeInt(mStarts); 3214 out.writeLong(mLaunchedTime); 3215 out.writeLong(mLaunchedSince); 3216 out.writeInt(mLaunched ? 1 : 0); 3217 out.writeInt(mLaunches); 3218 out.writeLong(mLoadedStartTime); 3219 out.writeInt(mLoadedStarts); 3220 out.writeInt(mLoadedLaunches); 3221 out.writeLong(mUnpluggedStartTime); 3222 out.writeInt(mUnpluggedStarts); 3223 out.writeInt(mUnpluggedLaunches); 3224 } 3225 3226 long getLaunchTimeToNowLocked(long batteryUptime) { 3227 if (!mLaunched) return mLaunchedTime; 3228 return mLaunchedTime + batteryUptime - mLaunchedSince; 3229 } 3230 3231 long getStartTimeToNowLocked(long batteryUptime) { 3232 if (!mRunning) return mStartTime; 3233 return mStartTime + batteryUptime - mRunningSince; 3234 } 3235 3236 public void startLaunchedLocked() { 3237 if (!mLaunched) { 3238 mLaunches++; 3239 mLaunchedSince = getBatteryUptimeLocked(); 3240 mLaunched = true; 3241 } 3242 } 3243 3244 public void stopLaunchedLocked() { 3245 if (mLaunched) { 3246 long time = getBatteryUptimeLocked() - mLaunchedSince; 3247 if (time > 0) { 3248 mLaunchedTime += time; 3249 } else { 3250 mLaunches--; 3251 } 3252 mLaunched = false; 3253 } 3254 } 3255 3256 public void startRunningLocked() { 3257 if (!mRunning) { 3258 mStarts++; 3259 mRunningSince = getBatteryUptimeLocked(); 3260 mRunning = true; 3261 } 3262 } 3263 3264 public void stopRunningLocked() { 3265 if (mRunning) { 3266 long time = getBatteryUptimeLocked() - mRunningSince; 3267 if (time > 0) { 3268 mStartTime += time; 3269 } else { 3270 mStarts--; 3271 } 3272 mRunning = false; 3273 } 3274 } 3275 3276 public BatteryStatsImpl getBatteryStats() { 3277 return BatteryStatsImpl.this; 3278 } 3279 3280 @Override 3281 public int getLaunches(int which) { 3282 int val; 3283 3284 if (which == STATS_LAST) { 3285 val = mLastLaunches; 3286 } else { 3287 val = mLaunches; 3288 if (which == STATS_CURRENT) { 3289 val -= mLoadedLaunches; 3290 } else if (which == STATS_SINCE_UNPLUGGED) { 3291 val -= mUnpluggedLaunches; 3292 } 3293 } 3294 3295 return val; 3296 } 3297 3298 @Override 3299 public long getStartTime(long now, int which) { 3300 long val; 3301 if (which == STATS_LAST) { 3302 val = mLastStartTime; 3303 } else { 3304 val = getStartTimeToNowLocked(now); 3305 if (which == STATS_CURRENT) { 3306 val -= mLoadedStartTime; 3307 } else if (which == STATS_SINCE_UNPLUGGED) { 3308 val -= mUnpluggedStartTime; 3309 } 3310 } 3311 3312 return val; 3313 } 3314 3315 @Override 3316 public int getStarts(int which) { 3317 int val; 3318 if (which == STATS_LAST) { 3319 val = mLastStarts; 3320 } else { 3321 val = mStarts; 3322 if (which == STATS_CURRENT) { 3323 val -= mLoadedStarts; 3324 } else if (which == STATS_SINCE_UNPLUGGED) { 3325 val -= mUnpluggedStarts; 3326 } 3327 } 3328 3329 return val; 3330 } 3331 } 3332 3333 public BatteryStatsImpl getBatteryStats() { 3334 return BatteryStatsImpl.this; 3335 } 3336 3337 public void incWakeupsLocked() { 3338 mWakeups++; 3339 } 3340 3341 final Serv newServiceStatsLocked() { 3342 return new Serv(); 3343 } 3344 } 3345 3346 /** 3347 * Retrieve the statistics object for a particular process, creating 3348 * if needed. 3349 */ 3350 public Proc getProcessStatsLocked(String name) { 3351 Proc ps = mProcessStats.get(name); 3352 if (ps == null) { 3353 ps = new Proc(); 3354 mProcessStats.put(name, ps); 3355 } 3356 3357 return ps; 3358 } 3359 3360 public SparseArray<? extends Pid> getPidStats() { 3361 return mPids; 3362 } 3363 3364 public Pid getPidStatsLocked(int pid) { 3365 Pid p = mPids.get(pid); 3366 if (p == null) { 3367 p = new Pid(); 3368 mPids.put(pid, p); 3369 } 3370 return p; 3371 } 3372 3373 /** 3374 * Retrieve the statistics object for a particular service, creating 3375 * if needed. 3376 */ 3377 public Pkg getPackageStatsLocked(String name) { 3378 Pkg ps = mPackageStats.get(name); 3379 if (ps == null) { 3380 ps = new Pkg(); 3381 mPackageStats.put(name, ps); 3382 } 3383 3384 return ps; 3385 } 3386 3387 /** 3388 * Retrieve the statistics object for a particular service, creating 3389 * if needed. 3390 */ 3391 public Pkg.Serv getServiceStatsLocked(String pkg, String serv) { 3392 Pkg ps = getPackageStatsLocked(pkg); 3393 Pkg.Serv ss = ps.mServiceStats.get(serv); 3394 if (ss == null) { 3395 ss = ps.newServiceStatsLocked(); 3396 ps.mServiceStats.put(serv, ss); 3397 } 3398 3399 return ss; 3400 } 3401 3402 public StopwatchTimer getWakeTimerLocked(String name, int type) { 3403 Wakelock wl = mWakelockStats.get(name); 3404 if (wl == null) { 3405 if (mWakelockStats.size() > MAX_WAKELOCKS_PER_UID) { 3406 name = BATCHED_WAKELOCK_NAME; 3407 wl = mWakelockStats.get(name); 3408 } 3409 if (wl == null) { 3410 wl = new Wakelock(); 3411 mWakelockStats.put(name, wl); 3412 } 3413 } 3414 StopwatchTimer t = null; 3415 switch (type) { 3416 case WAKE_TYPE_PARTIAL: 3417 t = wl.mTimerPartial; 3418 if (t == null) { 3419 t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables); 3420 wl.mTimerPartial = t; 3421 } 3422 return t; 3423 case WAKE_TYPE_FULL: 3424 t = wl.mTimerFull; 3425 if (t == null) { 3426 t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables); 3427 wl.mTimerFull = t; 3428 } 3429 return t; 3430 case WAKE_TYPE_WINDOW: 3431 t = wl.mTimerWindow; 3432 if (t == null) { 3433 t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables); 3434 wl.mTimerWindow = t; 3435 } 3436 return t; 3437 default: 3438 throw new IllegalArgumentException("type=" + type); 3439 } 3440 } 3441 3442 public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) { 3443 Sensor se = mSensorStats.get(sensor); 3444 if (se == null) { 3445 if (!create) { 3446 return null; 3447 } 3448 se = new Sensor(sensor); 3449 mSensorStats.put(sensor, se); 3450 } 3451 StopwatchTimer t = se.mTimer; 3452 if (t != null) { 3453 return t; 3454 } 3455 ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor); 3456 if (timers == null) { 3457 timers = new ArrayList<StopwatchTimer>(); 3458 mSensorTimers.put(sensor, timers); 3459 } 3460 t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables); 3461 se.mTimer = t; 3462 return t; 3463 } 3464 3465 public void noteStartWakeLocked(int pid, String name, int type) { 3466 StopwatchTimer t = getWakeTimerLocked(name, type); 3467 if (t != null) { 3468 t.startRunningLocked(BatteryStatsImpl.this); 3469 } 3470 if (pid >= 0 && type == WAKE_TYPE_PARTIAL) { 3471 Pid p = getPidStatsLocked(pid); 3472 p.mWakeStart = SystemClock.elapsedRealtime(); 3473 } 3474 } 3475 3476 public void noteStopWakeLocked(int pid, String name, int type) { 3477 StopwatchTimer t = getWakeTimerLocked(name, type); 3478 if (t != null) { 3479 t.stopRunningLocked(BatteryStatsImpl.this); 3480 } 3481 if (pid >= 0 && type == WAKE_TYPE_PARTIAL) { 3482 Pid p = mPids.get(pid); 3483 if (p != null) { 3484 p.mWakeSum += SystemClock.elapsedRealtime() - p.mWakeStart; 3485 p.mWakeStart = 0; 3486 } 3487 } 3488 } 3489 3490 public void reportExcessiveWakeLocked(String proc, long overTime, long usedTime) { 3491 Proc p = getProcessStatsLocked(proc); 3492 if (p != null) { 3493 p.addExcessiveWake(overTime, usedTime); 3494 } 3495 } 3496 3497 public void noteStartSensor(int sensor) { 3498 StopwatchTimer t = getSensorTimerLocked(sensor, true); 3499 if (t != null) { 3500 t.startRunningLocked(BatteryStatsImpl.this); 3501 } 3502 } 3503 3504 public void noteStopSensor(int sensor) { 3505 // Don't create a timer if one doesn't already exist 3506 StopwatchTimer t = getSensorTimerLocked(sensor, false); 3507 if (t != null) { 3508 t.stopRunningLocked(BatteryStatsImpl.this); 3509 } 3510 } 3511 3512 public void noteStartGps() { 3513 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true); 3514 if (t != null) { 3515 t.startRunningLocked(BatteryStatsImpl.this); 3516 } 3517 } 3518 3519 public void noteStopGps() { 3520 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false); 3521 if (t != null) { 3522 t.stopRunningLocked(BatteryStatsImpl.this); 3523 } 3524 } 3525 3526 public BatteryStatsImpl getBatteryStats() { 3527 return BatteryStatsImpl.this; 3528 } 3529 } 3530 3531 public BatteryStatsImpl(String filename) { 3532 mFile = new JournaledFile(new File(filename), new File(filename + ".tmp")); 3533 mStartCount++; 3534 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables); 3535 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3536 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables); 3537 } 3538 mInputEventCounter = new Counter(mUnpluggables); 3539 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables); 3540 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3541 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables); 3542 } 3543 mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables); 3544 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3545 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables); 3546 } 3547 mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables); 3548 mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables); 3549 mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables); 3550 mAudioOnTimer = new StopwatchTimer(-6, null, mUnpluggables); 3551 mVideoOnTimer = new StopwatchTimer(-7, null, mUnpluggables); 3552 mOnBattery = mOnBatteryInternal = false; 3553 initTimes(); 3554 mTrackBatteryPastUptime = 0; 3555 mTrackBatteryPastRealtime = 0; 3556 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; 3557 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; 3558 mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); 3559 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); 3560 mDischargeStartLevel = 0; 3561 mDischargeUnplugLevel = 0; 3562 mDischargeCurrentLevel = 0; 3563 mLowDischargeAmountSinceCharge = 0; 3564 mHighDischargeAmountSinceCharge = 0; 3565 } 3566 3567 public BatteryStatsImpl(Parcel p) { 3568 mFile = null; 3569 readFromParcel(p); 3570 } 3571 3572 public void setNumSpeedSteps(int steps) { 3573 if (sNumSpeedSteps == 0) sNumSpeedSteps = steps; 3574 } 3575 3576 public void setRadioScanningTimeout(long timeout) { 3577 if (mPhoneSignalScanningTimer != null) { 3578 mPhoneSignalScanningTimer.setTimeout(timeout); 3579 } 3580 } 3581 3582 @Override 3583 public HistoryItem getHistory() { 3584 return mHistory; 3585 } 3586 3587 @Override 3588 public long getHistoryBaseTime() { 3589 return mHistoryBaseTime; 3590 } 3591 3592 @Override 3593 public int getStartCount() { 3594 return mStartCount; 3595 } 3596 3597 public boolean isOnBattery() { 3598 return mOnBattery; 3599 } 3600 3601 public boolean isScreenOn() { 3602 return mScreenOn; 3603 } 3604 3605 void initTimes() { 3606 mBatteryRealtime = mTrackBatteryPastUptime = 0; 3607 mBatteryUptime = mTrackBatteryPastRealtime = 0; 3608 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; 3609 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; 3610 mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); 3611 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); 3612 } 3613 3614 public void resetAllStatsLocked() { 3615 mStartCount = 0; 3616 initTimes(); 3617 mScreenOnTimer.reset(this, false); 3618 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3619 mScreenBrightnessTimer[i].reset(this, false); 3620 } 3621 mInputEventCounter.reset(false); 3622 mPhoneOnTimer.reset(this, false); 3623 mAudioOnTimer.reset(this, false); 3624 mVideoOnTimer.reset(this, false); 3625 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3626 mPhoneSignalStrengthsTimer[i].reset(this, false); 3627 } 3628 mPhoneSignalScanningTimer.reset(this, false); 3629 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3630 mPhoneDataConnectionsTimer[i].reset(this, false); 3631 } 3632 mWifiOnTimer.reset(this, false); 3633 mWifiRunningTimer.reset(this, false); 3634 mBluetoothOnTimer.reset(this, false); 3635 3636 for (int i=0; i<mUidStats.size(); i++) { 3637 if (mUidStats.valueAt(i).reset()) { 3638 mUidStats.remove(mUidStats.keyAt(i)); 3639 i--; 3640 } 3641 } 3642 3643 if (mKernelWakelockStats.size() > 0) { 3644 for (SamplingTimer timer : mKernelWakelockStats.values()) { 3645 mUnpluggables.remove(timer); 3646 } 3647 mKernelWakelockStats.clear(); 3648 } 3649 3650 clearHistoryLocked(); 3651 } 3652 3653 void setOnBattery(boolean onBattery, int oldStatus, int level) { 3654 synchronized(this) { 3655 boolean doWrite = false; 3656 mOnBattery = mOnBatteryInternal = onBattery; 3657 3658 long uptime = SystemClock.uptimeMillis() * 1000; 3659 long mSecRealtime = SystemClock.elapsedRealtime(); 3660 long realtime = mSecRealtime * 1000; 3661 if (onBattery) { 3662 // We will reset our status if we are unplugging after the 3663 // battery was last full, or the level is at 100, or 3664 // we have gone through a significant charge (from a very low 3665 // level to a now very high level). 3666 if (oldStatus == BatteryManager.BATTERY_STATUS_FULL 3667 || level >= 100 3668 || (mDischargeCurrentLevel < 20 && level > 90)) { 3669 doWrite = true; 3670 resetAllStatsLocked(); 3671 mDischargeStartLevel = level; 3672 mLowDischargeAmountSinceCharge = 0; 3673 mHighDischargeAmountSinceCharge = 0; 3674 } 3675 updateKernelWakelocksLocked(); 3676 mHistoryCur.batteryLevel = (byte)level; 3677 mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; 3678 if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: " 3679 + Integer.toHexString(mHistoryCur.states)); 3680 addHistoryRecordLocked(mSecRealtime); 3681 mTrackBatteryUptimeStart = uptime; 3682 mTrackBatteryRealtimeStart = realtime; 3683 mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); 3684 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); 3685 mDischargeCurrentLevel = mDischargeUnplugLevel = level; 3686 doUnplugLocked(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); 3687 } else { 3688 updateKernelWakelocksLocked(); 3689 mHistoryCur.batteryLevel = (byte)level; 3690 mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; 3691 if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: " 3692 + Integer.toHexString(mHistoryCur.states)); 3693 addHistoryRecordLocked(mSecRealtime); 3694 mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; 3695 mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; 3696 mDischargeCurrentLevel = level; 3697 if (level < mDischargeUnplugLevel) { 3698 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1; 3699 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level; 3700 } 3701 doPlugLocked(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); 3702 } 3703 if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) { 3704 if (mFile != null) { 3705 writeLocked(); 3706 } 3707 } 3708 } 3709 } 3710 3711 // This should probably be exposed in the API, though it's not critical 3712 private static final int BATTERY_PLUGGED_NONE = 0; 3713 3714 public void setBatteryState(int status, int health, int plugType, int level, 3715 int temp, int volt) { 3716 boolean onBattery = plugType == BATTERY_PLUGGED_NONE; 3717 int oldStatus = mHistoryCur.batteryStatus; 3718 if (!mHaveBatteryLevel) { 3719 mHaveBatteryLevel = true; 3720 // We start out assuming that the device is plugged in (not 3721 // on battery). If our first report is now that we are indeed 3722 // plugged in, then twiddle our state to correctly reflect that 3723 // since we won't be going through the full setOnBattery(). 3724 if (onBattery == mOnBattery) { 3725 if (onBattery) { 3726 mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; 3727 } else { 3728 mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; 3729 } 3730 } 3731 oldStatus = status; 3732 } 3733 if (onBattery) { 3734 mDischargeCurrentLevel = level; 3735 mRecordingHistory = true; 3736 } 3737 if (onBattery != mOnBattery) { 3738 mHistoryCur.batteryLevel = (byte)level; 3739 mHistoryCur.batteryStatus = (byte)status; 3740 mHistoryCur.batteryHealth = (byte)health; 3741 mHistoryCur.batteryPlugType = (byte)plugType; 3742 mHistoryCur.batteryTemperature = (char)temp; 3743 mHistoryCur.batteryVoltage = (char)volt; 3744 setOnBattery(onBattery, oldStatus, level); 3745 } else { 3746 boolean changed = false; 3747 if (mHistoryCur.batteryLevel != level) { 3748 mHistoryCur.batteryLevel = (byte)level; 3749 changed = true; 3750 } 3751 if (mHistoryCur.batteryStatus != status) { 3752 mHistoryCur.batteryStatus = (byte)status; 3753 changed = true; 3754 } 3755 if (mHistoryCur.batteryHealth != health) { 3756 mHistoryCur.batteryHealth = (byte)health; 3757 changed = true; 3758 } 3759 if (mHistoryCur.batteryPlugType != plugType) { 3760 mHistoryCur.batteryPlugType = (byte)plugType; 3761 changed = true; 3762 } 3763 if (mHistoryCur.batteryTemperature != temp) { 3764 mHistoryCur.batteryTemperature = (char)temp; 3765 changed = true; 3766 } 3767 if (mHistoryCur.batteryVoltage != volt) { 3768 mHistoryCur.batteryVoltage = (char)volt; 3769 changed = true; 3770 } 3771 if (changed) { 3772 addHistoryRecordLocked(SystemClock.elapsedRealtime()); 3773 } 3774 } 3775 if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) { 3776 // We don't record history while we are plugged in and fully charged. 3777 // The next time we are unplugged, history will be cleared. 3778 mRecordingHistory = false; 3779 } 3780 } 3781 3782 public void updateKernelWakelocksLocked() { 3783 Map<String, KernelWakelockStats> m = readKernelWakelockStats(); 3784 3785 if (m == null) { 3786 // Not crashing might make board bringup easier. 3787 Slog.w(TAG, "Couldn't get kernel wake lock stats"); 3788 return; 3789 } 3790 3791 for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) { 3792 String name = ent.getKey(); 3793 KernelWakelockStats kws = ent.getValue(); 3794 3795 SamplingTimer kwlt = mKernelWakelockStats.get(name); 3796 if (kwlt == null) { 3797 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 3798 true /* track reported values */); 3799 mKernelWakelockStats.put(name, kwlt); 3800 } 3801 kwlt.updateCurrentReportedCount(kws.mCount); 3802 kwlt.updateCurrentReportedTotalTime(kws.mTotalTime); 3803 kwlt.setUpdateVersion(sKernelWakelockUpdateVersion); 3804 } 3805 3806 if (m.size() != mKernelWakelockStats.size()) { 3807 // Set timers to stale if they didn't appear in /proc/wakelocks this time. 3808 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 3809 SamplingTimer st = ent.getValue(); 3810 if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) { 3811 st.setStale(); 3812 } 3813 } 3814 } 3815 } 3816 3817 public long getAwakeTimeBattery() { 3818 return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT); 3819 } 3820 3821 public long getAwakeTimePlugged() { 3822 return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery(); 3823 } 3824 3825 @Override 3826 public long computeUptime(long curTime, int which) { 3827 switch (which) { 3828 case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart); 3829 case STATS_LAST: return mLastUptime; 3830 case STATS_CURRENT: return (curTime-mUptimeStart); 3831 case STATS_SINCE_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart); 3832 } 3833 return 0; 3834 } 3835 3836 @Override 3837 public long computeRealtime(long curTime, int which) { 3838 switch (which) { 3839 case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart); 3840 case STATS_LAST: return mLastRealtime; 3841 case STATS_CURRENT: return (curTime-mRealtimeStart); 3842 case STATS_SINCE_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart); 3843 } 3844 return 0; 3845 } 3846 3847 @Override 3848 public long computeBatteryUptime(long curTime, int which) { 3849 switch (which) { 3850 case STATS_SINCE_CHARGED: 3851 return mBatteryUptime + getBatteryUptime(curTime); 3852 case STATS_LAST: 3853 return mBatteryLastUptime; 3854 case STATS_CURRENT: 3855 return getBatteryUptime(curTime); 3856 case STATS_SINCE_UNPLUGGED: 3857 return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime; 3858 } 3859 return 0; 3860 } 3861 3862 @Override 3863 public long computeBatteryRealtime(long curTime, int which) { 3864 switch (which) { 3865 case STATS_SINCE_CHARGED: 3866 return mBatteryRealtime + getBatteryRealtimeLocked(curTime); 3867 case STATS_LAST: 3868 return mBatteryLastRealtime; 3869 case STATS_CURRENT: 3870 return getBatteryRealtimeLocked(curTime); 3871 case STATS_SINCE_UNPLUGGED: 3872 return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime; 3873 } 3874 return 0; 3875 } 3876 3877 long getBatteryUptimeLocked(long curTime) { 3878 long time = mTrackBatteryPastUptime; 3879 if (mOnBatteryInternal) { 3880 time += curTime - mTrackBatteryUptimeStart; 3881 } 3882 return time; 3883 } 3884 3885 long getBatteryUptimeLocked() { 3886 return getBatteryUptime(SystemClock.uptimeMillis() * 1000); 3887 } 3888 3889 @Override 3890 public long getBatteryUptime(long curTime) { 3891 return getBatteryUptimeLocked(curTime); 3892 } 3893 3894 long getBatteryRealtimeLocked(long curTime) { 3895 long time = mTrackBatteryPastRealtime; 3896 if (mOnBatteryInternal) { 3897 time += curTime - mTrackBatteryRealtimeStart; 3898 } 3899 return time; 3900 } 3901 3902 @Override 3903 public long getBatteryRealtime(long curTime) { 3904 return getBatteryRealtimeLocked(curTime); 3905 } 3906 3907 private long getTcpBytes(long current, long[] dataBytes, int which) { 3908 if (which == STATS_LAST) { 3909 return dataBytes[STATS_LAST]; 3910 } else { 3911 if (which == STATS_SINCE_UNPLUGGED) { 3912 if (dataBytes[STATS_SINCE_UNPLUGGED] < 0) { 3913 return dataBytes[STATS_LAST]; 3914 } else { 3915 return current - dataBytes[STATS_SINCE_UNPLUGGED]; 3916 } 3917 } else if (which == STATS_SINCE_CHARGED) { 3918 return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_SINCE_CHARGED]; 3919 } 3920 return current - dataBytes[STATS_CURRENT]; 3921 } 3922 } 3923 3924 /** Only STATS_UNPLUGGED works properly */ 3925 public long getMobileTcpBytesSent(int which) { 3926 return getTcpBytes(TrafficStats.getMobileTxBytes(), mMobileDataTx, which); 3927 } 3928 3929 /** Only STATS_UNPLUGGED works properly */ 3930 public long getMobileTcpBytesReceived(int which) { 3931 return getTcpBytes(TrafficStats.getMobileRxBytes(), mMobileDataRx, which); 3932 } 3933 3934 /** Only STATS_UNPLUGGED works properly */ 3935 public long getTotalTcpBytesSent(int which) { 3936 return getTcpBytes(TrafficStats.getTotalTxBytes(), mTotalDataTx, which); 3937 } 3938 3939 /** Only STATS_UNPLUGGED works properly */ 3940 public long getTotalTcpBytesReceived(int which) { 3941 return getTcpBytes(TrafficStats.getTotalRxBytes(), mTotalDataRx, which); 3942 } 3943 3944 @Override 3945 public int getDischargeStartLevel() { 3946 synchronized(this) { 3947 return getDischargeStartLevelLocked(); 3948 } 3949 } 3950 3951 public int getDischargeStartLevelLocked() { 3952 return mDischargeUnplugLevel; 3953 } 3954 3955 @Override 3956 public int getDischargeCurrentLevel() { 3957 synchronized(this) { 3958 return getDischargeCurrentLevelLocked(); 3959 } 3960 } 3961 3962 public int getDischargeCurrentLevelLocked() { 3963 return mDischargeCurrentLevel; 3964 } 3965 3966 @Override 3967 public int getLowDischargeAmountSinceCharge() { 3968 synchronized(this) { 3969 return mLowDischargeAmountSinceCharge; 3970 } 3971 } 3972 3973 @Override 3974 public int getHighDischargeAmountSinceCharge() { 3975 synchronized(this) { 3976 return mHighDischargeAmountSinceCharge; 3977 } 3978 } 3979 3980 @Override 3981 public int getCpuSpeedSteps() { 3982 return sNumSpeedSteps; 3983 } 3984 3985 /** 3986 * Retrieve the statistics object for a particular uid, creating if needed. 3987 */ 3988 public Uid getUidStatsLocked(int uid) { 3989 Uid u = mUidStats.get(uid); 3990 if (u == null) { 3991 u = new Uid(uid); 3992 mUidStats.put(uid, u); 3993 } 3994 return u; 3995 } 3996 3997 /** 3998 * Remove the statistics object for a particular uid. 3999 */ 4000 public void removeUidStatsLocked(int uid) { 4001 mUidStats.remove(uid); 4002 } 4003 4004 /** 4005 * Retrieve the statistics object for a particular process, creating 4006 * if needed. 4007 */ 4008 public Uid.Proc getProcessStatsLocked(int uid, String name) { 4009 Uid u = getUidStatsLocked(uid); 4010 return u.getProcessStatsLocked(name); 4011 } 4012 4013 /** 4014 * Retrieve the statistics object for a particular process, given 4015 * the name of the process. 4016 * @param name process name 4017 * @return the statistics object for the process 4018 */ 4019 public Uid.Proc getProcessStatsLocked(String name, int pid) { 4020 int uid; 4021 if (mUidCache.containsKey(name)) { 4022 uid = mUidCache.get(name); 4023 } else { 4024 uid = Process.getUidForPid(pid); 4025 mUidCache.put(name, uid); 4026 } 4027 Uid u = getUidStatsLocked(uid); 4028 return u.getProcessStatsLocked(name); 4029 } 4030 4031 /** 4032 * Retrieve the statistics object for a particular process, creating 4033 * if needed. 4034 */ 4035 public Uid.Pkg getPackageStatsLocked(int uid, String pkg) { 4036 Uid u = getUidStatsLocked(uid); 4037 return u.getPackageStatsLocked(pkg); 4038 } 4039 4040 /** 4041 * Retrieve the statistics object for a particular service, creating 4042 * if needed. 4043 */ 4044 public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) { 4045 Uid u = getUidStatsLocked(uid); 4046 return u.getServiceStatsLocked(pkg, name); 4047 } 4048 4049 public void shutdownLocked() { 4050 writeLocked(); 4051 mShuttingDown = true; 4052 } 4053 4054 public void writeLocked() { 4055 if (mFile == null) { 4056 Slog.w("BatteryStats", "writeLocked: no file associated with this instance"); 4057 return; 4058 } 4059 4060 if (mShuttingDown) { 4061 return; 4062 } 4063 4064 try { 4065 FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite()); 4066 Parcel out = Parcel.obtain(); 4067 writeSummaryToParcel(out); 4068 stream.write(out.marshall()); 4069 out.recycle(); 4070 4071 stream.flush(); 4072 stream.close(); 4073 mFile.commit(); 4074 4075 mLastWriteTime = SystemClock.elapsedRealtime(); 4076 return; 4077 } catch (IOException e) { 4078 Slog.w("BatteryStats", "Error writing battery statistics", e); 4079 } 4080 mFile.rollback(); 4081 } 4082 4083 static byte[] readFully(FileInputStream stream) throws java.io.IOException { 4084 int pos = 0; 4085 int avail = stream.available(); 4086 byte[] data = new byte[avail]; 4087 while (true) { 4088 int amt = stream.read(data, pos, data.length-pos); 4089 //Log.i("foo", "Read " + amt + " bytes at " + pos 4090 // + " of avail " + data.length); 4091 if (amt <= 0) { 4092 //Log.i("foo", "**** FINISHED READING: pos=" + pos 4093 // + " len=" + data.length); 4094 return data; 4095 } 4096 pos += amt; 4097 avail = stream.available(); 4098 if (avail > data.length-pos) { 4099 byte[] newData = new byte[pos+avail]; 4100 System.arraycopy(data, 0, newData, 0, pos); 4101 data = newData; 4102 } 4103 } 4104 } 4105 4106 public void readLocked() { 4107 if (mFile == null) { 4108 Slog.w("BatteryStats", "readLocked: no file associated with this instance"); 4109 return; 4110 } 4111 4112 mUidStats.clear(); 4113 4114 try { 4115 File file = mFile.chooseForRead(); 4116 if (!file.exists()) { 4117 return; 4118 } 4119 FileInputStream stream = new FileInputStream(file); 4120 4121 byte[] raw = readFully(stream); 4122 Parcel in = Parcel.obtain(); 4123 in.unmarshall(raw, 0, raw.length); 4124 in.setDataPosition(0); 4125 stream.close(); 4126 4127 readSummaryFromParcel(in); 4128 } catch(java.io.IOException e) { 4129 Slog.e("BatteryStats", "Error reading battery statistics", e); 4130 } 4131 4132 addHistoryRecordLocked(SystemClock.elapsedRealtime(), HistoryItem.CMD_START); 4133 } 4134 4135 public int describeContents() { 4136 return 0; 4137 } 4138 4139 void readHistory(Parcel in) { 4140 mHistory = mHistoryEnd = mHistoryCache = null; 4141 mHistoryBaseTime = 0; 4142 long time; 4143 while ((time=in.readLong()) >= 0) { 4144 HistoryItem rec = new HistoryItem(time, in); 4145 addHistoryRecordLocked(rec); 4146 if (rec.time > mHistoryBaseTime) { 4147 mHistoryBaseTime = rec.time; 4148 } 4149 } 4150 4151 long oldnow = SystemClock.elapsedRealtime() - (5*60*100); 4152 if (oldnow > 0) { 4153 // If the system process has restarted, but not the entire 4154 // system, then the mHistoryBaseTime already accounts for 4155 // much of the elapsed time. We thus want to adjust it back, 4156 // to avoid large gaps in the data. We determine we are 4157 // in this case by arbitrarily saying it is so if at this 4158 // point in boot the elapsed time is already more than 5 seconds. 4159 mHistoryBaseTime -= oldnow; 4160 } 4161 } 4162 4163 void writeHistory(Parcel out) { 4164 HistoryItem rec = mHistory; 4165 while (rec != null) { 4166 if (rec.time >= 0) rec.writeToParcel(out, 0); 4167 rec = rec.next; 4168 } 4169 out.writeLong(-1); 4170 } 4171 4172 private void readSummaryFromParcel(Parcel in) { 4173 final int version = in.readInt(); 4174 if (version != VERSION) { 4175 Slog.w("BatteryStats", "readFromParcel: version got " + version 4176 + ", expected " + VERSION + "; erasing old stats"); 4177 return; 4178 } 4179 4180 readHistory(in); 4181 4182 mStartCount = in.readInt(); 4183 mBatteryUptime = in.readLong(); 4184 mBatteryRealtime = in.readLong(); 4185 mUptime = in.readLong(); 4186 mRealtime = in.readLong(); 4187 mDischargeUnplugLevel = in.readInt(); 4188 mDischargeCurrentLevel = in.readInt(); 4189 mLowDischargeAmountSinceCharge = in.readInt(); 4190 mHighDischargeAmountSinceCharge = in.readInt(); 4191 4192 mStartCount++; 4193 4194 mScreenOn = false; 4195 mScreenOnTimer.readSummaryFromParcelLocked(in); 4196 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 4197 mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in); 4198 } 4199 mInputEventCounter.readSummaryFromParcelLocked(in); 4200 mPhoneOn = false; 4201 mPhoneOnTimer.readSummaryFromParcelLocked(in); 4202 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 4203 mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in); 4204 } 4205 mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in); 4206 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 4207 mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in); 4208 } 4209 mWifiOn = false; 4210 mWifiOnTimer.readSummaryFromParcelLocked(in); 4211 mWifiRunning = false; 4212 mWifiRunningTimer.readSummaryFromParcelLocked(in); 4213 mBluetoothOn = false; 4214 mBluetoothOnTimer.readSummaryFromParcelLocked(in); 4215 4216 int NKW = in.readInt(); 4217 if (NKW > 10000) { 4218 Slog.w(TAG, "File corrupt: too many kernel wake locks " + NKW); 4219 return; 4220 } 4221 for (int ikw = 0; ikw < NKW; ikw++) { 4222 if (in.readInt() != 0) { 4223 String kwltName = in.readString(); 4224 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in); 4225 } 4226 } 4227 4228 sNumSpeedSteps = in.readInt(); 4229 4230 final int NU = in.readInt(); 4231 if (NU > 10000) { 4232 Slog.w(TAG, "File corrupt: too many uids " + NU); 4233 return; 4234 } 4235 for (int iu = 0; iu < NU; iu++) { 4236 int uid = in.readInt(); 4237 Uid u = new Uid(uid); 4238 mUidStats.put(uid, u); 4239 4240 u.mWifiTurnedOn = false; 4241 if (in.readInt() != 0) { 4242 u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in); 4243 } 4244 u.mFullWifiLockOut = false; 4245 if (in.readInt() != 0) { 4246 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); 4247 } 4248 u.mScanWifiLockOut = false; 4249 if (in.readInt() != 0) { 4250 u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); 4251 } 4252 u.mWifiMulticastEnabled = false; 4253 if (in.readInt() != 0) { 4254 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in); 4255 } 4256 u.mAudioTurnedOn = false; 4257 if (in.readInt() != 0) { 4258 u.mAudioTurnedOnTimer.readSummaryFromParcelLocked(in); 4259 } 4260 u.mVideoTurnedOn = false; 4261 if (in.readInt() != 0) { 4262 u.mVideoTurnedOnTimer.readSummaryFromParcelLocked(in); 4263 } 4264 4265 if (in.readInt() != 0) { 4266 if (u.mUserActivityCounters == null) { 4267 u.initUserActivityLocked(); 4268 } 4269 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 4270 u.mUserActivityCounters[i].readSummaryFromParcelLocked(in); 4271 } 4272 } 4273 4274 int NW = in.readInt(); 4275 if (NW > 10000) { 4276 Slog.w(TAG, "File corrupt: too many wake locks " + NW); 4277 return; 4278 } 4279 for (int iw = 0; iw < NW; iw++) { 4280 String wlName = in.readString(); 4281 if (in.readInt() != 0) { 4282 u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in); 4283 } 4284 if (in.readInt() != 0) { 4285 u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in); 4286 } 4287 if (in.readInt() != 0) { 4288 u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in); 4289 } 4290 } 4291 4292 int NP = in.readInt(); 4293 if (NP > 10000) { 4294 Slog.w(TAG, "File corrupt: too many sensors " + NP); 4295 return; 4296 } 4297 for (int is = 0; is < NP; is++) { 4298 int seNumber = in.readInt(); 4299 if (in.readInt() != 0) { 4300 u.getSensorTimerLocked(seNumber, true) 4301 .readSummaryFromParcelLocked(in); 4302 } 4303 } 4304 4305 NP = in.readInt(); 4306 if (NP > 10000) { 4307 Slog.w(TAG, "File corrupt: too many processes " + NP); 4308 return; 4309 } 4310 for (int ip = 0; ip < NP; ip++) { 4311 String procName = in.readString(); 4312 Uid.Proc p = u.getProcessStatsLocked(procName); 4313 p.mUserTime = p.mLoadedUserTime = in.readLong(); 4314 p.mSystemTime = p.mLoadedSystemTime = in.readLong(); 4315 p.mStarts = p.mLoadedStarts = in.readInt(); 4316 p.readExcessiveWakeFromParcelLocked(in); 4317 } 4318 4319 NP = in.readInt(); 4320 if (NP > 10000) { 4321 Slog.w(TAG, "File corrupt: too many packages " + NP); 4322 return; 4323 } 4324 for (int ip = 0; ip < NP; ip++) { 4325 String pkgName = in.readString(); 4326 Uid.Pkg p = u.getPackageStatsLocked(pkgName); 4327 p.mWakeups = p.mLoadedWakeups = in.readInt(); 4328 final int NS = in.readInt(); 4329 for (int is = 0; is < NS; is++) { 4330 String servName = in.readString(); 4331 Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName); 4332 s.mStartTime = s.mLoadedStartTime = in.readLong(); 4333 s.mStarts = s.mLoadedStarts = in.readInt(); 4334 s.mLaunches = s.mLoadedLaunches = in.readInt(); 4335 } 4336 } 4337 4338 u.mLoadedTcpBytesReceived = in.readLong(); 4339 u.mLoadedTcpBytesSent = in.readLong(); 4340 } 4341 } 4342 4343 /** 4344 * Writes a summary of the statistics to a Parcel, in a format suitable to be written to 4345 * disk. This format does not allow a lossless round-trip. 4346 * 4347 * @param out the Parcel to be written to. 4348 */ 4349 public void writeSummaryToParcel(Parcel out) { 4350 final long NOW_SYS = SystemClock.uptimeMillis() * 1000; 4351 final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; 4352 final long NOW = getBatteryUptimeLocked(NOW_SYS); 4353 final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS); 4354 4355 out.writeInt(VERSION); 4356 4357 writeHistory(out); 4358 4359 out.writeInt(mStartCount); 4360 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED)); 4361 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED)); 4362 out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED)); 4363 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED)); 4364 out.writeInt(mDischargeUnplugLevel); 4365 out.writeInt(mDischargeCurrentLevel); 4366 out.writeInt(mLowDischargeAmountSinceCharge); 4367 out.writeInt(mHighDischargeAmountSinceCharge); 4368 4369 mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4370 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 4371 mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 4372 } 4373 mInputEventCounter.writeSummaryFromParcelLocked(out); 4374 mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4375 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 4376 mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 4377 } 4378 mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4379 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 4380 mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 4381 } 4382 mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4383 mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4384 mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4385 4386 out.writeInt(mKernelWakelockStats.size()); 4387 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 4388 Timer kwlt = ent.getValue(); 4389 if (kwlt != null) { 4390 out.writeInt(1); 4391 out.writeString(ent.getKey()); 4392 ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL); 4393 } else { 4394 out.writeInt(0); 4395 } 4396 } 4397 4398 out.writeInt(sNumSpeedSteps); 4399 final int NU = mUidStats.size(); 4400 out.writeInt(NU); 4401 for (int iu = 0; iu < NU; iu++) { 4402 out.writeInt(mUidStats.keyAt(iu)); 4403 Uid u = mUidStats.valueAt(iu); 4404 4405 if (u.mWifiTurnedOnTimer != null) { 4406 out.writeInt(1); 4407 u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4408 } else { 4409 out.writeInt(0); 4410 } 4411 if (u.mFullWifiLockTimer != null) { 4412 out.writeInt(1); 4413 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4414 } else { 4415 out.writeInt(0); 4416 } 4417 if (u.mScanWifiLockTimer != null) { 4418 out.writeInt(1); 4419 u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4420 } else { 4421 out.writeInt(0); 4422 } 4423 if (u.mWifiMulticastTimer != null) { 4424 out.writeInt(1); 4425 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4426 } else { 4427 out.writeInt(0); 4428 } 4429 if (u.mAudioTurnedOnTimer != null) { 4430 out.writeInt(1); 4431 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4432 } else { 4433 out.writeInt(0); 4434 } 4435 if (u.mVideoTurnedOnTimer != null) { 4436 out.writeInt(1); 4437 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4438 } else { 4439 out.writeInt(0); 4440 } 4441 4442 if (u.mUserActivityCounters == null) { 4443 out.writeInt(0); 4444 } else { 4445 out.writeInt(1); 4446 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 4447 u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out); 4448 } 4449 } 4450 4451 int NW = u.mWakelockStats.size(); 4452 out.writeInt(NW); 4453 if (NW > 0) { 4454 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent 4455 : u.mWakelockStats.entrySet()) { 4456 out.writeString(ent.getKey()); 4457 Uid.Wakelock wl = ent.getValue(); 4458 if (wl.mTimerFull != null) { 4459 out.writeInt(1); 4460 wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL); 4461 } else { 4462 out.writeInt(0); 4463 } 4464 if (wl.mTimerPartial != null) { 4465 out.writeInt(1); 4466 wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL); 4467 } else { 4468 out.writeInt(0); 4469 } 4470 if (wl.mTimerWindow != null) { 4471 out.writeInt(1); 4472 wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL); 4473 } else { 4474 out.writeInt(0); 4475 } 4476 } 4477 } 4478 4479 int NSE = u.mSensorStats.size(); 4480 out.writeInt(NSE); 4481 if (NSE > 0) { 4482 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent 4483 : u.mSensorStats.entrySet()) { 4484 out.writeInt(ent.getKey()); 4485 Uid.Sensor se = ent.getValue(); 4486 if (se.mTimer != null) { 4487 out.writeInt(1); 4488 se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL); 4489 } else { 4490 out.writeInt(0); 4491 } 4492 } 4493 } 4494 4495 int NP = u.mProcessStats.size(); 4496 out.writeInt(NP); 4497 if (NP > 0) { 4498 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent 4499 : u.mProcessStats.entrySet()) { 4500 out.writeString(ent.getKey()); 4501 Uid.Proc ps = ent.getValue(); 4502 out.writeLong(ps.mUserTime); 4503 out.writeLong(ps.mSystemTime); 4504 out.writeInt(ps.mStarts); 4505 ps.writeExcessiveWakeToParcelLocked(out); 4506 } 4507 } 4508 4509 NP = u.mPackageStats.size(); 4510 out.writeInt(NP); 4511 if (NP > 0) { 4512 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent 4513 : u.mPackageStats.entrySet()) { 4514 out.writeString(ent.getKey()); 4515 Uid.Pkg ps = ent.getValue(); 4516 out.writeInt(ps.mWakeups); 4517 final int NS = ps.mServiceStats.size(); 4518 out.writeInt(NS); 4519 if (NS > 0) { 4520 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent 4521 : ps.mServiceStats.entrySet()) { 4522 out.writeString(sent.getKey()); 4523 BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue(); 4524 long time = ss.getStartTimeToNowLocked(NOW); 4525 out.writeLong(time); 4526 out.writeInt(ss.mStarts); 4527 out.writeInt(ss.mLaunches); 4528 } 4529 } 4530 } 4531 } 4532 4533 out.writeLong(u.getTcpBytesReceived(STATS_SINCE_CHARGED)); 4534 out.writeLong(u.getTcpBytesSent(STATS_SINCE_CHARGED)); 4535 } 4536 } 4537 4538 public void readFromParcel(Parcel in) { 4539 readFromParcelLocked(in); 4540 } 4541 4542 void readFromParcelLocked(Parcel in) { 4543 int magic = in.readInt(); 4544 if (magic != MAGIC) { 4545 throw new ParcelFormatException("Bad magic number"); 4546 } 4547 4548 readHistory(in); 4549 4550 mStartCount = in.readInt(); 4551 mBatteryUptime = in.readLong(); 4552 mBatteryLastUptime = 0; 4553 mBatteryRealtime = in.readLong(); 4554 mBatteryLastRealtime = 0; 4555 mScreenOn = false; 4556 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in); 4557 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 4558 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in); 4559 } 4560 mInputEventCounter = new Counter(mUnpluggables, in); 4561 mPhoneOn = false; 4562 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 4563 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 4564 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in); 4565 } 4566 mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables, in); 4567 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 4568 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in); 4569 } 4570 mWifiOn = false; 4571 mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 4572 mWifiRunning = false; 4573 mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 4574 mBluetoothOn = false; 4575 mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 4576 mUptime = in.readLong(); 4577 mUptimeStart = in.readLong(); 4578 mLastUptime = 0; 4579 mRealtime = in.readLong(); 4580 mRealtimeStart = in.readLong(); 4581 mLastRealtime = 0; 4582 mOnBattery = in.readInt() != 0; 4583 mOnBatteryInternal = false; // we are no longer really running. 4584 mTrackBatteryPastUptime = in.readLong(); 4585 mTrackBatteryUptimeStart = in.readLong(); 4586 mTrackBatteryPastRealtime = in.readLong(); 4587 mTrackBatteryRealtimeStart = in.readLong(); 4588 mUnpluggedBatteryUptime = in.readLong(); 4589 mUnpluggedBatteryRealtime = in.readLong(); 4590 mDischargeUnplugLevel = in.readInt(); 4591 mDischargeCurrentLevel = in.readInt(); 4592 mLowDischargeAmountSinceCharge = in.readInt(); 4593 mHighDischargeAmountSinceCharge = in.readInt(); 4594 mLastWriteTime = in.readLong(); 4595 4596 mMobileDataRx[STATS_LAST] = in.readLong(); 4597 mMobileDataRx[STATS_SINCE_UNPLUGGED] = -1; 4598 mMobileDataTx[STATS_LAST] = in.readLong(); 4599 mMobileDataTx[STATS_SINCE_UNPLUGGED] = -1; 4600 mTotalDataRx[STATS_LAST] = in.readLong(); 4601 mTotalDataRx[STATS_SINCE_UNPLUGGED] = -1; 4602 mTotalDataTx[STATS_LAST] = in.readLong(); 4603 mTotalDataTx[STATS_SINCE_UNPLUGGED] = -1; 4604 4605 mRadioDataUptime = in.readLong(); 4606 mRadioDataStart = -1; 4607 4608 mBluetoothPingCount = in.readInt(); 4609 mBluetoothPingStart = -1; 4610 4611 mKernelWakelockStats.clear(); 4612 int NKW = in.readInt(); 4613 for (int ikw = 0; ikw < NKW; ikw++) { 4614 if (in.readInt() != 0) { 4615 String wakelockName = in.readString(); 4616 in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel 4617 SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in); 4618 mKernelWakelockStats.put(wakelockName, kwlt); 4619 } 4620 } 4621 4622 mPartialTimers.clear(); 4623 mFullTimers.clear(); 4624 mWindowTimers.clear(); 4625 4626 sNumSpeedSteps = in.readInt(); 4627 4628 int numUids = in.readInt(); 4629 mUidStats.clear(); 4630 for (int i = 0; i < numUids; i++) { 4631 int uid = in.readInt(); 4632 Uid u = new Uid(uid); 4633 u.readFromParcelLocked(mUnpluggables, in); 4634 mUidStats.append(uid, u); 4635 } 4636 } 4637 4638 public void writeToParcel(Parcel out, int flags) { 4639 writeToParcelLocked(out, true, flags); 4640 } 4641 4642 public void writeToParcelWithoutUids(Parcel out, int flags) { 4643 writeToParcelLocked(out, false, flags); 4644 } 4645 4646 @SuppressWarnings("unused") 4647 void writeToParcelLocked(Parcel out, boolean inclUids, int flags) { 4648 final long uSecUptime = SystemClock.uptimeMillis() * 1000; 4649 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 4650 final long batteryUptime = getBatteryUptimeLocked(uSecUptime); 4651 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 4652 4653 out.writeInt(MAGIC); 4654 4655 writeHistory(out); 4656 4657 out.writeInt(mStartCount); 4658 out.writeLong(mBatteryUptime); 4659 out.writeLong(mBatteryRealtime); 4660 mScreenOnTimer.writeToParcel(out, batteryRealtime); 4661 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 4662 mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime); 4663 } 4664 mInputEventCounter.writeToParcel(out); 4665 mPhoneOnTimer.writeToParcel(out, batteryRealtime); 4666 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 4667 mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime); 4668 } 4669 mPhoneSignalScanningTimer.writeToParcel(out, batteryRealtime); 4670 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 4671 mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime); 4672 } 4673 mWifiOnTimer.writeToParcel(out, batteryRealtime); 4674 mWifiRunningTimer.writeToParcel(out, batteryRealtime); 4675 mBluetoothOnTimer.writeToParcel(out, batteryRealtime); 4676 out.writeLong(mUptime); 4677 out.writeLong(mUptimeStart); 4678 out.writeLong(mRealtime); 4679 out.writeLong(mRealtimeStart); 4680 out.writeInt(mOnBattery ? 1 : 0); 4681 out.writeLong(batteryUptime); 4682 out.writeLong(mTrackBatteryUptimeStart); 4683 out.writeLong(batteryRealtime); 4684 out.writeLong(mTrackBatteryRealtimeStart); 4685 out.writeLong(mUnpluggedBatteryUptime); 4686 out.writeLong(mUnpluggedBatteryRealtime); 4687 out.writeInt(mDischargeUnplugLevel); 4688 out.writeInt(mDischargeCurrentLevel); 4689 out.writeInt(mLowDischargeAmountSinceCharge); 4690 out.writeInt(mHighDischargeAmountSinceCharge); 4691 out.writeLong(mLastWriteTime); 4692 4693 out.writeLong(getMobileTcpBytesReceived(STATS_SINCE_UNPLUGGED)); 4694 out.writeLong(getMobileTcpBytesSent(STATS_SINCE_UNPLUGGED)); 4695 out.writeLong(getTotalTcpBytesReceived(STATS_SINCE_UNPLUGGED)); 4696 out.writeLong(getTotalTcpBytesSent(STATS_SINCE_UNPLUGGED)); 4697 4698 // Write radio uptime for data 4699 out.writeLong(getRadioDataUptime()); 4700 4701 out.writeInt(getBluetoothPingCount()); 4702 4703 if (inclUids) { 4704 out.writeInt(mKernelWakelockStats.size()); 4705 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 4706 SamplingTimer kwlt = ent.getValue(); 4707 if (kwlt != null) { 4708 out.writeInt(1); 4709 out.writeString(ent.getKey()); 4710 Timer.writeTimerToParcel(out, kwlt, batteryRealtime); 4711 } else { 4712 out.writeInt(0); 4713 } 4714 } 4715 } else { 4716 out.writeInt(0); 4717 } 4718 4719 out.writeInt(sNumSpeedSteps); 4720 4721 if (inclUids) { 4722 int size = mUidStats.size(); 4723 out.writeInt(size); 4724 for (int i = 0; i < size; i++) { 4725 out.writeInt(mUidStats.keyAt(i)); 4726 Uid uid = mUidStats.valueAt(i); 4727 4728 uid.writeToParcelLocked(out, batteryRealtime); 4729 } 4730 } else { 4731 out.writeInt(0); 4732 } 4733 } 4734 4735 public static final Parcelable.Creator<BatteryStatsImpl> CREATOR = 4736 new Parcelable.Creator<BatteryStatsImpl>() { 4737 public BatteryStatsImpl createFromParcel(Parcel in) { 4738 return new BatteryStatsImpl(in); 4739 } 4740 4741 public BatteryStatsImpl[] newArray(int size) { 4742 return new BatteryStatsImpl[size]; 4743 } 4744 }; 4745 4746 public void dumpLocked(PrintWriter pw) { 4747 if (DEBUG) { 4748 Printer pr = new PrintWriterPrinter(pw); 4749 pr.println("*** Screen timer:"); 4750 mScreenOnTimer.logState(pr, " "); 4751 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 4752 pr.println("*** Screen brightness #" + i + ":"); 4753 mScreenBrightnessTimer[i].logState(pr, " "); 4754 } 4755 pr.println("*** Input event counter:"); 4756 mInputEventCounter.logState(pr, " "); 4757 pr.println("*** Phone timer:"); 4758 mPhoneOnTimer.logState(pr, " "); 4759 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 4760 pr.println("*** Signal strength #" + i + ":"); 4761 mPhoneSignalStrengthsTimer[i].logState(pr, " "); 4762 } 4763 pr.println("*** Signal scanning :"); 4764 mPhoneSignalScanningTimer.logState(pr, " "); 4765 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 4766 pr.println("*** Data connection type #" + i + ":"); 4767 mPhoneDataConnectionsTimer[i].logState(pr, " "); 4768 } 4769 pr.println("*** Wifi timer:"); 4770 mWifiOnTimer.logState(pr, " "); 4771 pr.println("*** WifiRunning timer:"); 4772 mWifiRunningTimer.logState(pr, " "); 4773 pr.println("*** Bluetooth timer:"); 4774 mBluetoothOnTimer.logState(pr, " "); 4775 } 4776 super.dumpLocked(pw); 4777 } 4778} 4779