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