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