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