Home | History | Annotate | Download | only in os
      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