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 17 package com.android.internal.os; 18 19 import com.android.internal.util.JournaledFile; 20 21 import android.bluetooth.BluetoothHeadset; 22 import android.net.TrafficStats; 23 import android.os.BatteryStats; 24 import android.os.Parcel; 25 import android.os.ParcelFormatException; 26 import android.os.Parcelable; 27 import android.os.Process; 28 import android.os.SystemClock; 29 import android.telephony.ServiceState; 30 import android.telephony.SignalStrength; 31 import android.telephony.TelephonyManager; 32 import android.util.Log; 33 import android.util.PrintWriterPrinter; 34 import android.util.Printer; 35 import android.util.Slog; 36 import android.util.SparseArray; 37 38 import java.io.BufferedReader; 39 import java.io.File; 40 import java.io.FileInputStream; 41 import java.io.FileOutputStream; 42 import java.io.FileReader; 43 import java.io.IOException; 44 import java.io.PrintWriter; 45 import java.util.ArrayList; 46 import java.util.HashMap; 47 import java.util.Iterator; 48 import java.util.Map; 49 import java.util.concurrent.atomic.AtomicInteger; 50 51 /** 52 * All information we are collecting about things that can happen that impact 53 * battery life. All times are represented in microseconds except where indicated 54 * otherwise. 55 */ 56 public final class BatteryStatsImpl extends BatteryStats { 57 private static final String TAG = "BatteryStatsImpl"; 58 private static final boolean DEBUG = false; 59 60 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data 61 private static final int MAGIC = 0xBA757475; // 'BATSTATS' 62 63 // Current on-disk Parcel version 64 private static final int VERSION = 43; 65 66 // The maximum number of names wakelocks we will keep track of 67 // per uid; once the limit is reached, we batch the remaining wakelocks 68 // in to one common name. 69 private static final int MAX_WAKELOCKS_PER_UID = 20; 70 71 private static final String BATCHED_WAKELOCK_NAME = "*overflow*"; 72 73 private static int sNumSpeedSteps; 74 75 private final JournaledFile mFile; 76 77 /** 78 * The statistics we have collected organized by uids. 79 */ 80 final SparseArray<BatteryStatsImpl.Uid> mUidStats = 81 new SparseArray<BatteryStatsImpl.Uid>(); 82 83 // A set of pools of currently active timers. When a timer is queried, we will divide the 84 // elapsed time by the number of active timers to arrive at that timer's share of the time. 85 // In order to do this, we must refresh each timer whenever the number of active timers 86 // changes. 87 final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>(); 88 final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>(); 89 final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>(); 90 final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers 91 = new SparseArray<ArrayList<StopwatchTimer>>(); 92 93 // These are the objects that will want to do something when the device 94 // is unplugged from power. 95 final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>(); 96 97 int mStartCount; 98 99 long mBatteryUptime; 100 long mBatteryLastUptime; 101 long mBatteryRealtime; 102 long mBatteryLastRealtime; 103 104 long mUptime; 105 long mUptimeStart; 106 long mLastUptime; 107 long mRealtime; 108 long mRealtimeStart; 109 long mLastRealtime; 110 111 boolean mScreenOn; 112 StopwatchTimer mScreenOnTimer; 113 114 int mScreenBrightnessBin = -1; 115 final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS]; 116 117 Counter mInputEventCounter; 118 119 boolean mPhoneOn; 120 StopwatchTimer mPhoneOnTimer; 121 122 boolean mAudioOn; 123 StopwatchTimer mAudioOnTimer; 124 125 boolean mVideoOn; 126 StopwatchTimer mVideoOnTimer; 127 128 int mPhoneSignalStrengthBin = -1; 129 final StopwatchTimer[] mPhoneSignalStrengthsTimer = 130 new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS]; 131 132 StopwatchTimer mPhoneSignalScanningTimer; 133 134 int mPhoneDataConnectionType = -1; 135 final StopwatchTimer[] mPhoneDataConnectionsTimer = 136 new StopwatchTimer[NUM_DATA_CONNECTION_TYPES]; 137 138 boolean mWifiOn; 139 StopwatchTimer mWifiOnTimer; 140 int mWifiOnUid = -1; 141 142 boolean mWifiRunning; 143 StopwatchTimer mWifiRunningTimer; 144 145 boolean mBluetoothOn; 146 StopwatchTimer mBluetoothOnTimer; 147 148 /** Bluetooth headset object */ 149 BluetoothHeadset mBtHeadset; 150 151 /** 152 * These provide time bases that discount the time the device is plugged 153 * in to power. 154 */ 155 boolean mOnBattery; 156 boolean mOnBatteryInternal; 157 long mTrackBatteryPastUptime; 158 long mTrackBatteryUptimeStart; 159 long mTrackBatteryPastRealtime; 160 long mTrackBatteryRealtimeStart; 161 162 long mUnpluggedBatteryUptime; 163 long mUnpluggedBatteryRealtime; 164 165 /* 166 * These keep track of battery levels (1-100) at the last plug event and the last unplug event. 167 */ 168 int mDischargeStartLevel; 169 int mDischargeCurrentLevel; 170 171 long mLastWriteTime = 0; // Milliseconds 172 173 // Mobile data transferred while on battery 174 private long[] mMobileDataTx = new long[4]; 175 private long[] mMobileDataRx = new long[4]; 176 private long[] mTotalDataTx = new long[4]; 177 private long[] mTotalDataRx = new long[4]; 178 179 private long mRadioDataUptime; 180 private long mRadioDataStart; 181 182 private int mBluetoothPingCount; 183 private int mBluetoothPingStart = -1; 184 185 private int mPhoneServiceState = -1; 186 187 /* 188 * Holds a SamplingTimer associated with each kernel wakelock name being tracked. 189 */ 190 private final HashMap<String, SamplingTimer> mKernelWakelockStats = 191 new HashMap<String, SamplingTimer>(); 192 193 public Map<String, ? extends SamplingTimer> getKernelWakelockStats() { 194 return mKernelWakelockStats; 195 } 196 197 private static int sKernelWakelockUpdateVersion = 0; 198 199 private static final int[] PROC_WAKELOCKS_FORMAT = new int[] { 200 Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name 201 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count 202 Process.PROC_TAB_TERM, 203 Process.PROC_TAB_TERM, 204 Process.PROC_TAB_TERM, 205 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime 206 }; 207 208 private final String[] mProcWakelocksName = new String[3]; 209 private final long[] mProcWakelocksData = new long[3]; 210 211 /* 212 * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added 213 * to mKernelWakelockStats. 214 */ 215 private final Map<String, KernelWakelockStats> mProcWakelockFileStats = 216 new HashMap<String, KernelWakelockStats>(); 217 218 private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>(); 219 220 // For debugging 221 public BatteryStatsImpl() { 222 mFile = null; 223 } 224 225 public static interface Unpluggable { 226 void unplug(long batteryUptime, long batteryRealtime); 227 void plug(long batteryUptime, long batteryRealtime); 228 } 229 230 /** 231 * State for keeping track of counting information. 232 */ 233 public static class Counter extends BatteryStats.Counter implements Unpluggable { 234 final AtomicInteger mCount = new AtomicInteger(); 235 int mLoadedCount; 236 int mLastCount; 237 int mUnpluggedCount; 238 int mPluggedCount; 239 240 Counter(ArrayList<Unpluggable> unpluggables, Parcel in) { 241 mPluggedCount = in.readInt(); 242 mCount.set(mPluggedCount); 243 mLoadedCount = in.readInt(); 244 mLastCount = in.readInt(); 245 mUnpluggedCount = in.readInt(); 246 unpluggables.add(this); 247 } 248 249 Counter(ArrayList<Unpluggable> unpluggables) { 250 unpluggables.add(this); 251 } 252 253 public void writeToParcel(Parcel out) { 254 out.writeInt(mCount.get()); 255 out.writeInt(mLoadedCount); 256 out.writeInt(mLastCount); 257 out.writeInt(mUnpluggedCount); 258 } 259 260 public void unplug(long batteryUptime, long batteryRealtime) { 261 mUnpluggedCount = mPluggedCount; 262 mCount.set(mPluggedCount); 263 } 264 265 public void plug(long batteryUptime, long batteryRealtime) { 266 mPluggedCount = mCount.get(); 267 } 268 269 /** 270 * Writes a possibly null Counter to a Parcel. 271 * 272 * @param out the Parcel to be written to. 273 * @param counter a Counter, or null. 274 */ 275 public static void writeCounterToParcel(Parcel out, Counter counter) { 276 if (counter == null) { 277 out.writeInt(0); // indicates null 278 return; 279 } 280 out.writeInt(1); // indicates non-null 281 282 counter.writeToParcel(out); 283 } 284 285 @Override 286 public int getCountLocked(int which) { 287 int val; 288 if (which == STATS_LAST) { 289 val = mLastCount; 290 } else { 291 val = mCount.get(); 292 if (which == STATS_UNPLUGGED) { 293 val -= mUnpluggedCount; 294 } else if (which != STATS_TOTAL) { 295 val -= mLoadedCount; 296 } 297 } 298 299 return val; 300 } 301 302 public void logState(Printer pw, String prefix) { 303 pw.println(prefix + "mCount=" + mCount.get() 304 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 305 + " mUnpluggedCount=" + mUnpluggedCount 306 + " mPluggedCount=" + mPluggedCount); 307 } 308 309 void stepAtomic() { 310 mCount.incrementAndGet(); 311 } 312 313 void writeSummaryFromParcelLocked(Parcel out) { 314 int count = mCount.get(); 315 out.writeInt(count); 316 out.writeInt(count - mLoadedCount); 317 } 318 319 void readSummaryFromParcelLocked(Parcel in) { 320 mLoadedCount = in.readInt(); 321 mCount.set(mLoadedCount); 322 mLastCount = in.readInt(); 323 mUnpluggedCount = mPluggedCount = mLoadedCount; 324 } 325 } 326 327 public static class SamplingCounter extends Counter { 328 329 SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) { 330 super(unpluggables, in); 331 } 332 333 SamplingCounter(ArrayList<Unpluggable> unpluggables) { 334 super(unpluggables); 335 } 336 337 public void addCountAtomic(long count) { 338 mCount.addAndGet((int)count); 339 } 340 } 341 342 /** 343 * State for keeping track of timing information. 344 */ 345 public static abstract class Timer extends BatteryStats.Timer implements Unpluggable { 346 final int mType; 347 348 349 int mCount; 350 int mLoadedCount; 351 int mLastCount; 352 int mUnpluggedCount; 353 354 // Times are in microseconds for better accuracy when dividing by the 355 // lock count, and are in "battery realtime" units. 356 357 /** 358 * The total time we have accumulated since the start of the original 359 * boot, to the last time something interesting happened in the 360 * current run. 361 */ 362 long mTotalTime; 363 364 /** 365 * The total time we loaded for the previous runs. Subtract this from 366 * mTotalTime to find the time for the current run of the system. 367 */ 368 long mLoadedTime; 369 370 /** 371 * The run time of the last run of the system, as loaded from the 372 * saved data. 373 */ 374 long mLastTime; 375 376 /** 377 * The value of mTotalTime when unplug() was last called. Subtract 378 * this from mTotalTime to find the time since the last unplug from 379 * power. 380 */ 381 long mUnpluggedTime; 382 383 /** 384 * Constructs from a parcel. 385 * @param type 386 * @param unpluggables 387 * @param powerType 388 * @param in 389 */ 390 Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) { 391 mType = type; 392 393 mCount = in.readInt(); 394 mLoadedCount = in.readInt(); 395 mLastCount = in.readInt(); 396 mUnpluggedCount = in.readInt(); 397 mTotalTime = in.readLong(); 398 mLoadedTime = in.readLong(); 399 mLastTime = in.readLong(); 400 mUnpluggedTime = in.readLong(); 401 unpluggables.add(this); 402 } 403 404 Timer(int type, ArrayList<Unpluggable> unpluggables) { 405 mType = type; 406 unpluggables.add(this); 407 } 408 409 protected abstract long computeRunTimeLocked(long curBatteryRealtime); 410 411 protected abstract int computeCurrentCountLocked(); 412 413 414 public void writeToParcel(Parcel out, long batteryRealtime) { 415 out.writeInt(mCount); 416 out.writeInt(mLoadedCount); 417 out.writeInt(mLastCount); 418 out.writeInt(mUnpluggedCount); 419 out.writeLong(computeRunTimeLocked(batteryRealtime)); 420 out.writeLong(mLoadedTime); 421 out.writeLong(mLastTime); 422 out.writeLong(mUnpluggedTime); 423 } 424 425 public void unplug(long batteryUptime, long batteryRealtime) { 426 if (DEBUG && mType < 0) { 427 Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime 428 + " old mUnpluggedTime=" + mUnpluggedTime 429 + " old mUnpluggedCount=" + mUnpluggedCount); 430 } 431 mUnpluggedTime = computeRunTimeLocked(batteryRealtime); 432 mUnpluggedCount = mCount; 433 if (DEBUG && mType < 0) { 434 Log.v(TAG, "unplug #" + mType 435 + ": new mUnpluggedTime=" + mUnpluggedTime 436 + " new mUnpluggedCount=" + mUnpluggedCount); 437 } 438 } 439 440 public void plug(long batteryUptime, long batteryRealtime) { 441 if (DEBUG && mType < 0) { 442 Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime 443 + " old mTotalTime=" + mTotalTime); 444 } 445 mTotalTime = computeRunTimeLocked(batteryRealtime); 446 mCount = computeCurrentCountLocked(); 447 if (DEBUG && mType < 0) { 448 Log.v(TAG, "plug #" + mType 449 + ": new mTotalTime=" + mTotalTime); 450 } 451 } 452 453 /** 454 * Writes a possibly null Timer to a Parcel. 455 * 456 * @param out the Parcel to be written to. 457 * @param timer a Timer, or null. 458 */ 459 public static void writeTimerToParcel(Parcel out, Timer timer, 460 long batteryRealtime) { 461 if (timer == null) { 462 out.writeInt(0); // indicates null 463 return; 464 } 465 out.writeInt(1); // indicates non-null 466 467 timer.writeToParcel(out, batteryRealtime); 468 } 469 470 @Override 471 public long getTotalTimeLocked(long batteryRealtime, int which) { 472 long val; 473 if (which == STATS_LAST) { 474 val = mLastTime; 475 } else { 476 val = computeRunTimeLocked(batteryRealtime); 477 if (which == STATS_UNPLUGGED) { 478 val -= mUnpluggedTime; 479 } else if (which != STATS_TOTAL) { 480 val -= mLoadedTime; 481 } 482 } 483 484 return val; 485 } 486 487 @Override 488 public int getCountLocked(int which) { 489 int val; 490 if (which == STATS_LAST) { 491 val = mLastCount; 492 } else { 493 val = computeCurrentCountLocked(); 494 if (which == STATS_UNPLUGGED) { 495 val -= mUnpluggedCount; 496 } else if (which != STATS_TOTAL) { 497 val -= mLoadedCount; 498 } 499 } 500 501 return val; 502 } 503 504 public void logState(Printer pw, String prefix) { 505 pw.println(prefix + " mCount=" + mCount 506 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount 507 + " mUnpluggedCount=" + mUnpluggedCount); 508 pw.println(prefix + "mTotalTime=" + mTotalTime 509 + " mLoadedTime=" + mLoadedTime); 510 pw.println(prefix + "mLastTime=" + mLastTime 511 + " mUnpluggedTime=" + mUnpluggedTime); 512 } 513 514 515 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 516 long runTime = computeRunTimeLocked(batteryRealtime); 517 // Divide by 1000 for backwards compatibility 518 out.writeLong((runTime + 500) / 1000); 519 out.writeLong(((runTime - mLoadedTime) + 500) / 1000); 520 out.writeInt(mCount); 521 out.writeInt(mCount - mLoadedCount); 522 } 523 524 void readSummaryFromParcelLocked(Parcel in) { 525 // Multiply by 1000 for backwards compatibility 526 mTotalTime = mLoadedTime = in.readLong() * 1000; 527 mLastTime = in.readLong() * 1000; 528 mUnpluggedTime = mTotalTime; 529 mCount = mLoadedCount = in.readInt(); 530 mLastCount = in.readInt(); 531 mUnpluggedCount = mCount; 532 } 533 } 534 535 public static final class SamplingTimer extends Timer { 536 537 /** 538 * The most recent reported count from /proc/wakelocks. 539 */ 540 int mCurrentReportedCount; 541 542 /** 543 * The reported count from /proc/wakelocks when unplug() was last 544 * called. 545 */ 546 int mUnpluggedReportedCount; 547 548 /** 549 * The most recent reported total_time from /proc/wakelocks. 550 */ 551 long mCurrentReportedTotalTime; 552 553 554 /** 555 * The reported total_time from /proc/wakelocks when unplug() was last 556 * called. 557 */ 558 long mUnpluggedReportedTotalTime; 559 560 /** 561 * Whether we are currently in a discharge cycle. 562 */ 563 boolean mInDischarge; 564 565 /** 566 * Whether we are currently recording reported values. 567 */ 568 boolean mTrackingReportedValues; 569 570 /* 571 * A sequnce counter, incremented once for each update of the stats. 572 */ 573 int mUpdateVersion; 574 575 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) { 576 super(0, unpluggables, in); 577 mCurrentReportedCount = in.readInt(); 578 mUnpluggedReportedCount = in.readInt(); 579 mCurrentReportedTotalTime = in.readLong(); 580 mUnpluggedReportedTotalTime = in.readLong(); 581 mTrackingReportedValues = in.readInt() == 1; 582 mInDischarge = inDischarge; 583 } 584 585 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, 586 boolean trackReportedValues) { 587 super(0, unpluggables); 588 mTrackingReportedValues = trackReportedValues; 589 mInDischarge = inDischarge; 590 } 591 592 public void setStale() { 593 mTrackingReportedValues = false; 594 mUnpluggedReportedTotalTime = 0; 595 mUnpluggedReportedCount = 0; 596 } 597 598 public void setUpdateVersion(int version) { 599 mUpdateVersion = version; 600 } 601 602 public int getUpdateVersion() { 603 return mUpdateVersion; 604 } 605 606 public void updateCurrentReportedCount(int count) { 607 if (mInDischarge && mUnpluggedReportedCount == 0) { 608 // Updating the reported value for the first time. 609 mUnpluggedReportedCount = count; 610 // If we are receiving an update update mTrackingReportedValues; 611 mTrackingReportedValues = true; 612 } 613 mCurrentReportedCount = count; 614 } 615 616 public void updateCurrentReportedTotalTime(long totalTime) { 617 if (mInDischarge && mUnpluggedReportedTotalTime == 0) { 618 // Updating the reported value for the first time. 619 mUnpluggedReportedTotalTime = totalTime; 620 // If we are receiving an update update mTrackingReportedValues; 621 mTrackingReportedValues = true; 622 } 623 mCurrentReportedTotalTime = totalTime; 624 } 625 626 public void unplug(long batteryUptime, long batteryRealtime) { 627 super.unplug(batteryUptime, batteryRealtime); 628 if (mTrackingReportedValues) { 629 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime; 630 mUnpluggedReportedCount = mCurrentReportedCount; 631 } 632 mInDischarge = true; 633 } 634 635 public void plug(long batteryUptime, long batteryRealtime) { 636 super.plug(batteryUptime, batteryRealtime); 637 mInDischarge = false; 638 } 639 640 public void logState(Printer pw, String prefix) { 641 super.logState(pw, prefix); 642 pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount 643 + " mUnpluggedReportedCount=" + mUnpluggedReportedCount 644 + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime 645 + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime); 646 } 647 648 protected long computeRunTimeLocked(long curBatteryRealtime) { 649 return mTotalTime + (mInDischarge && mTrackingReportedValues 650 ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0); 651 } 652 653 protected int computeCurrentCountLocked() { 654 return mCount + (mInDischarge && mTrackingReportedValues 655 ? mCurrentReportedCount - mUnpluggedReportedCount : 0); 656 } 657 658 public void writeToParcel(Parcel out, long batteryRealtime) { 659 super.writeToParcel(out, batteryRealtime); 660 out.writeInt(mCurrentReportedCount); 661 out.writeInt(mUnpluggedReportedCount); 662 out.writeLong(mCurrentReportedTotalTime); 663 out.writeLong(mUnpluggedReportedTotalTime); 664 out.writeInt(mTrackingReportedValues ? 1 : 0); 665 } 666 667 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { 668 super.writeSummaryFromParcelLocked(out, batteryRealtime); 669 out.writeLong(mCurrentReportedTotalTime); 670 out.writeInt(mCurrentReportedCount); 671 out.writeInt(mTrackingReportedValues ? 1 : 0); 672 } 673 674 void readSummaryFromParcelLocked(Parcel in) { 675 super.readSummaryFromParcelLocked(in); 676 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong(); 677 mUnpluggedReportedCount = mCurrentReportedCount = in.readInt(); 678 mTrackingReportedValues = in.readInt() == 1; 679 } 680 } 681 682 /** 683 * State for keeping track of timing information. 684 */ 685 public static final class StopwatchTimer extends Timer { 686 final ArrayList<StopwatchTimer> mTimerPool; 687 int mNesting; 688 689 690 /** 691 * The last time at which we updated the timer. If mNesting is > 0, 692 * subtract this from the current battery time to find the amount of 693 * time we have been running since we last computed an update. 694 */ 695 long mUpdateTime; 696 697 /** 698 * The total time at which the timer was acquired, to determine if 699 * was actually held for an interesting duration. 700 */ 701 long mAcquireTime; 702 703 long mTimeout; 704 705 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, 706 ArrayList<Unpluggable> unpluggables, Parcel in) { 707 super(type, unpluggables, in); 708 mTimerPool = timerPool; 709 mUpdateTime = in.readLong(); 710 } 711 712 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, 713 ArrayList<Unpluggable> unpluggables) { 714 super(type, unpluggables); 715 mTimerPool = timerPool; 716 } 717 718 void setTimeout(long timeout) { 719 mTimeout = timeout; 720 } 721 722 public void writeToParcel(Parcel out, long batteryRealtime) { 723 super.writeToParcel(out, batteryRealtime); 724 out.writeLong(mUpdateTime); 725 } 726 727 public void plug(long batteryUptime, long batteryRealtime) { 728 if (mNesting > 0) { 729 if (DEBUG && mType < 0) { 730 Log.v(TAG, "old mUpdateTime=" + mUpdateTime); 731 } 732 super.plug(batteryUptime, batteryRealtime); 733 mUpdateTime = batteryRealtime; 734 if (DEBUG && mType < 0) { 735 Log.v(TAG, "new mUpdateTime=" + mUpdateTime); 736 } 737 } 738 } 739 740 public void logState(Printer pw, String prefix) { 741 super.logState(pw, prefix); 742 pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime 743 + " mAcquireTime=" + mAcquireTime); 744 } 745 746 void startRunningLocked(BatteryStatsImpl stats) { 747 if (mNesting++ == 0) { 748 mUpdateTime = stats.getBatteryRealtimeLocked( 749 SystemClock.elapsedRealtime() * 1000); 750 if (mTimerPool != null) { 751 // Accumulate time to all currently active timers before adding 752 // this new one to the pool. 753 refreshTimersLocked(stats, mTimerPool); 754 // Add this timer to the active pool 755 mTimerPool.add(this); 756 } 757 // Increment the count 758 mCount++; 759 mAcquireTime = mTotalTime; 760 if (DEBUG && mType < 0) { 761 Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime 762 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 763 + " mAcquireTime=" + mAcquireTime); 764 } 765 } 766 } 767 768 boolean isRunningLocked() { 769 return mNesting > 0; 770 } 771 772 void stopRunningLocked(BatteryStatsImpl stats) { 773 // Ignore attempt to stop a timer that isn't running 774 if (mNesting == 0) { 775 return; 776 } 777 if (--mNesting == 0) { 778 if (mTimerPool != null) { 779 // Accumulate time to all active counters, scaled by the total 780 // active in the pool, before taking this one out of the pool. 781 refreshTimersLocked(stats, mTimerPool); 782 // Remove this timer from the active pool 783 mTimerPool.remove(this); 784 } else { 785 final long realtime = SystemClock.elapsedRealtime() * 1000; 786 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 787 mNesting = 1; 788 mTotalTime = computeRunTimeLocked(batteryRealtime); 789 mNesting = 0; 790 } 791 792 if (DEBUG && mType < 0) { 793 Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime 794 + " mTotalTime=" + mTotalTime + " mCount=" + mCount 795 + " mAcquireTime=" + mAcquireTime); 796 } 797 798 if (mTotalTime == mAcquireTime) { 799 // If there was no change in the time, then discard this 800 // count. A somewhat cheezy strategy, but hey. 801 mCount--; 802 } 803 } 804 } 805 806 // Update the total time for all other running Timers with the same type as this Timer 807 // due to a change in timer count 808 private static void refreshTimersLocked(final BatteryStatsImpl stats, 809 final ArrayList<StopwatchTimer> pool) { 810 final long realtime = SystemClock.elapsedRealtime() * 1000; 811 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); 812 final int N = pool.size(); 813 for (int i=N-1; i>= 0; i--) { 814 final StopwatchTimer t = pool.get(i); 815 long heldTime = batteryRealtime - t.mUpdateTime; 816 if (heldTime > 0) { 817 t.mTotalTime += heldTime / N; 818 } 819 t.mUpdateTime = batteryRealtime; 820 } 821 } 822 823 @Override 824 protected long computeRunTimeLocked(long curBatteryRealtime) { 825 if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) { 826 curBatteryRealtime = mUpdateTime + mTimeout; 827 } 828 return mTotalTime + (mNesting > 0 829 ? (curBatteryRealtime - mUpdateTime) 830 / (mTimerPool != null ? mTimerPool.size() : 1) 831 : 0); 832 } 833 834 @Override 835 protected int computeCurrentCountLocked() { 836 return mCount; 837 } 838 839 void readSummaryFromParcelLocked(Parcel in) { 840 super.readSummaryFromParcelLocked(in); 841 mNesting = 0; 842 } 843 } 844 845 private final Map<String, KernelWakelockStats> readKernelWakelockStats() { 846 847 byte[] buffer = new byte[4096]; 848 int len; 849 850 try { 851 FileInputStream is = new FileInputStream("/proc/wakelocks"); 852 len = is.read(buffer); 853 is.close(); 854 855 if (len > 0) { 856 int i; 857 for (i=0; i<len; i++) { 858 if (buffer[i] == '\0') { 859 len = i; 860 break; 861 } 862 } 863 } 864 } catch (java.io.FileNotFoundException e) { 865 return null; 866 } catch (java.io.IOException e) { 867 return null; 868 } 869 870 return parseProcWakelocks(buffer, len); 871 } 872 873 private final Map<String, KernelWakelockStats> parseProcWakelocks( 874 byte[] wlBuffer, int len) { 875 String name; 876 int count; 877 long totalTime; 878 int startIndex, endIndex; 879 int numUpdatedWlNames = 0; 880 881 // Advance past the first line. 882 int i; 883 for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++); 884 startIndex = endIndex = i + 1; 885 886 synchronized(this) { 887 Map<String, KernelWakelockStats> m = mProcWakelockFileStats; 888 889 sKernelWakelockUpdateVersion++; 890 while (endIndex < len) { 891 for (endIndex=startIndex; 892 endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0'; 893 endIndex++); 894 // Don't go over the end of the buffer 895 if (endIndex < len) { 896 endIndex++; // endIndex is an exclusive upper bound. 897 } 898 899 String[] nameStringArray = mProcWakelocksName; 900 long[] wlData = mProcWakelocksData; 901 // Stomp out any bad characters since this is from a circular buffer 902 // A corruption is seen sometimes that results in the vm crashing 903 // This should prevent crashes and the line will probably fail to parse 904 for (int j = startIndex; j < endIndex; j++) { 905 if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?'; 906 } 907 boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex, 908 PROC_WAKELOCKS_FORMAT, nameStringArray, wlData, null); 909 910 name = nameStringArray[0]; 911 count = (int) wlData[1]; 912 // convert nanoseconds to microseconds with rounding. 913 totalTime = (wlData[2] + 500) / 1000; 914 915 if (parsed && name.length() > 0) { 916 if (!m.containsKey(name)) { 917 m.put(name, new KernelWakelockStats(count, totalTime, 918 sKernelWakelockUpdateVersion)); 919 numUpdatedWlNames++; 920 } else { 921 KernelWakelockStats kwlStats = m.get(name); 922 if (kwlStats.mVersion == sKernelWakelockUpdateVersion) { 923 kwlStats.mCount += count; 924 kwlStats.mTotalTime += totalTime; 925 } else { 926 kwlStats.mCount = count; 927 kwlStats.mTotalTime = totalTime; 928 kwlStats.mVersion = sKernelWakelockUpdateVersion; 929 numUpdatedWlNames++; 930 } 931 } 932 } 933 startIndex = endIndex; 934 } 935 936 if (m.size() != numUpdatedWlNames) { 937 // Don't report old data. 938 Iterator<KernelWakelockStats> itr = m.values().iterator(); 939 while (itr.hasNext()) { 940 if (itr.next().mVersion != sKernelWakelockUpdateVersion) { 941 itr.remove(); 942 } 943 } 944 } 945 return m; 946 } 947 } 948 949 private class KernelWakelockStats { 950 public int mCount; 951 public long mTotalTime; 952 public int mVersion; 953 954 KernelWakelockStats(int count, long totalTime, int version) { 955 mCount = count; 956 mTotalTime = totalTime; 957 mVersion = version; 958 } 959 } 960 961 /* 962 * Get the KernelWakelockTimer associated with name, and create a new one if one 963 * doesn't already exist. 964 */ 965 public SamplingTimer getKernelWakelockTimerLocked(String name) { 966 SamplingTimer kwlt = mKernelWakelockStats.get(name); 967 if (kwlt == null) { 968 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 969 true /* track reported values */); 970 mKernelWakelockStats.put(name, kwlt); 971 } 972 return kwlt; 973 } 974 975 private void doDataPlug(long[] dataTransfer, long currentBytes) { 976 dataTransfer[STATS_LAST] = dataTransfer[STATS_UNPLUGGED]; 977 dataTransfer[STATS_UNPLUGGED] = -1; 978 } 979 980 private void doDataUnplug(long[] dataTransfer, long currentBytes) { 981 dataTransfer[STATS_UNPLUGGED] = currentBytes; 982 } 983 984 /** 985 * Radio uptime in microseconds when transferring data. This value is very approximate. 986 * @return 987 */ 988 private long getCurrentRadioDataUptime() { 989 try { 990 File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms"); 991 if (!awakeTimeFile.exists()) return 0; 992 BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile)); 993 String line = br.readLine(); 994 br.close(); 995 return Long.parseLong(line) * 1000; 996 } catch (NumberFormatException nfe) { 997 // Nothing 998 } catch (IOException ioe) { 999 // Nothing 1000 } 1001 return 0; 1002 } 1003 1004 /** 1005 * @deprecated use getRadioDataUptime 1006 */ 1007 public long getRadioDataUptimeMs() { 1008 return getRadioDataUptime() / 1000; 1009 } 1010 1011 /** 1012 * Returns the duration that the cell radio was up for data transfers. 1013 */ 1014 public long getRadioDataUptime() { 1015 if (mRadioDataStart == -1) { 1016 return mRadioDataUptime; 1017 } else { 1018 return getCurrentRadioDataUptime() - mRadioDataStart; 1019 } 1020 } 1021 1022 private int getCurrentBluetoothPingCount() { 1023 if (mBtHeadset != null) { 1024 return mBtHeadset.getBatteryUsageHint(); 1025 } 1026 return -1; 1027 } 1028 1029 public int getBluetoothPingCount() { 1030 if (mBluetoothPingStart == -1) { 1031 return mBluetoothPingCount; 1032 } else if (mBtHeadset != null) { 1033 return getCurrentBluetoothPingCount() - mBluetoothPingStart; 1034 } 1035 return 0; 1036 } 1037 1038 public void setBtHeadset(BluetoothHeadset headset) { 1039 if (headset != null && mBtHeadset == null && isOnBattery() && mBluetoothPingStart == -1) { 1040 mBluetoothPingStart = getCurrentBluetoothPingCount(); 1041 } 1042 mBtHeadset = headset; 1043 } 1044 1045 public void doUnplug(long batteryUptime, long batteryRealtime) { 1046 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 1047 Uid u = mUidStats.valueAt(iu); 1048 u.mStartedTcpBytesReceived = TrafficStats.getUidRxBytes(u.mUid); 1049 u.mStartedTcpBytesSent = TrafficStats.getUidTxBytes(u.mUid); 1050 u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived; 1051 u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent; 1052 } 1053 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 1054 mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime); 1055 } 1056 // Track total mobile data 1057 doDataUnplug(mMobileDataRx, TrafficStats.getMobileRxBytes()); 1058 doDataUnplug(mMobileDataTx, TrafficStats.getMobileTxBytes()); 1059 doDataUnplug(mTotalDataRx, TrafficStats.getTotalRxBytes()); 1060 doDataUnplug(mTotalDataTx, TrafficStats.getTotalTxBytes()); 1061 // Track radio awake time 1062 mRadioDataStart = getCurrentRadioDataUptime(); 1063 mRadioDataUptime = 0; 1064 // Track bt headset ping count 1065 mBluetoothPingStart = getCurrentBluetoothPingCount(); 1066 mBluetoothPingCount = 0; 1067 } 1068 1069 public void doPlug(long batteryUptime, long batteryRealtime) { 1070 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { 1071 Uid u = mUidStats.valueAt(iu); 1072 if (u.mStartedTcpBytesReceived >= 0) { 1073 u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived(); 1074 u.mStartedTcpBytesReceived = -1; 1075 } 1076 if (u.mStartedTcpBytesSent >= 0) { 1077 u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent(); 1078 u.mStartedTcpBytesSent = -1; 1079 } 1080 } 1081 for (int i = mUnpluggables.size() - 1; i >= 0; i--) { 1082 mUnpluggables.get(i).plug(batteryUptime, batteryRealtime); 1083 } 1084 doDataPlug(mMobileDataRx, TrafficStats.getMobileRxBytes()); 1085 doDataPlug(mMobileDataTx, TrafficStats.getMobileTxBytes()); 1086 doDataPlug(mTotalDataRx, TrafficStats.getTotalRxBytes()); 1087 doDataPlug(mTotalDataTx, TrafficStats.getTotalTxBytes()); 1088 // Track radio awake time 1089 mRadioDataUptime = getRadioDataUptime(); 1090 mRadioDataStart = -1; 1091 1092 // Track bt headset ping count 1093 mBluetoothPingCount = getBluetoothPingCount(); 1094 mBluetoothPingStart = -1; 1095 } 1096 1097 public void noteStartGps(int uid) { 1098 getUidStatsLocked(uid).noteStartGps(); 1099 } 1100 1101 public void noteStopGps(int uid) { 1102 getUidStatsLocked(uid).noteStopGps(); 1103 } 1104 1105 public void noteScreenOnLocked() { 1106 if (!mScreenOn) { 1107 mScreenOn = true; 1108 mScreenOnTimer.startRunningLocked(this); 1109 if (mScreenBrightnessBin >= 0) { 1110 mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this); 1111 } 1112 } 1113 } 1114 1115 public void noteScreenOffLocked() { 1116 if (mScreenOn) { 1117 mScreenOn = false; 1118 mScreenOnTimer.stopRunningLocked(this); 1119 if (mScreenBrightnessBin >= 0) { 1120 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this); 1121 } 1122 } 1123 } 1124 1125 public void noteScreenBrightnessLocked(int brightness) { 1126 // Bin the brightness. 1127 int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS); 1128 if (bin < 0) bin = 0; 1129 else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1; 1130 if (mScreenBrightnessBin != bin) { 1131 if (mScreenOn) { 1132 if (mScreenBrightnessBin >= 0) { 1133 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this); 1134 } 1135 mScreenBrightnessTimer[bin].startRunningLocked(this); 1136 } 1137 mScreenBrightnessBin = bin; 1138 } 1139 } 1140 1141 public void noteInputEventAtomic() { 1142 mInputEventCounter.stepAtomic(); 1143 } 1144 1145 public void noteUserActivityLocked(int uid, int event) { 1146 getUidStatsLocked(uid).noteUserActivityLocked(event); 1147 } 1148 1149 public void notePhoneOnLocked() { 1150 if (!mPhoneOn) { 1151 mPhoneOn = true; 1152 mPhoneOnTimer.startRunningLocked(this); 1153 } 1154 } 1155 1156 public void notePhoneOffLocked() { 1157 if (mPhoneOn) { 1158 mPhoneOn = false; 1159 mPhoneOnTimer.stopRunningLocked(this); 1160 } 1161 } 1162 1163 /** 1164 * Telephony stack updates the phone state. 1165 * @param state phone state from ServiceState.getState() 1166 */ 1167 public void notePhoneStateLocked(int state) { 1168 int bin = mPhoneSignalStrengthBin; 1169 boolean isAirplaneMode = state == ServiceState.STATE_POWER_OFF; 1170 // Stop all timers 1171 if (isAirplaneMode || state == ServiceState.STATE_OUT_OF_SERVICE) { 1172 for (int i = 0; i < NUM_SIGNAL_STRENGTH_BINS; i++) { 1173 while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) { 1174 mPhoneSignalStrengthsTimer[i].stopRunningLocked(this); 1175 } 1176 } 1177 } 1178 // Stop Signal Scanning timer, in case we're going into service 1179 while (mPhoneSignalScanningTimer.isRunningLocked()) { 1180 mPhoneSignalScanningTimer.stopRunningLocked(this); 1181 } 1182 1183 // If we're back in service or continuing in service, restart the old timer. 1184 if (state == ServiceState.STATE_IN_SERVICE) { 1185 if (bin == -1) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1186 if (!mPhoneSignalStrengthsTimer[bin].isRunningLocked()) { 1187 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this); 1188 } 1189 } else if (state == ServiceState.STATE_OUT_OF_SERVICE) { 1190 mPhoneSignalStrengthBin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1191 if (!mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].isRunningLocked()) { 1192 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].startRunningLocked(this); 1193 } 1194 if (!mPhoneSignalScanningTimer.isRunningLocked()) { 1195 mPhoneSignalScanningTimer.startRunningLocked(this); 1196 } 1197 } 1198 mPhoneServiceState = state; 1199 } 1200 1201 public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) { 1202 // Bin the strength. 1203 int bin; 1204 if (mPhoneServiceState == ServiceState.STATE_POWER_OFF 1205 || mPhoneServiceState == ServiceState.STATE_OUT_OF_SERVICE) { 1206 // Ignore any signal strength changes when radio was turned off or out of service. 1207 return; 1208 } 1209 if (!signalStrength.isGsm()) { 1210 int dBm = signalStrength.getCdmaDbm(); 1211 if (dBm >= -75) bin = SIGNAL_STRENGTH_GREAT; 1212 else if (dBm >= -85) bin = SIGNAL_STRENGTH_GOOD; 1213 else if (dBm >= -95) bin = SIGNAL_STRENGTH_MODERATE; 1214 else if (dBm >= -100) bin = SIGNAL_STRENGTH_POOR; 1215 else bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1216 } else { 1217 int asu = signalStrength.getGsmSignalStrength(); 1218 if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 1219 else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT; 1220 else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD; 1221 else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE; 1222 else bin = SIGNAL_STRENGTH_POOR; 1223 } 1224 if (mPhoneSignalStrengthBin != bin) { 1225 if (mPhoneSignalStrengthBin >= 0) { 1226 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this); 1227 } 1228 mPhoneSignalStrengthBin = bin; 1229 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this); 1230 } 1231 } 1232 1233 public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) { 1234 int bin = DATA_CONNECTION_NONE; 1235 if (hasData) { 1236 switch (dataType) { 1237 case TelephonyManager.NETWORK_TYPE_EDGE: 1238 bin = DATA_CONNECTION_EDGE; 1239 break; 1240 case TelephonyManager.NETWORK_TYPE_GPRS: 1241 bin = DATA_CONNECTION_GPRS; 1242 break; 1243 case TelephonyManager.NETWORK_TYPE_UMTS: 1244 bin = DATA_CONNECTION_UMTS; 1245 break; 1246 default: 1247 bin = DATA_CONNECTION_OTHER; 1248 break; 1249 } 1250 } 1251 if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData); 1252 if (mPhoneDataConnectionType != bin) { 1253 if (mPhoneDataConnectionType >= 0) { 1254 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this); 1255 } 1256 mPhoneDataConnectionType = bin; 1257 mPhoneDataConnectionsTimer[bin].startRunningLocked(this); 1258 } 1259 } 1260 1261 public void noteWifiOnLocked(int uid) { 1262 if (!mWifiOn) { 1263 mWifiOn = true; 1264 mWifiOnTimer.startRunningLocked(this); 1265 } 1266 if (mWifiOnUid != uid) { 1267 if (mWifiOnUid >= 0) { 1268 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked(); 1269 } 1270 mWifiOnUid = uid; 1271 getUidStatsLocked(uid).noteWifiTurnedOnLocked(); 1272 } 1273 } 1274 1275 public void noteWifiOffLocked(int uid) { 1276 if (mWifiOn) { 1277 mWifiOn = false; 1278 mWifiOnTimer.stopRunningLocked(this); 1279 } 1280 if (mWifiOnUid >= 0) { 1281 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked(); 1282 mWifiOnUid = -1; 1283 } 1284 } 1285 1286 public void noteAudioOnLocked(int uid) { 1287 if (!mAudioOn) { 1288 mAudioOn = true; 1289 mAudioOnTimer.startRunningLocked(this); 1290 } 1291 getUidStatsLocked(uid).noteAudioTurnedOnLocked(); 1292 } 1293 1294 public void noteAudioOffLocked(int uid) { 1295 if (mAudioOn) { 1296 mAudioOn = false; 1297 mAudioOnTimer.stopRunningLocked(this); 1298 } 1299 getUidStatsLocked(uid).noteAudioTurnedOffLocked(); 1300 } 1301 1302 public void noteVideoOnLocked(int uid) { 1303 if (!mVideoOn) { 1304 mVideoOn = true; 1305 mVideoOnTimer.startRunningLocked(this); 1306 } 1307 getUidStatsLocked(uid).noteVideoTurnedOnLocked(); 1308 } 1309 1310 public void noteVideoOffLocked(int uid) { 1311 if (mVideoOn) { 1312 mVideoOn = false; 1313 mVideoOnTimer.stopRunningLocked(this); 1314 } 1315 getUidStatsLocked(uid).noteVideoTurnedOffLocked(); 1316 } 1317 1318 public void noteWifiRunningLocked() { 1319 if (!mWifiRunning) { 1320 mWifiRunning = true; 1321 mWifiRunningTimer.startRunningLocked(this); 1322 } 1323 } 1324 1325 public void noteWifiStoppedLocked() { 1326 if (mWifiRunning) { 1327 mWifiRunning = false; 1328 mWifiRunningTimer.stopRunningLocked(this); 1329 } 1330 } 1331 1332 public void noteBluetoothOnLocked() { 1333 if (!mBluetoothOn) { 1334 mBluetoothOn = true; 1335 mBluetoothOnTimer.startRunningLocked(this); 1336 } 1337 } 1338 1339 public void noteBluetoothOffLocked() { 1340 if (mBluetoothOn) { 1341 mBluetoothOn = false; 1342 mBluetoothOnTimer.stopRunningLocked(this); 1343 } 1344 } 1345 1346 public void noteFullWifiLockAcquiredLocked(int uid) { 1347 getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(); 1348 } 1349 1350 public void noteFullWifiLockReleasedLocked(int uid) { 1351 getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(); 1352 } 1353 1354 public void noteScanWifiLockAcquiredLocked(int uid) { 1355 getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked(); 1356 } 1357 1358 public void noteScanWifiLockReleasedLocked(int uid) { 1359 getUidStatsLocked(uid).noteScanWifiLockReleasedLocked(); 1360 } 1361 1362 public void noteWifiMulticastEnabledLocked(int uid) { 1363 getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(); 1364 } 1365 1366 public void noteWifiMulticastDisabledLocked(int uid) { 1367 getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(); 1368 } 1369 1370 @Override public long getScreenOnTime(long batteryRealtime, int which) { 1371 return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which); 1372 } 1373 1374 @Override public long getScreenBrightnessTime(int brightnessBin, 1375 long batteryRealtime, int which) { 1376 return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked( 1377 batteryRealtime, which); 1378 } 1379 1380 @Override public int getInputEventCount(int which) { 1381 return mInputEventCounter.getCountLocked(which); 1382 } 1383 1384 @Override public long getPhoneOnTime(long batteryRealtime, int which) { 1385 return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which); 1386 } 1387 1388 @Override public long getPhoneSignalStrengthTime(int strengthBin, 1389 long batteryRealtime, int which) { 1390 return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked( 1391 batteryRealtime, which); 1392 } 1393 1394 @Override public long getPhoneSignalScanningTime( 1395 long batteryRealtime, int which) { 1396 return mPhoneSignalScanningTimer.getTotalTimeLocked( 1397 batteryRealtime, which); 1398 } 1399 1400 @Override public int getPhoneSignalStrengthCount(int dataType, int which) { 1401 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1402 } 1403 1404 @Override public long getPhoneDataConnectionTime(int dataType, 1405 long batteryRealtime, int which) { 1406 return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked( 1407 batteryRealtime, which); 1408 } 1409 1410 @Override public int getPhoneDataConnectionCount(int dataType, int which) { 1411 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); 1412 } 1413 1414 @Override public long getWifiOnTime(long batteryRealtime, int which) { 1415 return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which); 1416 } 1417 1418 @Override public long getWifiRunningTime(long batteryRealtime, int which) { 1419 return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which); 1420 } 1421 1422 @Override public long getBluetoothOnTime(long batteryRealtime, int which) { 1423 return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which); 1424 } 1425 1426 @Override public boolean getIsOnBattery() { 1427 return mOnBattery; 1428 } 1429 1430 @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() { 1431 return mUidStats; 1432 } 1433 1434 /** 1435 * The statistics associated with a particular uid. 1436 */ 1437 public final class Uid extends BatteryStats.Uid { 1438 1439 final int mUid; 1440 long mLoadedTcpBytesReceived; 1441 long mLoadedTcpBytesSent; 1442 long mCurrentTcpBytesReceived; 1443 long mCurrentTcpBytesSent; 1444 long mTcpBytesReceivedAtLastUnplug; 1445 long mTcpBytesSentAtLastUnplug; 1446 1447 // These are not saved/restored when parcelling, since we want 1448 // to return from the parcel with a snapshot of the state. 1449 long mStartedTcpBytesReceived = -1; 1450 long mStartedTcpBytesSent = -1; 1451 1452 boolean mWifiTurnedOn; 1453 StopwatchTimer mWifiTurnedOnTimer; 1454 1455 boolean mFullWifiLockOut; 1456 StopwatchTimer mFullWifiLockTimer; 1457 1458 boolean mScanWifiLockOut; 1459 StopwatchTimer mScanWifiLockTimer; 1460 1461 boolean mWifiMulticastEnabled; 1462 StopwatchTimer mWifiMulticastTimer; 1463 1464 boolean mAudioTurnedOn; 1465 StopwatchTimer mAudioTurnedOnTimer; 1466 1467 boolean mVideoTurnedOn; 1468 StopwatchTimer mVideoTurnedOnTimer; 1469 1470 Counter[] mUserActivityCounters; 1471 1472 /** 1473 * The statistics we have collected for this uid's wake locks. 1474 */ 1475 final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>(); 1476 1477 /** 1478 * The statistics we have collected for this uid's sensor activations. 1479 */ 1480 final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>(); 1481 1482 /** 1483 * The statistics we have collected for this uid's processes. 1484 */ 1485 final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>(); 1486 1487 /** 1488 * The statistics we have collected for this uid's processes. 1489 */ 1490 final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>(); 1491 1492 public Uid(int uid) { 1493 mUid = uid; 1494 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables); 1495 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables); 1496 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables); 1497 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1498 null, mUnpluggables); 1499 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables); 1500 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables); 1501 } 1502 1503 @Override 1504 public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() { 1505 return mWakelockStats; 1506 } 1507 1508 @Override 1509 public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() { 1510 return mSensorStats; 1511 } 1512 1513 @Override 1514 public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() { 1515 return mProcessStats; 1516 } 1517 1518 @Override 1519 public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { 1520 return mPackageStats; 1521 } 1522 1523 @Override 1524 public int getUid() { 1525 return mUid; 1526 } 1527 1528 @Override 1529 public long getTcpBytesReceived(int which) { 1530 if (which == STATS_LAST) { 1531 return mLoadedTcpBytesReceived; 1532 } else { 1533 long current = computeCurrentTcpBytesReceived(); 1534 if (which == STATS_UNPLUGGED) { 1535 current -= mTcpBytesReceivedAtLastUnplug; 1536 } else if (which == STATS_TOTAL) { 1537 current += mLoadedTcpBytesReceived; 1538 } 1539 return current; 1540 } 1541 } 1542 1543 public long computeCurrentTcpBytesReceived() { 1544 return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0 1545 ? (TrafficStats.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0); 1546 } 1547 1548 @Override 1549 public long getTcpBytesSent(int which) { 1550 if (which == STATS_LAST) { 1551 return mLoadedTcpBytesSent; 1552 } else { 1553 long current = computeCurrentTcpBytesSent(); 1554 if (which == STATS_UNPLUGGED) { 1555 current -= mTcpBytesSentAtLastUnplug; 1556 } else if (which == STATS_TOTAL) { 1557 current += mLoadedTcpBytesSent; 1558 } 1559 return current; 1560 } 1561 } 1562 1563 @Override 1564 public void noteWifiTurnedOnLocked() { 1565 if (!mWifiTurnedOn) { 1566 mWifiTurnedOn = true; 1567 mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1568 } 1569 } 1570 1571 @Override 1572 public void noteWifiTurnedOffLocked() { 1573 if (mWifiTurnedOn) { 1574 mWifiTurnedOn = false; 1575 mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1576 } 1577 } 1578 1579 @Override 1580 public void noteFullWifiLockAcquiredLocked() { 1581 if (!mFullWifiLockOut) { 1582 mFullWifiLockOut = true; 1583 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 1584 } 1585 } 1586 1587 @Override 1588 public void noteVideoTurnedOnLocked() { 1589 if (!mVideoTurnedOn) { 1590 mVideoTurnedOn = true; 1591 mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1592 } 1593 } 1594 1595 @Override 1596 public void noteVideoTurnedOffLocked() { 1597 if (mVideoTurnedOn) { 1598 mVideoTurnedOn = false; 1599 mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1600 } 1601 } 1602 1603 @Override 1604 public void noteAudioTurnedOnLocked() { 1605 if (!mAudioTurnedOn) { 1606 mAudioTurnedOn = true; 1607 mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); 1608 } 1609 } 1610 1611 @Override 1612 public void noteAudioTurnedOffLocked() { 1613 if (mAudioTurnedOn) { 1614 mAudioTurnedOn = false; 1615 mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); 1616 } 1617 } 1618 1619 @Override 1620 public void noteFullWifiLockReleasedLocked() { 1621 if (mFullWifiLockOut) { 1622 mFullWifiLockOut = false; 1623 mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 1624 } 1625 } 1626 1627 @Override 1628 public void noteScanWifiLockAcquiredLocked() { 1629 if (!mScanWifiLockOut) { 1630 mScanWifiLockOut = true; 1631 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); 1632 } 1633 } 1634 1635 @Override 1636 public void noteScanWifiLockReleasedLocked() { 1637 if (mScanWifiLockOut) { 1638 mScanWifiLockOut = false; 1639 mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); 1640 } 1641 } 1642 1643 @Override 1644 public void noteWifiMulticastEnabledLocked() { 1645 if (!mWifiMulticastEnabled) { 1646 mWifiMulticastEnabled = true; 1647 mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this); 1648 } 1649 } 1650 1651 @Override 1652 public void noteWifiMulticastDisabledLocked() { 1653 if (mWifiMulticastEnabled) { 1654 mWifiMulticastEnabled = false; 1655 mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this); 1656 } 1657 } 1658 1659 @Override 1660 public long getWifiTurnedOnTime(long batteryRealtime, int which) { 1661 return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1662 } 1663 1664 @Override 1665 public long getAudioTurnedOnTime(long batteryRealtime, int which) { 1666 return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1667 } 1668 1669 @Override 1670 public long getVideoTurnedOnTime(long batteryRealtime, int which) { 1671 return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); 1672 } 1673 1674 @Override 1675 public long getFullWifiLockTime(long batteryRealtime, int which) { 1676 return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 1677 } 1678 1679 @Override 1680 public long getScanWifiLockTime(long batteryRealtime, int which) { 1681 return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); 1682 } 1683 1684 @Override 1685 public long getWifiMulticastTime(long batteryRealtime, int which) { 1686 return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime, 1687 which); 1688 } 1689 1690 @Override 1691 public void noteUserActivityLocked(int type) { 1692 if (mUserActivityCounters == null) { 1693 initUserActivityLocked(); 1694 } 1695 if (type < 0) type = 0; 1696 else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1; 1697 mUserActivityCounters[type].stepAtomic(); 1698 } 1699 1700 @Override 1701 public boolean hasUserActivity() { 1702 return mUserActivityCounters != null; 1703 } 1704 1705 @Override 1706 public int getUserActivityCount(int type, int which) { 1707 if (mUserActivityCounters == null) { 1708 return 0; 1709 } 1710 return mUserActivityCounters[type].getCountLocked(which); 1711 } 1712 1713 void initUserActivityLocked() { 1714 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 1715 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1716 mUserActivityCounters[i] = new Counter(mUnpluggables); 1717 } 1718 } 1719 1720 public long computeCurrentTcpBytesSent() { 1721 return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0 1722 ? (TrafficStats.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0); 1723 } 1724 1725 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1726 out.writeInt(mWakelockStats.size()); 1727 for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) { 1728 out.writeString(wakelockEntry.getKey()); 1729 Uid.Wakelock wakelock = wakelockEntry.getValue(); 1730 wakelock.writeToParcelLocked(out, batteryRealtime); 1731 } 1732 1733 out.writeInt(mSensorStats.size()); 1734 for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) { 1735 out.writeInt(sensorEntry.getKey()); 1736 Uid.Sensor sensor = sensorEntry.getValue(); 1737 sensor.writeToParcelLocked(out, batteryRealtime); 1738 } 1739 1740 out.writeInt(mProcessStats.size()); 1741 for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) { 1742 out.writeString(procEntry.getKey()); 1743 Uid.Proc proc = procEntry.getValue(); 1744 proc.writeToParcelLocked(out); 1745 } 1746 1747 out.writeInt(mPackageStats.size()); 1748 for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) { 1749 out.writeString(pkgEntry.getKey()); 1750 Uid.Pkg pkg = pkgEntry.getValue(); 1751 pkg.writeToParcelLocked(out); 1752 } 1753 1754 out.writeLong(mLoadedTcpBytesReceived); 1755 out.writeLong(mLoadedTcpBytesSent); 1756 out.writeLong(computeCurrentTcpBytesReceived()); 1757 out.writeLong(computeCurrentTcpBytesSent()); 1758 out.writeLong(mTcpBytesReceivedAtLastUnplug); 1759 out.writeLong(mTcpBytesSentAtLastUnplug); 1760 mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime); 1761 mFullWifiLockTimer.writeToParcel(out, batteryRealtime); 1762 mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime); 1763 mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime); 1764 mScanWifiLockTimer.writeToParcel(out, batteryRealtime); 1765 mWifiMulticastTimer.writeToParcel(out, batteryRealtime); 1766 if (mUserActivityCounters == null) { 1767 out.writeInt(0); 1768 } else { 1769 out.writeInt(1); 1770 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1771 mUserActivityCounters[i].writeToParcel(out); 1772 } 1773 } 1774 } 1775 1776 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1777 int numWakelocks = in.readInt(); 1778 mWakelockStats.clear(); 1779 for (int j = 0; j < numWakelocks; j++) { 1780 String wakelockName = in.readString(); 1781 Uid.Wakelock wakelock = new Wakelock(); 1782 wakelock.readFromParcelLocked(unpluggables, in); 1783 if (mWakelockStats.size() < MAX_WAKELOCKS_PER_UID) { 1784 // We will just drop some random set of wakelocks if 1785 // the previous run of the system was an older version 1786 // that didn't impose a limit. 1787 mWakelockStats.put(wakelockName, wakelock); 1788 } 1789 } 1790 1791 int numSensors = in.readInt(); 1792 mSensorStats.clear(); 1793 for (int k = 0; k < numSensors; k++) { 1794 int sensorNumber = in.readInt(); 1795 Uid.Sensor sensor = new Sensor(sensorNumber); 1796 sensor.readFromParcelLocked(mUnpluggables, in); 1797 mSensorStats.put(sensorNumber, sensor); 1798 } 1799 1800 int numProcs = in.readInt(); 1801 mProcessStats.clear(); 1802 for (int k = 0; k < numProcs; k++) { 1803 String processName = in.readString(); 1804 Uid.Proc proc = new Proc(); 1805 proc.readFromParcelLocked(in); 1806 mProcessStats.put(processName, proc); 1807 } 1808 1809 int numPkgs = in.readInt(); 1810 mPackageStats.clear(); 1811 for (int l = 0; l < numPkgs; l++) { 1812 String packageName = in.readString(); 1813 Uid.Pkg pkg = new Pkg(); 1814 pkg.readFromParcelLocked(in); 1815 mPackageStats.put(packageName, pkg); 1816 } 1817 1818 mLoadedTcpBytesReceived = in.readLong(); 1819 mLoadedTcpBytesSent = in.readLong(); 1820 mCurrentTcpBytesReceived = in.readLong(); 1821 mCurrentTcpBytesSent = in.readLong(); 1822 mTcpBytesReceivedAtLastUnplug = in.readLong(); 1823 mTcpBytesSentAtLastUnplug = in.readLong(); 1824 mWifiTurnedOn = false; 1825 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables, in); 1826 mFullWifiLockOut = false; 1827 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in); 1828 mAudioTurnedOn = false; 1829 mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables, in); 1830 mVideoTurnedOn = false; 1831 mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables, in); 1832 mScanWifiLockOut = false; 1833 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in); 1834 mWifiMulticastEnabled = false; 1835 mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, 1836 null, mUnpluggables, in); 1837 if (in.readInt() == 0) { 1838 mUserActivityCounters = null; 1839 } else { 1840 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; 1841 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { 1842 mUserActivityCounters[i] = new Counter(mUnpluggables, in); 1843 } 1844 } 1845 } 1846 1847 /** 1848 * The statistics associated with a particular wake lock. 1849 */ 1850 public final class Wakelock extends BatteryStats.Uid.Wakelock { 1851 /** 1852 * How long (in ms) this uid has been keeping the device partially awake. 1853 */ 1854 StopwatchTimer mTimerPartial; 1855 1856 /** 1857 * How long (in ms) this uid has been keeping the device fully awake. 1858 */ 1859 StopwatchTimer mTimerFull; 1860 1861 /** 1862 * How long (in ms) this uid has had a window keeping the device awake. 1863 */ 1864 StopwatchTimer mTimerWindow; 1865 1866 /** 1867 * Reads a possibly null Timer from a Parcel. The timer is associated with the 1868 * proper timer pool from the given BatteryStatsImpl object. 1869 * 1870 * @param in the Parcel to be read from. 1871 * return a new Timer, or null. 1872 */ 1873 private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, 1874 ArrayList<Unpluggable> unpluggables, Parcel in) { 1875 if (in.readInt() == 0) { 1876 return null; 1877 } 1878 1879 return new StopwatchTimer(type, pool, unpluggables, in); 1880 } 1881 1882 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1883 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL, 1884 mPartialTimers, unpluggables, in); 1885 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, 1886 mFullTimers, unpluggables, in); 1887 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, 1888 mWindowTimers, unpluggables, in); 1889 } 1890 1891 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1892 Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime); 1893 Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime); 1894 Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime); 1895 } 1896 1897 @Override 1898 public Timer getWakeTime(int type) { 1899 switch (type) { 1900 case WAKE_TYPE_FULL: return mTimerFull; 1901 case WAKE_TYPE_PARTIAL: return mTimerPartial; 1902 case WAKE_TYPE_WINDOW: return mTimerWindow; 1903 default: throw new IllegalArgumentException("type = " + type); 1904 } 1905 } 1906 } 1907 1908 public final class Sensor extends BatteryStats.Uid.Sensor { 1909 final int mHandle; 1910 StopwatchTimer mTimer; 1911 1912 public Sensor(int handle) { 1913 mHandle = handle; 1914 } 1915 1916 private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables, 1917 Parcel in) { 1918 if (in.readInt() == 0) { 1919 return null; 1920 } 1921 1922 ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle); 1923 if (pool == null) { 1924 pool = new ArrayList<StopwatchTimer>(); 1925 mSensorTimers.put(mHandle, pool); 1926 } 1927 return new StopwatchTimer(0, pool, unpluggables, in); 1928 } 1929 1930 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { 1931 mTimer = readTimerFromParcel(unpluggables, in); 1932 } 1933 1934 void writeToParcelLocked(Parcel out, long batteryRealtime) { 1935 Timer.writeTimerToParcel(out, mTimer, batteryRealtime); 1936 } 1937 1938 @Override 1939 public Timer getSensorTime() { 1940 return mTimer; 1941 } 1942 1943 @Override 1944 public int getHandle() { 1945 return mHandle; 1946 } 1947 } 1948 1949 /** 1950 * The statistics associated with a particular process. 1951 */ 1952 public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable { 1953 /** 1954 * Total time (in 1/100 sec) spent executing in user code. 1955 */ 1956 long mUserTime; 1957 1958 /** 1959 * Total time (in 1/100 sec) spent executing in kernel code. 1960 */ 1961 long mSystemTime; 1962 1963 /** 1964 * Number of times the process has been started. 1965 */ 1966 int mStarts; 1967 1968 /** 1969 * Amount of time the process was running in the foreground. 1970 */ 1971 long mForegroundTime; 1972 1973 /** 1974 * The amount of user time loaded from a previous save. 1975 */ 1976 long mLoadedUserTime; 1977 1978 /** 1979 * The amount of system time loaded from a previous save. 1980 */ 1981 long mLoadedSystemTime; 1982 1983 /** 1984 * The number of times the process has started from a previous save. 1985 */ 1986 int mLoadedStarts; 1987 1988 /** 1989 * The amount of foreground time loaded from a previous save. 1990 */ 1991 long mLoadedForegroundTime; 1992 1993 /** 1994 * The amount of user time loaded from the previous run. 1995 */ 1996 long mLastUserTime; 1997 1998 /** 1999 * The amount of system time loaded from the previous run. 2000 */ 2001 long mLastSystemTime; 2002 2003 /** 2004 * The number of times the process has started from the previous run. 2005 */ 2006 int mLastStarts; 2007 2008 /** 2009 * The amount of foreground time loaded from the previous run 2010 */ 2011 long mLastForegroundTime; 2012 2013 /** 2014 * The amount of user time when last unplugged. 2015 */ 2016 long mUnpluggedUserTime; 2017 2018 /** 2019 * The amount of system time when last unplugged. 2020 */ 2021 long mUnpluggedSystemTime; 2022 2023 /** 2024 * The number of times the process has started before unplugged. 2025 */ 2026 int mUnpluggedStarts; 2027 2028 /** 2029 * The amount of foreground time since unplugged. 2030 */ 2031 long mUnpluggedForegroundTime; 2032 2033 SamplingCounter[] mSpeedBins; 2034 2035 Proc() { 2036 mUnpluggables.add(this); 2037 mSpeedBins = new SamplingCounter[getCpuSpeedSteps()]; 2038 for (int i = 0; i < mSpeedBins.length; i++) { 2039 mSpeedBins[i] = new SamplingCounter(mUnpluggables); 2040 } 2041 } 2042 2043 public void unplug(long batteryUptime, long batteryRealtime) { 2044 mUnpluggedUserTime = mUserTime; 2045 mUnpluggedSystemTime = mSystemTime; 2046 mUnpluggedStarts = mStarts; 2047 mUnpluggedForegroundTime = mForegroundTime; 2048 } 2049 2050 public void plug(long batteryUptime, long batteryRealtime) { 2051 } 2052 2053 void writeToParcelLocked(Parcel out) { 2054 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 2055 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 2056 2057 out.writeLong(mUserTime); 2058 out.writeLong(mSystemTime); 2059 out.writeLong(mForegroundTime); 2060 out.writeInt(mStarts); 2061 out.writeLong(mLoadedUserTime); 2062 out.writeLong(mLoadedSystemTime); 2063 out.writeLong(mLoadedForegroundTime); 2064 out.writeInt(mLoadedStarts); 2065 out.writeLong(mLastUserTime); 2066 out.writeLong(mLastSystemTime); 2067 out.writeLong(mLastForegroundTime); 2068 out.writeInt(mLastStarts); 2069 out.writeLong(mUnpluggedUserTime); 2070 out.writeLong(mUnpluggedSystemTime); 2071 out.writeLong(mUnpluggedForegroundTime); 2072 out.writeInt(mUnpluggedStarts); 2073 2074 out.writeInt(mSpeedBins.length); 2075 for (int i = 0; i < mSpeedBins.length; i++) { 2076 mSpeedBins[i].writeToParcel(out); 2077 } 2078 } 2079 2080 void readFromParcelLocked(Parcel in) { 2081 mUserTime = in.readLong(); 2082 mSystemTime = in.readLong(); 2083 mForegroundTime = in.readLong(); 2084 mStarts = in.readInt(); 2085 mLoadedUserTime = in.readLong(); 2086 mLoadedSystemTime = in.readLong(); 2087 mLoadedForegroundTime = in.readLong(); 2088 mLoadedStarts = in.readInt(); 2089 mLastUserTime = in.readLong(); 2090 mLastSystemTime = in.readLong(); 2091 mLastForegroundTime = in.readLong(); 2092 mLastStarts = in.readInt(); 2093 mUnpluggedUserTime = in.readLong(); 2094 mUnpluggedSystemTime = in.readLong(); 2095 mUnpluggedForegroundTime = in.readLong(); 2096 mUnpluggedStarts = in.readInt(); 2097 2098 int bins = in.readInt(); 2099 mSpeedBins = new SamplingCounter[bins]; 2100 for (int i = 0; i < bins; i++) { 2101 mSpeedBins[i] = new SamplingCounter(mUnpluggables, in); 2102 } 2103 } 2104 2105 public BatteryStatsImpl getBatteryStats() { 2106 return BatteryStatsImpl.this; 2107 } 2108 2109 public void addCpuTimeLocked(int utime, int stime) { 2110 mUserTime += utime; 2111 mSystemTime += stime; 2112 } 2113 2114 public void addForegroundTimeLocked(long ttime) { 2115 mForegroundTime += ttime; 2116 } 2117 2118 public void incStartsLocked() { 2119 mStarts++; 2120 } 2121 2122 @Override 2123 public long getUserTime(int which) { 2124 long val; 2125 if (which == STATS_LAST) { 2126 val = mLastUserTime; 2127 } else { 2128 val = mUserTime; 2129 if (which == STATS_CURRENT) { 2130 val -= mLoadedUserTime; 2131 } else if (which == STATS_UNPLUGGED) { 2132 val -= mUnpluggedUserTime; 2133 } 2134 } 2135 return val; 2136 } 2137 2138 @Override 2139 public long getSystemTime(int which) { 2140 long val; 2141 if (which == STATS_LAST) { 2142 val = mLastSystemTime; 2143 } else { 2144 val = mSystemTime; 2145 if (which == STATS_CURRENT) { 2146 val -= mLoadedSystemTime; 2147 } else if (which == STATS_UNPLUGGED) { 2148 val -= mUnpluggedSystemTime; 2149 } 2150 } 2151 return val; 2152 } 2153 2154 @Override 2155 public long getForegroundTime(int which) { 2156 long val; 2157 if (which == STATS_LAST) { 2158 val = mLastForegroundTime; 2159 } else { 2160 val = mForegroundTime; 2161 if (which == STATS_CURRENT) { 2162 val -= mLoadedForegroundTime; 2163 } else if (which == STATS_UNPLUGGED) { 2164 val -= mUnpluggedForegroundTime; 2165 } 2166 } 2167 return val; 2168 } 2169 2170 @Override 2171 public int getStarts(int which) { 2172 int val; 2173 if (which == STATS_LAST) { 2174 val = mLastStarts; 2175 } else { 2176 val = mStarts; 2177 if (which == STATS_CURRENT) { 2178 val -= mLoadedStarts; 2179 } else if (which == STATS_UNPLUGGED) { 2180 val -= mUnpluggedStarts; 2181 } 2182 } 2183 return val; 2184 } 2185 2186 /* Called by ActivityManagerService when CPU times are updated. */ 2187 public void addSpeedStepTimes(long[] values) { 2188 for (int i = 0; i < mSpeedBins.length && i < values.length; i++) { 2189 mSpeedBins[i].addCountAtomic(values[i]); 2190 } 2191 } 2192 2193 @Override 2194 public long getTimeAtCpuSpeedStep(int speedStep, int which) { 2195 if (speedStep < mSpeedBins.length) { 2196 return mSpeedBins[speedStep].getCountLocked(which); 2197 } else { 2198 return 0; 2199 } 2200 } 2201 } 2202 2203 /** 2204 * The statistics associated with a particular package. 2205 */ 2206 public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable { 2207 /** 2208 * Number of times this package has done something that could wake up the 2209 * device from sleep. 2210 */ 2211 int mWakeups; 2212 2213 /** 2214 * Number of things that could wake up the device loaded from a 2215 * previous save. 2216 */ 2217 int mLoadedWakeups; 2218 2219 /** 2220 * Number of things that could wake up the device as of the 2221 * last run. 2222 */ 2223 int mLastWakeups; 2224 2225 /** 2226 * Number of things that could wake up the device as of the 2227 * last run. 2228 */ 2229 int mUnpluggedWakeups; 2230 2231 /** 2232 * The statics we have collected for this package's services. 2233 */ 2234 final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>(); 2235 2236 Pkg() { 2237 mUnpluggables.add(this); 2238 } 2239 2240 public void unplug(long batteryUptime, long batteryRealtime) { 2241 mUnpluggedWakeups = mWakeups; 2242 } 2243 2244 public void plug(long batteryUptime, long batteryRealtime) { 2245 } 2246 2247 void readFromParcelLocked(Parcel in) { 2248 mWakeups = in.readInt(); 2249 mLoadedWakeups = in.readInt(); 2250 mLastWakeups = in.readInt(); 2251 mUnpluggedWakeups = in.readInt(); 2252 2253 int numServs = in.readInt(); 2254 mServiceStats.clear(); 2255 for (int m = 0; m < numServs; m++) { 2256 String serviceName = in.readString(); 2257 Uid.Pkg.Serv serv = new Serv(); 2258 mServiceStats.put(serviceName, serv); 2259 2260 serv.readFromParcelLocked(in); 2261 } 2262 } 2263 2264 void writeToParcelLocked(Parcel out) { 2265 out.writeInt(mWakeups); 2266 out.writeInt(mLoadedWakeups); 2267 out.writeInt(mLastWakeups); 2268 out.writeInt(mUnpluggedWakeups); 2269 2270 out.writeInt(mServiceStats.size()); 2271 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) { 2272 out.writeString(servEntry.getKey()); 2273 Uid.Pkg.Serv serv = servEntry.getValue(); 2274 2275 serv.writeToParcelLocked(out); 2276 } 2277 } 2278 2279 @Override 2280 public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() { 2281 return mServiceStats; 2282 } 2283 2284 @Override 2285 public int getWakeups(int which) { 2286 int val; 2287 if (which == STATS_LAST) { 2288 val = mLastWakeups; 2289 } else { 2290 val = mWakeups; 2291 if (which == STATS_CURRENT) { 2292 val -= mLoadedWakeups; 2293 } else if (which == STATS_UNPLUGGED) { 2294 val -= mUnpluggedWakeups; 2295 } 2296 } 2297 2298 return val; 2299 } 2300 2301 /** 2302 * The statistics associated with a particular service. 2303 */ 2304 public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable { 2305 /** 2306 * Total time (ms in battery uptime) the service has been left started. 2307 */ 2308 long mStartTime; 2309 2310 /** 2311 * If service has been started and not yet stopped, this is 2312 * when it was started. 2313 */ 2314 long mRunningSince; 2315 2316 /** 2317 * True if we are currently running. 2318 */ 2319 boolean mRunning; 2320 2321 /** 2322 * Total number of times startService() has been called. 2323 */ 2324 int mStarts; 2325 2326 /** 2327 * Total time (ms in battery uptime) the service has been left launched. 2328 */ 2329 long mLaunchedTime; 2330 2331 /** 2332 * If service has been launched and not yet exited, this is 2333 * when it was launched (ms in battery uptime). 2334 */ 2335 long mLaunchedSince; 2336 2337 /** 2338 * True if we are currently launched. 2339 */ 2340 boolean mLaunched; 2341 2342 /** 2343 * Total number times the service has been launched. 2344 */ 2345 int mLaunches; 2346 2347 /** 2348 * The amount of time spent started loaded from a previous save 2349 * (ms in battery uptime). 2350 */ 2351 long mLoadedStartTime; 2352 2353 /** 2354 * The number of starts loaded from a previous save. 2355 */ 2356 int mLoadedStarts; 2357 2358 /** 2359 * The number of launches loaded from a previous save. 2360 */ 2361 int mLoadedLaunches; 2362 2363 /** 2364 * The amount of time spent started as of the last run (ms 2365 * in battery uptime). 2366 */ 2367 long mLastStartTime; 2368 2369 /** 2370 * The number of starts as of the last run. 2371 */ 2372 int mLastStarts; 2373 2374 /** 2375 * The number of launches as of the last run. 2376 */ 2377 int mLastLaunches; 2378 2379 /** 2380 * The amount of time spent started when last unplugged (ms 2381 * in battery uptime). 2382 */ 2383 long mUnpluggedStartTime; 2384 2385 /** 2386 * The number of starts when last unplugged. 2387 */ 2388 int mUnpluggedStarts; 2389 2390 /** 2391 * The number of launches when last unplugged. 2392 */ 2393 int mUnpluggedLaunches; 2394 2395 Serv() { 2396 mUnpluggables.add(this); 2397 } 2398 2399 public void unplug(long batteryUptime, long batteryRealtime) { 2400 mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime); 2401 mUnpluggedStarts = mStarts; 2402 mUnpluggedLaunches = mLaunches; 2403 } 2404 2405 public void plug(long batteryUptime, long batteryRealtime) { 2406 } 2407 2408 void readFromParcelLocked(Parcel in) { 2409 mStartTime = in.readLong(); 2410 mRunningSince = in.readLong(); 2411 mRunning = in.readInt() != 0; 2412 mStarts = in.readInt(); 2413 mLaunchedTime = in.readLong(); 2414 mLaunchedSince = in.readLong(); 2415 mLaunched = in.readInt() != 0; 2416 mLaunches = in.readInt(); 2417 mLoadedStartTime = in.readLong(); 2418 mLoadedStarts = in.readInt(); 2419 mLoadedLaunches = in.readInt(); 2420 mLastStartTime = in.readLong(); 2421 mLastStarts = in.readInt(); 2422 mLastLaunches = in.readInt(); 2423 mUnpluggedStartTime = in.readLong(); 2424 mUnpluggedStarts = in.readInt(); 2425 mUnpluggedLaunches = in.readInt(); 2426 } 2427 2428 void writeToParcelLocked(Parcel out) { 2429 out.writeLong(mStartTime); 2430 out.writeLong(mRunningSince); 2431 out.writeInt(mRunning ? 1 : 0); 2432 out.writeInt(mStarts); 2433 out.writeLong(mLaunchedTime); 2434 out.writeLong(mLaunchedSince); 2435 out.writeInt(mLaunched ? 1 : 0); 2436 out.writeInt(mLaunches); 2437 out.writeLong(mLoadedStartTime); 2438 out.writeInt(mLoadedStarts); 2439 out.writeInt(mLoadedLaunches); 2440 out.writeLong(mLastStartTime); 2441 out.writeInt(mLastStarts); 2442 out.writeInt(mLastLaunches); 2443 out.writeLong(mUnpluggedStartTime); 2444 out.writeInt(mUnpluggedStarts); 2445 out.writeInt(mUnpluggedLaunches); 2446 } 2447 2448 long getLaunchTimeToNowLocked(long batteryUptime) { 2449 if (!mLaunched) return mLaunchedTime; 2450 return mLaunchedTime + batteryUptime - mLaunchedSince; 2451 } 2452 2453 long getStartTimeToNowLocked(long batteryUptime) { 2454 if (!mRunning) return mStartTime; 2455 return mStartTime + batteryUptime - mRunningSince; 2456 } 2457 2458 public void startLaunchedLocked() { 2459 if (!mLaunched) { 2460 mLaunches++; 2461 mLaunchedSince = getBatteryUptimeLocked(); 2462 mLaunched = true; 2463 } 2464 } 2465 2466 public void stopLaunchedLocked() { 2467 if (mLaunched) { 2468 long time = getBatteryUptimeLocked() - mLaunchedSince; 2469 if (time > 0) { 2470 mLaunchedTime += time; 2471 } else { 2472 mLaunches--; 2473 } 2474 mLaunched = false; 2475 } 2476 } 2477 2478 public void startRunningLocked() { 2479 if (!mRunning) { 2480 mStarts++; 2481 mRunningSince = getBatteryUptimeLocked(); 2482 mRunning = true; 2483 } 2484 } 2485 2486 public void stopRunningLocked() { 2487 if (mRunning) { 2488 long time = getBatteryUptimeLocked() - mRunningSince; 2489 if (time > 0) { 2490 mStartTime += time; 2491 } else { 2492 mStarts--; 2493 } 2494 mRunning = false; 2495 } 2496 } 2497 2498 public BatteryStatsImpl getBatteryStats() { 2499 return BatteryStatsImpl.this; 2500 } 2501 2502 @Override 2503 public int getLaunches(int which) { 2504 int val; 2505 2506 if (which == STATS_LAST) { 2507 val = mLastLaunches; 2508 } else { 2509 val = mLaunches; 2510 if (which == STATS_CURRENT) { 2511 val -= mLoadedLaunches; 2512 } else if (which == STATS_UNPLUGGED) { 2513 val -= mUnpluggedLaunches; 2514 } 2515 } 2516 2517 return val; 2518 } 2519 2520 @Override 2521 public long getStartTime(long now, int which) { 2522 long val; 2523 if (which == STATS_LAST) { 2524 val = mLastStartTime; 2525 } else { 2526 val = getStartTimeToNowLocked(now); 2527 if (which == STATS_CURRENT) { 2528 val -= mLoadedStartTime; 2529 } else if (which == STATS_UNPLUGGED) { 2530 val -= mUnpluggedStartTime; 2531 } 2532 } 2533 2534 return val; 2535 } 2536 2537 @Override 2538 public int getStarts(int which) { 2539 int val; 2540 if (which == STATS_LAST) { 2541 val = mLastStarts; 2542 } else { 2543 val = mStarts; 2544 if (which == STATS_CURRENT) { 2545 val -= mLoadedStarts; 2546 } else if (which == STATS_UNPLUGGED) { 2547 val -= mUnpluggedStarts; 2548 } 2549 } 2550 2551 return val; 2552 } 2553 } 2554 2555 public BatteryStatsImpl getBatteryStats() { 2556 return BatteryStatsImpl.this; 2557 } 2558 2559 public void incWakeupsLocked() { 2560 mWakeups++; 2561 } 2562 2563 final Serv newServiceStatsLocked() { 2564 return new Serv(); 2565 } 2566 } 2567 2568 /** 2569 * Retrieve the statistics object for a particular process, creating 2570 * if needed. 2571 */ 2572 public Proc getProcessStatsLocked(String name) { 2573 Proc ps = mProcessStats.get(name); 2574 if (ps == null) { 2575 ps = new Proc(); 2576 mProcessStats.put(name, ps); 2577 } 2578 2579 return ps; 2580 } 2581 2582 /** 2583 * Retrieve the statistics object for a particular service, creating 2584 * if needed. 2585 */ 2586 public Pkg getPackageStatsLocked(String name) { 2587 Pkg ps = mPackageStats.get(name); 2588 if (ps == null) { 2589 ps = new Pkg(); 2590 mPackageStats.put(name, ps); 2591 } 2592 2593 return ps; 2594 } 2595 2596 /** 2597 * Retrieve the statistics object for a particular service, creating 2598 * if needed. 2599 */ 2600 public Pkg.Serv getServiceStatsLocked(String pkg, String serv) { 2601 Pkg ps = getPackageStatsLocked(pkg); 2602 Pkg.Serv ss = ps.mServiceStats.get(serv); 2603 if (ss == null) { 2604 ss = ps.newServiceStatsLocked(); 2605 ps.mServiceStats.put(serv, ss); 2606 } 2607 2608 return ss; 2609 } 2610 2611 public StopwatchTimer getWakeTimerLocked(String name, int type) { 2612 Wakelock wl = mWakelockStats.get(name); 2613 if (wl == null) { 2614 if (mWakelockStats.size() > MAX_WAKELOCKS_PER_UID) { 2615 name = BATCHED_WAKELOCK_NAME; 2616 wl = mWakelockStats.get(name); 2617 } 2618 if (wl == null) { 2619 wl = new Wakelock(); 2620 mWakelockStats.put(name, wl); 2621 } 2622 } 2623 StopwatchTimer t = null; 2624 switch (type) { 2625 case WAKE_TYPE_PARTIAL: 2626 t = wl.mTimerPartial; 2627 if (t == null) { 2628 t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables); 2629 wl.mTimerPartial = t; 2630 } 2631 return t; 2632 case WAKE_TYPE_FULL: 2633 t = wl.mTimerFull; 2634 if (t == null) { 2635 t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables); 2636 wl.mTimerFull = t; 2637 } 2638 return t; 2639 case WAKE_TYPE_WINDOW: 2640 t = wl.mTimerWindow; 2641 if (t == null) { 2642 t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables); 2643 wl.mTimerWindow = t; 2644 } 2645 return t; 2646 default: 2647 throw new IllegalArgumentException("type=" + type); 2648 } 2649 } 2650 2651 public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) { 2652 Sensor se = mSensorStats.get(sensor); 2653 if (se == null) { 2654 if (!create) { 2655 return null; 2656 } 2657 se = new Sensor(sensor); 2658 mSensorStats.put(sensor, se); 2659 } 2660 StopwatchTimer t = se.mTimer; 2661 if (t != null) { 2662 return t; 2663 } 2664 ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor); 2665 if (timers == null) { 2666 timers = new ArrayList<StopwatchTimer>(); 2667 mSensorTimers.put(sensor, timers); 2668 } 2669 t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables); 2670 se.mTimer = t; 2671 return t; 2672 } 2673 2674 public void noteStartWakeLocked(String name, int type) { 2675 StopwatchTimer t = getWakeTimerLocked(name, type); 2676 if (t != null) { 2677 t.startRunningLocked(BatteryStatsImpl.this); 2678 } 2679 } 2680 2681 public void noteStopWakeLocked(String name, int type) { 2682 StopwatchTimer t = getWakeTimerLocked(name, type); 2683 if (t != null) { 2684 t.stopRunningLocked(BatteryStatsImpl.this); 2685 } 2686 } 2687 2688 public void noteStartSensor(int sensor) { 2689 StopwatchTimer t = getSensorTimerLocked(sensor, true); 2690 if (t != null) { 2691 t.startRunningLocked(BatteryStatsImpl.this); 2692 } 2693 } 2694 2695 public void noteStopSensor(int sensor) { 2696 // Don't create a timer if one doesn't already exist 2697 StopwatchTimer t = getSensorTimerLocked(sensor, false); 2698 if (t != null) { 2699 t.stopRunningLocked(BatteryStatsImpl.this); 2700 } 2701 } 2702 2703 public void noteStartGps() { 2704 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true); 2705 if (t != null) { 2706 t.startRunningLocked(BatteryStatsImpl.this); 2707 } 2708 } 2709 2710 public void noteStopGps() { 2711 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false); 2712 if (t != null) { 2713 t.stopRunningLocked(BatteryStatsImpl.this); 2714 } 2715 } 2716 2717 public BatteryStatsImpl getBatteryStats() { 2718 return BatteryStatsImpl.this; 2719 } 2720 } 2721 2722 public BatteryStatsImpl(String filename) { 2723 mFile = new JournaledFile(new File(filename), new File(filename + ".tmp")); 2724 mStartCount++; 2725 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables); 2726 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 2727 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables); 2728 } 2729 mInputEventCounter = new Counter(mUnpluggables); 2730 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables); 2731 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 2732 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables); 2733 } 2734 mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables); 2735 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 2736 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables); 2737 } 2738 mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables); 2739 mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables); 2740 mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables); 2741 mAudioOnTimer = new StopwatchTimer(-6, null, mUnpluggables); 2742 mOnBattery = mOnBatteryInternal = false; 2743 mTrackBatteryPastUptime = 0; 2744 mTrackBatteryPastRealtime = 0; 2745 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; 2746 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; 2747 mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); 2748 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); 2749 mDischargeStartLevel = 0; 2750 mDischargeCurrentLevel = 0; 2751 } 2752 2753 public BatteryStatsImpl(Parcel p) { 2754 mFile = null; 2755 readFromParcel(p); 2756 } 2757 2758 public void setNumSpeedSteps(int steps) { 2759 if (sNumSpeedSteps == 0) sNumSpeedSteps = steps; 2760 } 2761 2762 public void setRadioScanningTimeout(long timeout) { 2763 if (mPhoneSignalScanningTimer != null) { 2764 mPhoneSignalScanningTimer.setTimeout(timeout); 2765 } 2766 } 2767 2768 @Override 2769 public int getStartCount() { 2770 return mStartCount; 2771 } 2772 2773 public boolean isOnBattery() { 2774 return mOnBattery; 2775 } 2776 2777 public void setOnBattery(boolean onBattery, int level) { 2778 synchronized(this) { 2779 updateKernelWakelocksLocked(); 2780 if (mOnBattery != onBattery) { 2781 mOnBattery = mOnBatteryInternal = onBattery; 2782 2783 long uptime = SystemClock.uptimeMillis() * 1000; 2784 long mSecRealtime = SystemClock.elapsedRealtime(); 2785 long realtime = mSecRealtime * 1000; 2786 if (onBattery) { 2787 mTrackBatteryUptimeStart = uptime; 2788 mTrackBatteryRealtimeStart = realtime; 2789 mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); 2790 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); 2791 mDischargeCurrentLevel = mDischargeStartLevel = level; 2792 doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); 2793 } else { 2794 mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; 2795 mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; 2796 mDischargeCurrentLevel = level; 2797 doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); 2798 } 2799 if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) { 2800 if (mFile != null) { 2801 writeLocked(); 2802 } 2803 } 2804 } 2805 } 2806 } 2807 2808 public void recordCurrentLevel(int level) { 2809 mDischargeCurrentLevel = level; 2810 } 2811 2812 public void updateKernelWakelocksLocked() { 2813 Map<String, KernelWakelockStats> m = readKernelWakelockStats(); 2814 2815 if (m == null) { 2816 // Not crashing might make board bringup easier. 2817 Slog.w(TAG, "Couldn't get kernel wake lock stats"); 2818 return; 2819 } 2820 2821 for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) { 2822 String name = ent.getKey(); 2823 KernelWakelockStats kws = ent.getValue(); 2824 2825 SamplingTimer kwlt = mKernelWakelockStats.get(name); 2826 if (kwlt == null) { 2827 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 2828 true /* track reported values */); 2829 mKernelWakelockStats.put(name, kwlt); 2830 } 2831 kwlt.updateCurrentReportedCount(kws.mCount); 2832 kwlt.updateCurrentReportedTotalTime(kws.mTotalTime); 2833 kwlt.setUpdateVersion(sKernelWakelockUpdateVersion); 2834 } 2835 2836 if (m.size() != mKernelWakelockStats.size()) { 2837 // Set timers to stale if they didn't appear in /proc/wakelocks this time. 2838 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 2839 SamplingTimer st = ent.getValue(); 2840 if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) { 2841 st.setStale(); 2842 } 2843 } 2844 } 2845 } 2846 2847 public long getAwakeTimeBattery() { 2848 return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT); 2849 } 2850 2851 public long getAwakeTimePlugged() { 2852 return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery(); 2853 } 2854 2855 @Override 2856 public long computeUptime(long curTime, int which) { 2857 switch (which) { 2858 case STATS_TOTAL: return mUptime + (curTime-mUptimeStart); 2859 case STATS_LAST: return mLastUptime; 2860 case STATS_CURRENT: return (curTime-mUptimeStart); 2861 case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart); 2862 } 2863 return 0; 2864 } 2865 2866 @Override 2867 public long computeRealtime(long curTime, int which) { 2868 switch (which) { 2869 case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart); 2870 case STATS_LAST: return mLastRealtime; 2871 case STATS_CURRENT: return (curTime-mRealtimeStart); 2872 case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart); 2873 } 2874 return 0; 2875 } 2876 2877 @Override 2878 public long computeBatteryUptime(long curTime, int which) { 2879 switch (which) { 2880 case STATS_TOTAL: 2881 return mBatteryUptime + getBatteryUptime(curTime); 2882 case STATS_LAST: 2883 return mBatteryLastUptime; 2884 case STATS_CURRENT: 2885 return getBatteryUptime(curTime); 2886 case STATS_UNPLUGGED: 2887 return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime; 2888 } 2889 return 0; 2890 } 2891 2892 @Override 2893 public long computeBatteryRealtime(long curTime, int which) { 2894 switch (which) { 2895 case STATS_TOTAL: 2896 return mBatteryRealtime + getBatteryRealtimeLocked(curTime); 2897 case STATS_LAST: 2898 return mBatteryLastRealtime; 2899 case STATS_CURRENT: 2900 return getBatteryRealtimeLocked(curTime); 2901 case STATS_UNPLUGGED: 2902 return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime; 2903 } 2904 return 0; 2905 } 2906 2907 long getBatteryUptimeLocked(long curTime) { 2908 long time = mTrackBatteryPastUptime; 2909 if (mOnBatteryInternal) { 2910 time += curTime - mTrackBatteryUptimeStart; 2911 } 2912 return time; 2913 } 2914 2915 long getBatteryUptimeLocked() { 2916 return getBatteryUptime(SystemClock.uptimeMillis() * 1000); 2917 } 2918 2919 @Override 2920 public long getBatteryUptime(long curTime) { 2921 return getBatteryUptimeLocked(curTime); 2922 } 2923 2924 long getBatteryRealtimeLocked(long curTime) { 2925 long time = mTrackBatteryPastRealtime; 2926 if (mOnBatteryInternal) { 2927 time += curTime - mTrackBatteryRealtimeStart; 2928 } 2929 return time; 2930 } 2931 2932 @Override 2933 public long getBatteryRealtime(long curTime) { 2934 return getBatteryRealtimeLocked(curTime); 2935 } 2936 2937 private long getTcpBytes(long current, long[] dataBytes, int which) { 2938 if (which == STATS_LAST) { 2939 return dataBytes[STATS_LAST]; 2940 } else { 2941 if (which == STATS_UNPLUGGED) { 2942 if (dataBytes[STATS_UNPLUGGED] < 0) { 2943 return dataBytes[STATS_LAST]; 2944 } else { 2945 return current - dataBytes[STATS_UNPLUGGED]; 2946 } 2947 } else if (which == STATS_TOTAL) { 2948 return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_TOTAL]; 2949 } 2950 return current - dataBytes[STATS_CURRENT]; 2951 } 2952 } 2953 2954 /** Only STATS_UNPLUGGED works properly */ 2955 public long getMobileTcpBytesSent(int which) { 2956 return getTcpBytes(TrafficStats.getMobileTxBytes(), mMobileDataTx, which); 2957 } 2958 2959 /** Only STATS_UNPLUGGED works properly */ 2960 public long getMobileTcpBytesReceived(int which) { 2961 return getTcpBytes(TrafficStats.getMobileRxBytes(), mMobileDataRx, which); 2962 } 2963 2964 /** Only STATS_UNPLUGGED works properly */ 2965 public long getTotalTcpBytesSent(int which) { 2966 return getTcpBytes(TrafficStats.getTotalTxBytes(), mTotalDataTx, which); 2967 } 2968 2969 /** Only STATS_UNPLUGGED works properly */ 2970 public long getTotalTcpBytesReceived(int which) { 2971 return getTcpBytes(TrafficStats.getTotalRxBytes(), mTotalDataRx, which); 2972 } 2973 2974 @Override 2975 public int getDischargeStartLevel() { 2976 synchronized(this) { 2977 return getDischargeStartLevelLocked(); 2978 } 2979 } 2980 2981 public int getDischargeStartLevelLocked() { 2982 return mDischargeStartLevel; 2983 } 2984 2985 @Override 2986 public int getDischargeCurrentLevel() { 2987 synchronized(this) { 2988 return getDischargeCurrentLevelLocked(); 2989 } 2990 } 2991 2992 public int getDischargeCurrentLevelLocked() { 2993 return mDischargeCurrentLevel; 2994 } 2995 2996 @Override 2997 public int getCpuSpeedSteps() { 2998 return sNumSpeedSteps; 2999 } 3000 3001 /** 3002 * Retrieve the statistics object for a particular uid, creating if needed. 3003 */ 3004 public Uid getUidStatsLocked(int uid) { 3005 Uid u = mUidStats.get(uid); 3006 if (u == null) { 3007 u = new Uid(uid); 3008 mUidStats.put(uid, u); 3009 } 3010 return u; 3011 } 3012 3013 /** 3014 * Remove the statistics object for a particular uid. 3015 */ 3016 public void removeUidStatsLocked(int uid) { 3017 mUidStats.remove(uid); 3018 } 3019 3020 /** 3021 * Retrieve the statistics object for a particular process, creating 3022 * if needed. 3023 */ 3024 public Uid.Proc getProcessStatsLocked(int uid, String name) { 3025 Uid u = getUidStatsLocked(uid); 3026 return u.getProcessStatsLocked(name); 3027 } 3028 3029 /** 3030 * Retrieve the statistics object for a particular process, given 3031 * the name of the process. 3032 * @param name process name 3033 * @return the statistics object for the process 3034 */ 3035 public Uid.Proc getProcessStatsLocked(String name, int pid) { 3036 int uid; 3037 if (mUidCache.containsKey(name)) { 3038 uid = mUidCache.get(name); 3039 } else { 3040 uid = Process.getUidForPid(pid); 3041 mUidCache.put(name, uid); 3042 } 3043 Uid u = getUidStatsLocked(uid); 3044 return u.getProcessStatsLocked(name); 3045 } 3046 3047 /** 3048 * Retrieve the statistics object for a particular process, creating 3049 * if needed. 3050 */ 3051 public Uid.Pkg getPackageStatsLocked(int uid, String pkg) { 3052 Uid u = getUidStatsLocked(uid); 3053 return u.getPackageStatsLocked(pkg); 3054 } 3055 3056 /** 3057 * Retrieve the statistics object for a particular service, creating 3058 * if needed. 3059 */ 3060 public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) { 3061 Uid u = getUidStatsLocked(uid); 3062 return u.getServiceStatsLocked(pkg, name); 3063 } 3064 3065 private static JournaledFile makeJournaledFile() { 3066 final String base = "/data/system/device_policies.xml"; 3067 return new JournaledFile(new File(base), new File(base + ".tmp")); 3068 } 3069 3070 public void writeLocked() { 3071 if (mFile == null) { 3072 Slog.w("BatteryStats", "writeLocked: no file associated with this instance"); 3073 return; 3074 } 3075 3076 try { 3077 FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite()); 3078 Parcel out = Parcel.obtain(); 3079 writeSummaryToParcel(out); 3080 stream.write(out.marshall()); 3081 out.recycle(); 3082 3083 stream.flush(); 3084 stream.close(); 3085 mFile.commit(); 3086 3087 mLastWriteTime = SystemClock.elapsedRealtime(); 3088 return; 3089 } catch (IOException e) { 3090 Slog.w("BatteryStats", "Error writing battery statistics", e); 3091 } 3092 mFile.rollback(); 3093 } 3094 3095 static byte[] readFully(FileInputStream stream) throws java.io.IOException { 3096 int pos = 0; 3097 int avail = stream.available(); 3098 byte[] data = new byte[avail]; 3099 while (true) { 3100 int amt = stream.read(data, pos, data.length-pos); 3101 //Log.i("foo", "Read " + amt + " bytes at " + pos 3102 // + " of avail " + data.length); 3103 if (amt <= 0) { 3104 //Log.i("foo", "**** FINISHED READING: pos=" + pos 3105 // + " len=" + data.length); 3106 return data; 3107 } 3108 pos += amt; 3109 avail = stream.available(); 3110 if (avail > data.length-pos) { 3111 byte[] newData = new byte[pos+avail]; 3112 System.arraycopy(data, 0, newData, 0, pos); 3113 data = newData; 3114 } 3115 } 3116 } 3117 3118 public void readLocked() { 3119 if (mFile == null) { 3120 Slog.w("BatteryStats", "readLocked: no file associated with this instance"); 3121 return; 3122 } 3123 3124 mUidStats.clear(); 3125 3126 try { 3127 File file = mFile.chooseForRead(); 3128 if (!file.exists()) { 3129 return; 3130 } 3131 FileInputStream stream = new FileInputStream(file); 3132 3133 byte[] raw = readFully(stream); 3134 Parcel in = Parcel.obtain(); 3135 in.unmarshall(raw, 0, raw.length); 3136 in.setDataPosition(0); 3137 stream.close(); 3138 3139 readSummaryFromParcel(in); 3140 } catch(java.io.IOException e) { 3141 Slog.e("BatteryStats", "Error reading battery statistics", e); 3142 } 3143 } 3144 3145 public int describeContents() { 3146 return 0; 3147 } 3148 3149 private void readSummaryFromParcel(Parcel in) { 3150 final int version = in.readInt(); 3151 if (version != VERSION) { 3152 Slog.w("BatteryStats", "readFromParcel: version got " + version 3153 + ", expected " + VERSION + "; erasing old stats"); 3154 return; 3155 } 3156 3157 mStartCount = in.readInt(); 3158 mBatteryUptime = in.readLong(); 3159 mBatteryLastUptime = in.readLong(); 3160 mBatteryRealtime = in.readLong(); 3161 mBatteryLastRealtime = in.readLong(); 3162 mUptime = in.readLong(); 3163 mLastUptime = in.readLong(); 3164 mRealtime = in.readLong(); 3165 mLastRealtime = in.readLong(); 3166 mDischargeStartLevel = in.readInt(); 3167 mDischargeCurrentLevel = in.readInt(); 3168 3169 mStartCount++; 3170 3171 mScreenOn = false; 3172 mScreenOnTimer.readSummaryFromParcelLocked(in); 3173 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3174 mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in); 3175 } 3176 mInputEventCounter.readSummaryFromParcelLocked(in); 3177 mPhoneOn = false; 3178 mPhoneOnTimer.readSummaryFromParcelLocked(in); 3179 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3180 mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in); 3181 } 3182 mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in); 3183 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3184 mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in); 3185 } 3186 mWifiOn = false; 3187 mWifiOnTimer.readSummaryFromParcelLocked(in); 3188 mWifiRunning = false; 3189 mWifiRunningTimer.readSummaryFromParcelLocked(in); 3190 mBluetoothOn = false; 3191 mBluetoothOnTimer.readSummaryFromParcelLocked(in); 3192 3193 int NKW = in.readInt(); 3194 if (NKW > 10000) { 3195 Slog.w(TAG, "File corrupt: too many kernel wake locks " + NKW); 3196 return; 3197 } 3198 for (int ikw = 0; ikw < NKW; ikw++) { 3199 if (in.readInt() != 0) { 3200 String kwltName = in.readString(); 3201 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in); 3202 } 3203 } 3204 3205 sNumSpeedSteps = in.readInt(); 3206 3207 final int NU = in.readInt(); 3208 if (NU > 10000) { 3209 Slog.w(TAG, "File corrupt: too many uids " + NU); 3210 return; 3211 } 3212 for (int iu = 0; iu < NU; iu++) { 3213 int uid = in.readInt(); 3214 Uid u = new Uid(uid); 3215 mUidStats.put(uid, u); 3216 3217 u.mWifiTurnedOn = false; 3218 u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in); 3219 u.mFullWifiLockOut = false; 3220 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); 3221 u.mAudioTurnedOn = false; 3222 u.mAudioTurnedOnTimer.readSummaryFromParcelLocked(in); 3223 u.mVideoTurnedOn = false; 3224 u.mVideoTurnedOnTimer.readSummaryFromParcelLocked(in); 3225 u.mScanWifiLockOut = false; 3226 u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); 3227 u.mWifiMulticastEnabled = false; 3228 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in); 3229 3230 if (in.readInt() != 0) { 3231 if (u.mUserActivityCounters == null) { 3232 u.initUserActivityLocked(); 3233 } 3234 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 3235 u.mUserActivityCounters[i].readSummaryFromParcelLocked(in); 3236 } 3237 } 3238 3239 int NW = in.readInt(); 3240 if (NW > 10000) { 3241 Slog.w(TAG, "File corrupt: too many wake locks " + NW); 3242 return; 3243 } 3244 for (int iw = 0; iw < NW; iw++) { 3245 String wlName = in.readString(); 3246 if (in.readInt() != 0) { 3247 u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in); 3248 } 3249 if (in.readInt() != 0) { 3250 u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in); 3251 } 3252 if (in.readInt() != 0) { 3253 u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in); 3254 } 3255 } 3256 3257 int NP = in.readInt(); 3258 if (NP > 10000) { 3259 Slog.w(TAG, "File corrupt: too many sensors " + NP); 3260 return; 3261 } 3262 for (int is = 0; is < NP; is++) { 3263 int seNumber = in.readInt(); 3264 if (in.readInt() != 0) { 3265 u.getSensorTimerLocked(seNumber, true) 3266 .readSummaryFromParcelLocked(in); 3267 } 3268 } 3269 3270 NP = in.readInt(); 3271 if (NP > 10000) { 3272 Slog.w(TAG, "File corrupt: too many processes " + NP); 3273 return; 3274 } 3275 for (int ip = 0; ip < NP; ip++) { 3276 String procName = in.readString(); 3277 Uid.Proc p = u.getProcessStatsLocked(procName); 3278 p.mUserTime = p.mLoadedUserTime = in.readLong(); 3279 p.mLastUserTime = in.readLong(); 3280 p.mSystemTime = p.mLoadedSystemTime = in.readLong(); 3281 p.mLastSystemTime = in.readLong(); 3282 p.mStarts = p.mLoadedStarts = in.readInt(); 3283 p.mLastStarts = in.readInt(); 3284 } 3285 3286 NP = in.readInt(); 3287 if (NP > 10000) { 3288 Slog.w(TAG, "File corrupt: too many packages " + NP); 3289 return; 3290 } 3291 for (int ip = 0; ip < NP; ip++) { 3292 String pkgName = in.readString(); 3293 Uid.Pkg p = u.getPackageStatsLocked(pkgName); 3294 p.mWakeups = p.mLoadedWakeups = in.readInt(); 3295 p.mLastWakeups = in.readInt(); 3296 final int NS = in.readInt(); 3297 for (int is = 0; is < NS; is++) { 3298 String servName = in.readString(); 3299 Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName); 3300 s.mStartTime = s.mLoadedStartTime = in.readLong(); 3301 s.mLastStartTime = in.readLong(); 3302 s.mStarts = s.mLoadedStarts = in.readInt(); 3303 s.mLastStarts = in.readInt(); 3304 s.mLaunches = s.mLoadedLaunches = in.readInt(); 3305 s.mLastLaunches = in.readInt(); 3306 } 3307 } 3308 3309 u.mLoadedTcpBytesReceived = in.readLong(); 3310 u.mLoadedTcpBytesSent = in.readLong(); 3311 } 3312 } 3313 3314 /** 3315 * Writes a summary of the statistics to a Parcel, in a format suitable to be written to 3316 * disk. This format does not allow a lossless round-trip. 3317 * 3318 * @param out the Parcel to be written to. 3319 */ 3320 public void writeSummaryToParcel(Parcel out) { 3321 final long NOW_SYS = SystemClock.uptimeMillis() * 1000; 3322 final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; 3323 final long NOW = getBatteryUptimeLocked(NOW_SYS); 3324 final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS); 3325 3326 out.writeInt(VERSION); 3327 3328 out.writeInt(mStartCount); 3329 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_TOTAL)); 3330 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT)); 3331 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_TOTAL)); 3332 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT)); 3333 out.writeLong(computeUptime(NOW_SYS, STATS_TOTAL)); 3334 out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT)); 3335 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL)); 3336 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT)); 3337 out.writeInt(mDischargeStartLevel); 3338 out.writeInt(mDischargeCurrentLevel); 3339 3340 3341 mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3342 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3343 mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 3344 } 3345 mInputEventCounter.writeSummaryFromParcelLocked(out); 3346 mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3347 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3348 mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 3349 } 3350 mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3351 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3352 mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); 3353 } 3354 mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3355 mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3356 mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3357 3358 out.writeInt(mKernelWakelockStats.size()); 3359 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 3360 Timer kwlt = ent.getValue(); 3361 if (kwlt != null) { 3362 out.writeInt(1); 3363 out.writeString(ent.getKey()); 3364 ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL); 3365 } else { 3366 out.writeInt(0); 3367 } 3368 } 3369 3370 out.writeInt(sNumSpeedSteps); 3371 final int NU = mUidStats.size(); 3372 out.writeInt(NU); 3373 for (int iu = 0; iu < NU; iu++) { 3374 out.writeInt(mUidStats.keyAt(iu)); 3375 Uid u = mUidStats.valueAt(iu); 3376 3377 u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3378 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3379 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3380 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3381 u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3382 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3383 3384 if (u.mUserActivityCounters == null) { 3385 out.writeInt(0); 3386 } else { 3387 out.writeInt(1); 3388 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { 3389 u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out); 3390 } 3391 } 3392 3393 int NW = u.mWakelockStats.size(); 3394 out.writeInt(NW); 3395 if (NW > 0) { 3396 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent 3397 : u.mWakelockStats.entrySet()) { 3398 out.writeString(ent.getKey()); 3399 Uid.Wakelock wl = ent.getValue(); 3400 if (wl.mTimerFull != null) { 3401 out.writeInt(1); 3402 wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL); 3403 } else { 3404 out.writeInt(0); 3405 } 3406 if (wl.mTimerPartial != null) { 3407 out.writeInt(1); 3408 wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL); 3409 } else { 3410 out.writeInt(0); 3411 } 3412 if (wl.mTimerWindow != null) { 3413 out.writeInt(1); 3414 wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL); 3415 } else { 3416 out.writeInt(0); 3417 } 3418 } 3419 } 3420 3421 int NSE = u.mSensorStats.size(); 3422 out.writeInt(NSE); 3423 if (NSE > 0) { 3424 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent 3425 : u.mSensorStats.entrySet()) { 3426 out.writeInt(ent.getKey()); 3427 Uid.Sensor se = ent.getValue(); 3428 if (se.mTimer != null) { 3429 out.writeInt(1); 3430 se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL); 3431 } else { 3432 out.writeInt(0); 3433 } 3434 } 3435 } 3436 3437 int NP = u.mProcessStats.size(); 3438 out.writeInt(NP); 3439 if (NP > 0) { 3440 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent 3441 : u.mProcessStats.entrySet()) { 3442 out.writeString(ent.getKey()); 3443 Uid.Proc ps = ent.getValue(); 3444 out.writeLong(ps.mUserTime); 3445 out.writeLong(ps.mUserTime - ps.mLoadedUserTime); 3446 out.writeLong(ps.mSystemTime); 3447 out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime); 3448 out.writeInt(ps.mStarts); 3449 out.writeInt(ps.mStarts - ps.mLoadedStarts); 3450 } 3451 } 3452 3453 NP = u.mPackageStats.size(); 3454 out.writeInt(NP); 3455 if (NP > 0) { 3456 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent 3457 : u.mPackageStats.entrySet()) { 3458 out.writeString(ent.getKey()); 3459 Uid.Pkg ps = ent.getValue(); 3460 out.writeInt(ps.mWakeups); 3461 out.writeInt(ps.mWakeups - ps.mLoadedWakeups); 3462 final int NS = ps.mServiceStats.size(); 3463 out.writeInt(NS); 3464 if (NS > 0) { 3465 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent 3466 : ps.mServiceStats.entrySet()) { 3467 out.writeString(sent.getKey()); 3468 BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue(); 3469 long time = ss.getStartTimeToNowLocked(NOW); 3470 out.writeLong(time); 3471 out.writeLong(time - ss.mLoadedStartTime); 3472 out.writeInt(ss.mStarts); 3473 out.writeInt(ss.mStarts - ss.mLoadedStarts); 3474 out.writeInt(ss.mLaunches); 3475 out.writeInt(ss.mLaunches - ss.mLoadedLaunches); 3476 } 3477 } 3478 } 3479 } 3480 3481 out.writeLong(u.getTcpBytesReceived(STATS_TOTAL)); 3482 out.writeLong(u.getTcpBytesSent(STATS_TOTAL)); 3483 } 3484 } 3485 3486 public void readFromParcel(Parcel in) { 3487 readFromParcelLocked(in); 3488 } 3489 3490 void readFromParcelLocked(Parcel in) { 3491 int magic = in.readInt(); 3492 if (magic != MAGIC) { 3493 throw new ParcelFormatException("Bad magic number"); 3494 } 3495 3496 mStartCount = in.readInt(); 3497 mBatteryUptime = in.readLong(); 3498 mBatteryLastUptime = in.readLong(); 3499 mBatteryRealtime = in.readLong(); 3500 mBatteryLastRealtime = in.readLong(); 3501 mScreenOn = false; 3502 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in); 3503 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3504 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in); 3505 } 3506 mInputEventCounter = new Counter(mUnpluggables, in); 3507 mPhoneOn = false; 3508 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3509 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3510 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in); 3511 } 3512 mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables, in); 3513 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3514 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in); 3515 } 3516 mWifiOn = false; 3517 mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3518 mWifiRunning = false; 3519 mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3520 mBluetoothOn = false; 3521 mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in); 3522 mUptime = in.readLong(); 3523 mUptimeStart = in.readLong(); 3524 mLastUptime = in.readLong(); 3525 mRealtime = in.readLong(); 3526 mRealtimeStart = in.readLong(); 3527 mLastRealtime = in.readLong(); 3528 mOnBattery = in.readInt() != 0; 3529 mOnBatteryInternal = false; // we are no longer really running. 3530 mTrackBatteryPastUptime = in.readLong(); 3531 mTrackBatteryUptimeStart = in.readLong(); 3532 mTrackBatteryPastRealtime = in.readLong(); 3533 mTrackBatteryRealtimeStart = in.readLong(); 3534 mUnpluggedBatteryUptime = in.readLong(); 3535 mUnpluggedBatteryRealtime = in.readLong(); 3536 mDischargeStartLevel = in.readInt(); 3537 mDischargeCurrentLevel = in.readInt(); 3538 mLastWriteTime = in.readLong(); 3539 3540 mMobileDataRx[STATS_LAST] = in.readLong(); 3541 mMobileDataRx[STATS_UNPLUGGED] = -1; 3542 mMobileDataTx[STATS_LAST] = in.readLong(); 3543 mMobileDataTx[STATS_UNPLUGGED] = -1; 3544 mTotalDataRx[STATS_LAST] = in.readLong(); 3545 mTotalDataRx[STATS_UNPLUGGED] = -1; 3546 mTotalDataTx[STATS_LAST] = in.readLong(); 3547 mTotalDataTx[STATS_UNPLUGGED] = -1; 3548 3549 mRadioDataUptime = in.readLong(); 3550 mRadioDataStart = -1; 3551 3552 mBluetoothPingCount = in.readInt(); 3553 mBluetoothPingStart = -1; 3554 3555 mKernelWakelockStats.clear(); 3556 int NKW = in.readInt(); 3557 for (int ikw = 0; ikw < NKW; ikw++) { 3558 if (in.readInt() != 0) { 3559 String wakelockName = in.readString(); 3560 in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel 3561 SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in); 3562 mKernelWakelockStats.put(wakelockName, kwlt); 3563 } 3564 } 3565 3566 mPartialTimers.clear(); 3567 mFullTimers.clear(); 3568 mWindowTimers.clear(); 3569 3570 sNumSpeedSteps = in.readInt(); 3571 3572 int numUids = in.readInt(); 3573 mUidStats.clear(); 3574 for (int i = 0; i < numUids; i++) { 3575 int uid = in.readInt(); 3576 Uid u = new Uid(uid); 3577 u.readFromParcelLocked(mUnpluggables, in); 3578 mUidStats.append(uid, u); 3579 } 3580 } 3581 3582 public void writeToParcel(Parcel out, int flags) { 3583 writeToParcelLocked(out, flags); 3584 } 3585 3586 @SuppressWarnings("unused") 3587 void writeToParcelLocked(Parcel out, int flags) { 3588 final long uSecUptime = SystemClock.uptimeMillis() * 1000; 3589 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; 3590 final long batteryUptime = getBatteryUptimeLocked(uSecUptime); 3591 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); 3592 3593 out.writeInt(MAGIC); 3594 out.writeInt(mStartCount); 3595 out.writeLong(mBatteryUptime); 3596 out.writeLong(mBatteryLastUptime); 3597 out.writeLong(mBatteryRealtime); 3598 out.writeLong(mBatteryLastRealtime); 3599 mScreenOnTimer.writeToParcel(out, batteryRealtime); 3600 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3601 mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime); 3602 } 3603 mInputEventCounter.writeToParcel(out); 3604 mPhoneOnTimer.writeToParcel(out, batteryRealtime); 3605 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3606 mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime); 3607 } 3608 mPhoneSignalScanningTimer.writeToParcel(out, batteryRealtime); 3609 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3610 mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime); 3611 } 3612 mWifiOnTimer.writeToParcel(out, batteryRealtime); 3613 mWifiRunningTimer.writeToParcel(out, batteryRealtime); 3614 mBluetoothOnTimer.writeToParcel(out, batteryRealtime); 3615 out.writeLong(mUptime); 3616 out.writeLong(mUptimeStart); 3617 out.writeLong(mLastUptime); 3618 out.writeLong(mRealtime); 3619 out.writeLong(mRealtimeStart); 3620 out.writeLong(mLastRealtime); 3621 out.writeInt(mOnBattery ? 1 : 0); 3622 out.writeLong(batteryUptime); 3623 out.writeLong(mTrackBatteryUptimeStart); 3624 out.writeLong(batteryRealtime); 3625 out.writeLong(mTrackBatteryRealtimeStart); 3626 out.writeLong(mUnpluggedBatteryUptime); 3627 out.writeLong(mUnpluggedBatteryRealtime); 3628 out.writeInt(mDischargeStartLevel); 3629 out.writeInt(mDischargeCurrentLevel); 3630 out.writeLong(mLastWriteTime); 3631 3632 out.writeLong(getMobileTcpBytesReceived(STATS_UNPLUGGED)); 3633 out.writeLong(getMobileTcpBytesSent(STATS_UNPLUGGED)); 3634 out.writeLong(getTotalTcpBytesReceived(STATS_UNPLUGGED)); 3635 out.writeLong(getTotalTcpBytesSent(STATS_UNPLUGGED)); 3636 3637 // Write radio uptime for data 3638 out.writeLong(getRadioDataUptime()); 3639 3640 out.writeInt(getBluetoothPingCount()); 3641 3642 out.writeInt(mKernelWakelockStats.size()); 3643 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { 3644 SamplingTimer kwlt = ent.getValue(); 3645 if (kwlt != null) { 3646 out.writeInt(1); 3647 out.writeString(ent.getKey()); 3648 Timer.writeTimerToParcel(out, kwlt, batteryRealtime); 3649 } else { 3650 out.writeInt(0); 3651 } 3652 } 3653 3654 out.writeInt(sNumSpeedSteps); 3655 3656 int size = mUidStats.size(); 3657 out.writeInt(size); 3658 for (int i = 0; i < size; i++) { 3659 out.writeInt(mUidStats.keyAt(i)); 3660 Uid uid = mUidStats.valueAt(i); 3661 3662 uid.writeToParcelLocked(out, batteryRealtime); 3663 } 3664 } 3665 3666 public static final Parcelable.Creator<BatteryStatsImpl> CREATOR = 3667 new Parcelable.Creator<BatteryStatsImpl>() { 3668 public BatteryStatsImpl createFromParcel(Parcel in) { 3669 return new BatteryStatsImpl(in); 3670 } 3671 3672 public BatteryStatsImpl[] newArray(int size) { 3673 return new BatteryStatsImpl[size]; 3674 } 3675 }; 3676 3677 public void dumpLocked(PrintWriter pw) { 3678 if (DEBUG) { 3679 Printer pr = new PrintWriterPrinter(pw); 3680 pr.println("*** Screen timer:"); 3681 mScreenOnTimer.logState(pr, " "); 3682 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { 3683 pr.println("*** Screen brightness #" + i + ":"); 3684 mScreenBrightnessTimer[i].logState(pr, " "); 3685 } 3686 pr.println("*** Input event counter:"); 3687 mInputEventCounter.logState(pr, " "); 3688 pr.println("*** Phone timer:"); 3689 mPhoneOnTimer.logState(pr, " "); 3690 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 3691 pr.println("*** Signal strength #" + i + ":"); 3692 mPhoneSignalStrengthsTimer[i].logState(pr, " "); 3693 } 3694 pr.println("*** Signal scanning :"); 3695 mPhoneSignalScanningTimer.logState(pr, " "); 3696 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 3697 pr.println("*** Data connection type #" + i + ":"); 3698 mPhoneDataConnectionsTimer[i].logState(pr, " "); 3699 } 3700 pr.println("*** Wifi timer:"); 3701 mWifiOnTimer.logState(pr, " "); 3702 pr.println("*** WifiRunning timer:"); 3703 mWifiRunningTimer.logState(pr, " "); 3704 pr.println("*** Bluetooth timer:"); 3705 mBluetoothOnTimer.logState(pr, " "); 3706 } 3707 super.dumpLocked(pw); 3708 } 3709 } 3710