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