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