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