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