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