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