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