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