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