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