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