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