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