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