Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2006-2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.os;
     18 
     19 import static android.net.NetworkStats.UID_ALL;
     20 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
     21 
     22 import android.app.ActivityManager;
     23 import android.bluetooth.BluetoothDevice;
     24 import android.bluetooth.BluetoothHeadset;
     25 import android.content.Context;
     26 import android.net.ConnectivityManager;
     27 import android.net.NetworkStats;
     28 import android.net.wifi.WifiManager;
     29 import android.os.BadParcelableException;
     30 import android.os.BatteryManager;
     31 import android.os.BatteryStats;
     32 import android.os.Build;
     33 import android.os.FileUtils;
     34 import android.os.Handler;
     35 import android.os.Looper;
     36 import android.os.Message;
     37 import android.os.Parcel;
     38 import android.os.ParcelFormatException;
     39 import android.os.Parcelable;
     40 import android.os.Process;
     41 import android.os.SystemClock;
     42 import android.os.SystemProperties;
     43 import android.os.WorkSource;
     44 import android.telephony.DataConnectionRealTimeInfo;
     45 import android.telephony.ServiceState;
     46 import android.telephony.SignalStrength;
     47 import android.telephony.TelephonyManager;
     48 import android.text.TextUtils;
     49 import android.util.ArrayMap;
     50 import android.util.Log;
     51 import android.util.LogWriter;
     52 import android.util.MutableInt;
     53 import android.util.PrintWriterPrinter;
     54 import android.util.Printer;
     55 import android.util.Slog;
     56 import android.util.SparseArray;
     57 import android.util.SparseIntArray;
     58 import android.util.TimeUtils;
     59 import android.view.Display;
     60 
     61 import com.android.internal.annotations.GuardedBy;
     62 import com.android.internal.net.NetworkStatsFactory;
     63 import com.android.internal.util.ArrayUtils;
     64 import com.android.internal.util.FastPrintWriter;
     65 import com.android.internal.util.JournaledFile;
     66 
     67 import java.io.File;
     68 import java.io.FileInputStream;
     69 import java.io.FileOutputStream;
     70 import java.io.IOException;
     71 import java.io.PrintWriter;
     72 import java.util.ArrayList;
     73 import java.util.HashMap;
     74 import java.util.Iterator;
     75 import java.util.List;
     76 import java.util.Map;
     77 import java.util.concurrent.atomic.AtomicInteger;
     78 import java.util.concurrent.locks.ReentrantLock;
     79 
     80 /**
     81  * All information we are collecting about things that can happen that impact
     82  * battery life.  All times are represented in microseconds except where indicated
     83  * otherwise.
     84  */
     85 public final class BatteryStatsImpl extends BatteryStats {
     86     private static final String TAG = "BatteryStatsImpl";
     87     private static final boolean DEBUG = false;
     88     private static final boolean DEBUG_HISTORY = false;
     89     private static final boolean USE_OLD_HISTORY = false;   // for debugging.
     90 
     91     // TODO: remove "tcp" from network methods, since we measure total stats.
     92 
     93     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
     94     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
     95 
     96     // Current on-disk Parcel version
     97     private static final int VERSION = 116 + (USE_OLD_HISTORY ? 1000 : 0);
     98 
     99     // Maximum number of items we will record in the history.
    100     private static final int MAX_HISTORY_ITEMS = 2000;
    101 
    102     // No, really, THIS is the maximum number of items we will record in the history.
    103     private static final int MAX_MAX_HISTORY_ITEMS = 3000;
    104 
    105     // The maximum number of names wakelocks we will keep track of
    106     // per uid; once the limit is reached, we batch the remaining wakelocks
    107     // in to one common name.
    108     private static final int MAX_WAKELOCKS_PER_UID = 100;
    109 
    110     private static int sNumSpeedSteps;
    111 
    112     private final JournaledFile mFile;
    113     public final AtomicFile mCheckinFile;
    114 
    115     static final int MSG_UPDATE_WAKELOCKS = 1;
    116     static final int MSG_REPORT_POWER_CHANGE = 2;
    117     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
    118 
    119     public interface BatteryCallback {
    120         public void batteryNeedsCpuUpdate();
    121         public void batteryPowerChanged(boolean onBattery);
    122     }
    123 
    124     final class MyHandler extends Handler {
    125         public MyHandler(Looper looper) {
    126             super(looper, null, true);
    127         }
    128 
    129         @Override
    130         public void handleMessage(Message msg) {
    131             BatteryCallback cb = mCallback;
    132             switch (msg.what) {
    133                 case MSG_UPDATE_WAKELOCKS:
    134                     if (cb != null) {
    135                         cb.batteryNeedsCpuUpdate();
    136                     }
    137                     break;
    138                 case MSG_REPORT_POWER_CHANGE:
    139                     if (cb != null) {
    140                         cb.batteryPowerChanged(msg.arg1 != 0);
    141                     }
    142                     break;
    143             }
    144         }
    145     }
    146 
    147     public final MyHandler mHandler;
    148 
    149     private BatteryCallback mCallback;
    150 
    151     /**
    152      * Mapping isolated uids to the actual owning app uid.
    153      */
    154     final SparseIntArray mIsolatedUids = new SparseIntArray();
    155 
    156     /**
    157      * The statistics we have collected organized by uids.
    158      */
    159     final SparseArray<BatteryStatsImpl.Uid> mUidStats =
    160         new SparseArray<BatteryStatsImpl.Uid>();
    161 
    162     // A set of pools of currently active timers.  When a timer is queried, we will divide the
    163     // elapsed time by the number of active timers to arrive at that timer's share of the time.
    164     // In order to do this, we must refresh each timer whenever the number of active timers
    165     // changes.
    166     final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>();
    167     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>();
    168     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>();
    169     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
    170             = new SparseArray<ArrayList<StopwatchTimer>>();
    171     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<StopwatchTimer>();
    172     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<StopwatchTimer>();
    173     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<StopwatchTimer>();
    174     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<StopwatchTimer>();
    175     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers =
    176             new SparseArray<ArrayList<StopwatchTimer>>();
    177     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<StopwatchTimer>();
    178     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<StopwatchTimer>();
    179 
    180     // Last partial timers we use for distributing CPU usage.
    181     final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
    182 
    183     // These are the objects that will want to do something when the device
    184     // is unplugged from power.
    185     final TimeBase mOnBatteryTimeBase = new TimeBase();
    186 
    187     // These are the objects that will want to do something when the device
    188     // is unplugged from power *and* the screen is off.
    189     final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase();
    190 
    191     // Set to true when we want to distribute CPU across wakelocks for the next
    192     // CPU update, even if we aren't currently running wake locks.
    193     boolean mDistributeWakelockCpu;
    194 
    195     boolean mShuttingDown;
    196 
    197     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
    198 
    199     long mHistoryBaseTime;
    200     boolean mHaveBatteryLevel = false;
    201     boolean mRecordingHistory = false;
    202     int mNumHistoryItems;
    203 
    204     static final int MAX_HISTORY_BUFFER = 256*1024; // 256KB
    205     static final int MAX_MAX_HISTORY_BUFFER = 320*1024; // 320KB
    206     final Parcel mHistoryBuffer = Parcel.obtain();
    207     final HistoryItem mHistoryLastWritten = new HistoryItem();
    208     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
    209     final HistoryItem mHistoryReadTmp = new HistoryItem();
    210     final HistoryItem mHistoryAddTmp = new HistoryItem();
    211     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<HistoryTag, Integer>();
    212     String[] mReadHistoryStrings;
    213     int[] mReadHistoryUids;
    214     int mReadHistoryChars;
    215     int mNextHistoryTagIdx = 0;
    216     int mNumHistoryTagChars = 0;
    217     int mHistoryBufferLastPos = -1;
    218     boolean mHistoryOverflow = false;
    219     long mLastHistoryElapsedRealtime = 0;
    220     long mTrackRunningHistoryElapsedRealtime = 0;
    221     long mTrackRunningHistoryUptime = 0;
    222 
    223     final HistoryItem mHistoryCur = new HistoryItem();
    224 
    225     HistoryItem mHistory;
    226     HistoryItem mHistoryEnd;
    227     HistoryItem mHistoryLastEnd;
    228     HistoryItem mHistoryCache;
    229 
    230     private HistoryItem mHistoryIterator;
    231     private boolean mReadOverflow;
    232     private boolean mIteratingHistory;
    233 
    234     int mStartCount;
    235 
    236     long mStartClockTime;
    237     String mStartPlatformVersion;
    238     String mEndPlatformVersion;
    239 
    240     long mLastRecordedClockTime;
    241     long mLastRecordedClockRealtime;
    242 
    243     long mUptime;
    244     long mUptimeStart;
    245     long mRealtime;
    246     long mRealtimeStart;
    247 
    248     int mWakeLockNesting;
    249     boolean mWakeLockImportant;
    250     boolean mRecordAllHistory;
    251     boolean mNoAutoReset;
    252 
    253     int mScreenState = Display.STATE_UNKNOWN;
    254     StopwatchTimer mScreenOnTimer;
    255 
    256     int mScreenBrightnessBin = -1;
    257     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
    258 
    259     boolean mInteractive;
    260     StopwatchTimer mInteractiveTimer;
    261 
    262     boolean mLowPowerModeEnabled;
    263     StopwatchTimer mLowPowerModeEnabledTimer;
    264 
    265     boolean mPhoneOn;
    266     StopwatchTimer mPhoneOnTimer;
    267 
    268     int mAudioOnNesting;
    269     StopwatchTimer mAudioOnTimer;
    270 
    271     int mVideoOnNesting;
    272     StopwatchTimer mVideoOnTimer;
    273 
    274     boolean mFlashlightOn;
    275     StopwatchTimer mFlashlightOnTimer;
    276 
    277     int mPhoneSignalStrengthBin = -1;
    278     int mPhoneSignalStrengthBinRaw = -1;
    279     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
    280             new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
    281 
    282     StopwatchTimer mPhoneSignalScanningTimer;
    283 
    284     int mPhoneDataConnectionType = -1;
    285     final StopwatchTimer[] mPhoneDataConnectionsTimer =
    286             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
    287 
    288     final LongSamplingCounter[] mNetworkByteActivityCounters =
    289             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
    290     final LongSamplingCounter[] mNetworkPacketActivityCounters =
    291             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
    292 
    293     boolean mWifiOn;
    294     StopwatchTimer mWifiOnTimer;
    295 
    296     boolean mGlobalWifiRunning;
    297     StopwatchTimer mGlobalWifiRunningTimer;
    298 
    299     int mWifiState = -1;
    300     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
    301 
    302     int mWifiSupplState = -1;
    303     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
    304 
    305     int mWifiSignalStrengthBin = -1;
    306     final StopwatchTimer[] mWifiSignalStrengthsTimer =
    307             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
    308 
    309     boolean mBluetoothOn;
    310     StopwatchTimer mBluetoothOnTimer;
    311 
    312     int mBluetoothState = -1;
    313     final StopwatchTimer[] mBluetoothStateTimer = new StopwatchTimer[NUM_BLUETOOTH_STATES];
    314 
    315     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
    316     long mMobileRadioActiveStartTime;
    317     StopwatchTimer mMobileRadioActiveTimer;
    318     StopwatchTimer mMobileRadioActivePerAppTimer;
    319     LongSamplingCounter mMobileRadioActiveAdjustedTime;
    320     LongSamplingCounter mMobileRadioActiveUnknownTime;
    321     LongSamplingCounter mMobileRadioActiveUnknownCount;
    322 
    323     /** Bluetooth headset object */
    324     BluetoothHeadset mBtHeadset;
    325 
    326     /**
    327      * These provide time bases that discount the time the device is plugged
    328      * in to power.
    329      */
    330     boolean mOnBattery;
    331     boolean mOnBatteryInternal;
    332 
    333     /*
    334      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
    335      */
    336     int mDischargeStartLevel;
    337     int mDischargeUnplugLevel;
    338     int mDischargePlugLevel;
    339     int mDischargeCurrentLevel;
    340     int mCurrentBatteryLevel;
    341     int mLowDischargeAmountSinceCharge;
    342     int mHighDischargeAmountSinceCharge;
    343     int mDischargeScreenOnUnplugLevel;
    344     int mDischargeScreenOffUnplugLevel;
    345     int mDischargeAmountScreenOn;
    346     int mDischargeAmountScreenOnSinceCharge;
    347     int mDischargeAmountScreenOff;
    348     int mDischargeAmountScreenOffSinceCharge;
    349 
    350     static final int MAX_LEVEL_STEPS = 200;
    351 
    352     int mInitStepMode = 0;
    353     int mCurStepMode = 0;
    354     int mModStepMode = 0;
    355 
    356     int mLastDischargeStepLevel;
    357     long mLastDischargeStepTime;
    358     int mMinDischargeStepLevel;
    359     int mNumDischargeStepDurations;
    360     final long[] mDischargeStepDurations = new long[MAX_LEVEL_STEPS];
    361 
    362     int mLastChargeStepLevel;
    363     long mLastChargeStepTime;
    364     int mMaxChargeStepLevel;
    365     int mNumChargeStepDurations;
    366     final long[] mChargeStepDurations = new long[MAX_LEVEL_STEPS];
    367 
    368     long mLastWriteTime = 0; // Milliseconds
    369 
    370     private int mBluetoothPingCount;
    371     private int mBluetoothPingStart = -1;
    372 
    373     private int mPhoneServiceState = -1;
    374     private int mPhoneServiceStateRaw = -1;
    375     private int mPhoneSimStateRaw = -1;
    376 
    377     private int mNumConnectivityChange;
    378     private int mLoadedNumConnectivityChange;
    379     private int mUnpluggedNumConnectivityChange;
    380 
    381     /*
    382      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
    383      */
    384     private final HashMap<String, SamplingTimer> mKernelWakelockStats =
    385             new HashMap<String, SamplingTimer>();
    386 
    387     public Map<String, ? extends Timer> getKernelWakelockStats() {
    388         return mKernelWakelockStats;
    389     }
    390 
    391     private static int sKernelWakelockUpdateVersion = 0;
    392 
    393     String mLastWakeupReason = null;
    394     long mLastWakeupUptimeMs = 0;
    395     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
    396 
    397     public Map<String, ? extends Timer> getWakeupReasonStats() {
    398         return mWakeupReasonStats;
    399     }
    400 
    401     private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
    402         Process.PROC_TAB_TERM|Process.PROC_OUT_STRING|                // 0: name
    403                               Process.PROC_QUOTES,
    404         Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 1: count
    405         Process.PROC_TAB_TERM,
    406         Process.PROC_TAB_TERM,
    407         Process.PROC_TAB_TERM,
    408         Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 5: totalTime
    409     };
    410 
    411     private static final int[] WAKEUP_SOURCES_FORMAT = new int[] {
    412         Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
    413         Process.PROC_TAB_TERM|Process.PROC_COMBINE|
    414                               Process.PROC_OUT_LONG,                  // 1: count
    415         Process.PROC_TAB_TERM|Process.PROC_COMBINE,
    416         Process.PROC_TAB_TERM|Process.PROC_COMBINE,
    417         Process.PROC_TAB_TERM|Process.PROC_COMBINE,
    418         Process.PROC_TAB_TERM|Process.PROC_COMBINE,
    419         Process.PROC_TAB_TERM|Process.PROC_COMBINE
    420                              |Process.PROC_OUT_LONG,                  // 6: totalTime
    421     };
    422 
    423     private final String[] mProcWakelocksName = new String[3];
    424     private final long[] mProcWakelocksData = new long[3];
    425 
    426     /*
    427      * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added
    428      * to mKernelWakelockStats.
    429      */
    430     private final Map<String, KernelWakelockStats> mProcWakelockFileStats =
    431             new HashMap<String, KernelWakelockStats>();
    432 
    433     private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
    434     private NetworkStats mCurMobileSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
    435     private NetworkStats mLastMobileSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
    436     private NetworkStats mCurWifiSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
    437     private NetworkStats mLastWifiSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
    438     private NetworkStats mTmpNetworkStats;
    439     private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
    440 
    441     @GuardedBy("this")
    442     private String[] mMobileIfaces = new String[0];
    443     @GuardedBy("this")
    444     private String[] mWifiIfaces = new String[0];
    445 
    446     public BatteryStatsImpl() {
    447         mFile = null;
    448         mCheckinFile = null;
    449         mHandler = null;
    450         clearHistoryLocked();
    451     }
    452 
    453     public static interface TimeBaseObs {
    454         void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
    455         void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
    456     }
    457 
    458     static class TimeBase {
    459         private final ArrayList<TimeBaseObs> mObservers = new ArrayList<TimeBaseObs>();
    460 
    461         private long mUptime;
    462         private long mRealtime;
    463 
    464         private boolean mRunning;
    465 
    466         private long mPastUptime;
    467         private long mUptimeStart;
    468         private long mPastRealtime;
    469         private long mRealtimeStart;
    470         private long mUnpluggedUptime;
    471         private long mUnpluggedRealtime;
    472 
    473         public void dump(PrintWriter pw, String prefix) {
    474             StringBuilder sb = new StringBuilder(128);
    475             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
    476             sb.setLength(0);
    477             sb.append(prefix);
    478                     sb.append("mUptime=");
    479                     formatTimeMs(sb, mUptime / 1000);
    480             pw.println(sb.toString());
    481             sb.setLength(0);
    482             sb.append(prefix);
    483                     sb.append("mRealtime=");
    484                     formatTimeMs(sb, mRealtime / 1000);
    485             pw.println(sb.toString());
    486             sb.setLength(0);
    487             sb.append(prefix);
    488                     sb.append("mPastUptime=");
    489                     formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
    490                     formatTimeMs(sb, mUptimeStart / 1000);
    491                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
    492             pw.println(sb.toString());
    493             sb.setLength(0);
    494             sb.append(prefix);
    495                     sb.append("mPastRealtime=");
    496                     formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
    497                     formatTimeMs(sb, mRealtimeStart / 1000);
    498                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
    499             pw.println(sb.toString());
    500         }
    501 
    502         public void add(TimeBaseObs observer) {
    503             mObservers.add(observer);
    504         }
    505 
    506         public void remove(TimeBaseObs observer) {
    507             if (!mObservers.remove(observer)) {
    508                 Slog.wtf(TAG, "Removed unknown observer: " + observer);
    509             }
    510         }
    511 
    512         public void init(long uptime, long realtime) {
    513             mRealtime = 0;
    514             mUptime = 0;
    515             mPastUptime = 0;
    516             mPastRealtime = 0;
    517             mUptimeStart = uptime;
    518             mRealtimeStart = realtime;
    519             mUnpluggedUptime = getUptime(mUptimeStart);
    520             mUnpluggedRealtime = getRealtime(mRealtimeStart);
    521         }
    522 
    523         public void reset(long uptime, long realtime) {
    524             if (!mRunning) {
    525                 mPastUptime = 0;
    526                 mPastRealtime = 0;
    527             } else {
    528                 mUptimeStart = uptime;
    529                 mRealtimeStart = realtime;
    530                 mUnpluggedUptime = getUptime(uptime);
    531                 mUnpluggedRealtime = getRealtime(realtime);
    532             }
    533         }
    534 
    535         public long computeUptime(long curTime, int which) {
    536             switch (which) {
    537                 case STATS_SINCE_CHARGED:
    538                     return mUptime + getUptime(curTime);
    539                 case STATS_CURRENT:
    540                     return getUptime(curTime);
    541                 case STATS_SINCE_UNPLUGGED:
    542                     return getUptime(curTime) - mUnpluggedUptime;
    543             }
    544             return 0;
    545         }
    546 
    547         public long computeRealtime(long curTime, int which) {
    548             switch (which) {
    549                 case STATS_SINCE_CHARGED:
    550                     return mRealtime + getRealtime(curTime);
    551                 case STATS_CURRENT:
    552                     return getRealtime(curTime);
    553                 case STATS_SINCE_UNPLUGGED:
    554                     return getRealtime(curTime) - mUnpluggedRealtime;
    555             }
    556             return 0;
    557         }
    558 
    559         public long getUptime(long curTime) {
    560             long time = mPastUptime;
    561             if (mRunning) {
    562                 time += curTime - mUptimeStart;
    563             }
    564             return time;
    565         }
    566 
    567         public long getRealtime(long curTime) {
    568             long time = mPastRealtime;
    569             if (mRunning) {
    570                 time += curTime - mRealtimeStart;
    571             }
    572             return time;
    573         }
    574 
    575         public long getUptimeStart() {
    576             return mUptimeStart;
    577         }
    578 
    579         public long getRealtimeStart() {
    580             return mRealtimeStart;
    581         }
    582 
    583         public boolean isRunning() {
    584             return mRunning;
    585         }
    586 
    587         public boolean setRunning(boolean running, long uptime, long realtime) {
    588             if (mRunning != running) {
    589                 mRunning = running;
    590                 if (running) {
    591                     mUptimeStart = uptime;
    592                     mRealtimeStart = realtime;
    593                     long batteryUptime = mUnpluggedUptime = getUptime(uptime);
    594                     long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
    595 
    596                     for (int i = mObservers.size() - 1; i >= 0; i--) {
    597                         mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime);
    598                     }
    599                 } else {
    600                     mPastUptime += uptime - mUptimeStart;
    601                     mPastRealtime += realtime - mRealtimeStart;
    602 
    603                     long batteryUptime = getUptime(uptime);
    604                     long batteryRealtime = getRealtime(realtime);
    605 
    606                     for (int i = mObservers.size() - 1; i >= 0; i--) {
    607                         mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime);
    608                     }
    609                 }
    610                 return true;
    611             }
    612             return false;
    613         }
    614 
    615         public void readSummaryFromParcel(Parcel in) {
    616             mUptime = in.readLong();
    617             mRealtime = in.readLong();
    618         }
    619 
    620         public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
    621             out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
    622             out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
    623         }
    624 
    625         public void readFromParcel(Parcel in) {
    626             mRunning = false;
    627             mUptime = in.readLong();
    628             mPastUptime = in.readLong();
    629             mUptimeStart = in.readLong();
    630             mRealtime = in.readLong();
    631             mPastRealtime = in.readLong();
    632             mRealtimeStart = in.readLong();
    633             mUnpluggedUptime = in.readLong();
    634             mUnpluggedRealtime = in.readLong();
    635         }
    636 
    637         public void writeToParcel(Parcel out, long uptime, long realtime) {
    638             final long runningUptime = getUptime(uptime);
    639             final long runningRealtime = getRealtime(realtime);
    640             out.writeLong(mUptime);
    641             out.writeLong(runningUptime);
    642             out.writeLong(mUptimeStart);
    643             out.writeLong(mRealtime);
    644             out.writeLong(runningRealtime);
    645             out.writeLong(mRealtimeStart);
    646             out.writeLong(mUnpluggedUptime);
    647             out.writeLong(mUnpluggedRealtime);
    648         }
    649     }
    650 
    651     /**
    652      * State for keeping track of counting information.
    653      */
    654     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
    655         final AtomicInteger mCount = new AtomicInteger();
    656         final TimeBase mTimeBase;
    657         int mLoadedCount;
    658         int mLastCount;
    659         int mUnpluggedCount;
    660         int mPluggedCount;
    661 
    662         Counter(TimeBase timeBase, Parcel in) {
    663             mTimeBase = timeBase;
    664             mPluggedCount = in.readInt();
    665             mCount.set(mPluggedCount);
    666             mLoadedCount = in.readInt();
    667             mLastCount = 0;
    668             mUnpluggedCount = in.readInt();
    669             timeBase.add(this);
    670         }
    671 
    672         Counter(TimeBase timeBase) {
    673             mTimeBase = timeBase;
    674             timeBase.add(this);
    675         }
    676 
    677         public void writeToParcel(Parcel out) {
    678             out.writeInt(mCount.get());
    679             out.writeInt(mLoadedCount);
    680             out.writeInt(mUnpluggedCount);
    681         }
    682 
    683         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
    684             mUnpluggedCount = mPluggedCount;
    685             mCount.set(mPluggedCount);
    686         }
    687 
    688         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
    689             mPluggedCount = mCount.get();
    690         }
    691 
    692         /**
    693          * Writes a possibly null Counter to a Parcel.
    694          *
    695          * @param out the Parcel to be written to.
    696          * @param counter a Counter, or null.
    697          */
    698         public static void writeCounterToParcel(Parcel out, Counter counter) {
    699             if (counter == null) {
    700                 out.writeInt(0); // indicates null
    701                 return;
    702             }
    703             out.writeInt(1); // indicates non-null
    704 
    705             counter.writeToParcel(out);
    706         }
    707 
    708         @Override
    709         public int getCountLocked(int which) {
    710             int val = mCount.get();
    711             if (which == STATS_SINCE_UNPLUGGED) {
    712                 val -= mUnpluggedCount;
    713             } else if (which != STATS_SINCE_CHARGED) {
    714                 val -= mLoadedCount;
    715             }
    716 
    717             return val;
    718         }
    719 
    720         public void logState(Printer pw, String prefix) {
    721             pw.println(prefix + "mCount=" + mCount.get()
    722                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
    723                     + " mUnpluggedCount=" + mUnpluggedCount
    724                     + " mPluggedCount=" + mPluggedCount);
    725         }
    726 
    727         void stepAtomic() {
    728             mCount.incrementAndGet();
    729         }
    730 
    731         /**
    732          * Clear state of this counter.
    733          */
    734         void reset(boolean detachIfReset) {
    735             mCount.set(0);
    736             mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
    737             if (detachIfReset) {
    738                 detach();
    739             }
    740         }
    741 
    742         void detach() {
    743             mTimeBase.remove(this);
    744         }
    745 
    746         void writeSummaryFromParcelLocked(Parcel out) {
    747             int count = mCount.get();
    748             out.writeInt(count);
    749         }
    750 
    751         void readSummaryFromParcelLocked(Parcel in) {
    752             mLoadedCount = in.readInt();
    753             mCount.set(mLoadedCount);
    754             mLastCount = 0;
    755             mUnpluggedCount = mPluggedCount = mLoadedCount;
    756         }
    757     }
    758 
    759     public static class SamplingCounter extends Counter {
    760         SamplingCounter(TimeBase timeBase, Parcel in) {
    761             super(timeBase, in);
    762         }
    763 
    764         SamplingCounter(TimeBase timeBase) {
    765             super(timeBase);
    766         }
    767 
    768         public void addCountAtomic(long count) {
    769             mCount.addAndGet((int)count);
    770         }
    771     }
    772 
    773     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
    774         final TimeBase mTimeBase;
    775         long mCount;
    776         long mLoadedCount;
    777         long mLastCount;
    778         long mUnpluggedCount;
    779         long mPluggedCount;
    780 
    781         LongSamplingCounter(TimeBase timeBase, Parcel in) {
    782             mTimeBase = timeBase;
    783             mPluggedCount = in.readLong();
    784             mCount = mPluggedCount;
    785             mLoadedCount = in.readLong();
    786             mLastCount = 0;
    787             mUnpluggedCount = in.readLong();
    788             timeBase.add(this);
    789         }
    790 
    791         LongSamplingCounter(TimeBase timeBase) {
    792             mTimeBase = timeBase;
    793             timeBase.add(this);
    794         }
    795 
    796         public void writeToParcel(Parcel out) {
    797             out.writeLong(mCount);
    798             out.writeLong(mLoadedCount);
    799             out.writeLong(mUnpluggedCount);
    800         }
    801 
    802         @Override
    803         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
    804             mUnpluggedCount = mPluggedCount;
    805             mCount = mPluggedCount;
    806         }
    807 
    808         @Override
    809         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
    810             mPluggedCount = mCount;
    811         }
    812 
    813         public long getCountLocked(int which) {
    814             long val = mCount;
    815             if (which == STATS_SINCE_UNPLUGGED) {
    816                 val -= mUnpluggedCount;
    817             } else if (which != STATS_SINCE_CHARGED) {
    818                 val -= mLoadedCount;
    819             }
    820 
    821             return val;
    822         }
    823 
    824         @Override
    825         public void logState(Printer pw, String prefix) {
    826             pw.println(prefix + "mCount=" + mCount
    827                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
    828                     + " mUnpluggedCount=" + mUnpluggedCount
    829                     + " mPluggedCount=" + mPluggedCount);
    830         }
    831 
    832         void addCountLocked(long count) {
    833             mCount += count;
    834         }
    835 
    836         /**
    837          * Clear state of this counter.
    838          */
    839         void reset(boolean detachIfReset) {
    840             mCount = 0;
    841             mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
    842             if (detachIfReset) {
    843                 detach();
    844             }
    845         }
    846 
    847         void detach() {
    848             mTimeBase.remove(this);
    849         }
    850 
    851         void writeSummaryFromParcelLocked(Parcel out) {
    852             out.writeLong(mCount);
    853         }
    854 
    855         void readSummaryFromParcelLocked(Parcel in) {
    856             mLoadedCount = in.readLong();
    857             mCount = mLoadedCount;
    858             mLastCount = 0;
    859             mUnpluggedCount = mPluggedCount = mLoadedCount;
    860         }
    861     }
    862 
    863     /**
    864      * State for keeping track of timing information.
    865      */
    866     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
    867         final int mType;
    868         final TimeBase mTimeBase;
    869 
    870         int mCount;
    871         int mLoadedCount;
    872         int mLastCount;
    873         int mUnpluggedCount;
    874 
    875         // Times are in microseconds for better accuracy when dividing by the
    876         // lock count, and are in "battery realtime" units.
    877 
    878         /**
    879          * The total time we have accumulated since the start of the original
    880          * boot, to the last time something interesting happened in the
    881          * current run.
    882          */
    883         long mTotalTime;
    884 
    885         /**
    886          * The total time we loaded for the previous runs.  Subtract this from
    887          * mTotalTime to find the time for the current run of the system.
    888          */
    889         long mLoadedTime;
    890 
    891         /**
    892          * The run time of the last run of the system, as loaded from the
    893          * saved data.
    894          */
    895         long mLastTime;
    896 
    897         /**
    898          * The value of mTotalTime when unplug() was last called.  Subtract
    899          * this from mTotalTime to find the time since the last unplug from
    900          * power.
    901          */
    902         long mUnpluggedTime;
    903 
    904         /**
    905          * Constructs from a parcel.
    906          * @param type
    907          * @param timeBase
    908          * @param in
    909          */
    910         Timer(int type, TimeBase timeBase, Parcel in) {
    911             mType = type;
    912             mTimeBase = timeBase;
    913 
    914             mCount = in.readInt();
    915             mLoadedCount = in.readInt();
    916             mLastCount = 0;
    917             mUnpluggedCount = in.readInt();
    918             mTotalTime = in.readLong();
    919             mLoadedTime = in.readLong();
    920             mLastTime = 0;
    921             mUnpluggedTime = in.readLong();
    922             timeBase.add(this);
    923             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
    924         }
    925 
    926         Timer(int type, TimeBase timeBase) {
    927             mType = type;
    928             mTimeBase = timeBase;
    929             timeBase.add(this);
    930         }
    931 
    932         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
    933 
    934         protected abstract int computeCurrentCountLocked();
    935 
    936         /**
    937          * Clear state of this timer.  Returns true if the timer is inactive
    938          * so can be completely dropped.
    939          */
    940         boolean reset(boolean detachIfReset) {
    941             mTotalTime = mLoadedTime = mLastTime = 0;
    942             mCount = mLoadedCount = mLastCount = 0;
    943             if (detachIfReset) {
    944                 detach();
    945             }
    946             return true;
    947         }
    948 
    949         void detach() {
    950             mTimeBase.remove(this);
    951         }
    952 
    953         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
    954             if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
    955                     + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
    956             out.writeInt(mCount);
    957             out.writeInt(mLoadedCount);
    958             out.writeInt(mUnpluggedCount);
    959             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
    960             out.writeLong(mLoadedTime);
    961             out.writeLong(mUnpluggedTime);
    962         }
    963 
    964         public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
    965             if (DEBUG && mType < 0) {
    966                 Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime
    967                         + " old mUnpluggedTime=" + mUnpluggedTime
    968                         + " old mUnpluggedCount=" + mUnpluggedCount);
    969             }
    970             mUnpluggedTime = computeRunTimeLocked(baseRealtime);
    971             mUnpluggedCount = mCount;
    972             if (DEBUG && mType < 0) {
    973                 Log.v(TAG, "unplug #" + mType
    974                         + ": new mUnpluggedTime=" + mUnpluggedTime
    975                         + " new mUnpluggedCount=" + mUnpluggedCount);
    976             }
    977         }
    978 
    979         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
    980             if (DEBUG && mType < 0) {
    981                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
    982                         + " old mTotalTime=" + mTotalTime);
    983             }
    984             mTotalTime = computeRunTimeLocked(baseRealtime);
    985             mCount = computeCurrentCountLocked();
    986             if (DEBUG && mType < 0) {
    987                 Log.v(TAG, "plug #" + mType
    988                         + ": new mTotalTime=" + mTotalTime);
    989             }
    990         }
    991 
    992         /**
    993          * Writes a possibly null Timer to a Parcel.
    994          *
    995          * @param out the Parcel to be written to.
    996          * @param timer a Timer, or null.
    997          */
    998         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
    999             if (timer == null) {
   1000                 out.writeInt(0); // indicates null
   1001                 return;
   1002             }
   1003             out.writeInt(1); // indicates non-null
   1004 
   1005             timer.writeToParcel(out, elapsedRealtimeUs);
   1006         }
   1007 
   1008         @Override
   1009         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
   1010             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
   1011             if (which == STATS_SINCE_UNPLUGGED) {
   1012                 val -= mUnpluggedTime;
   1013             } else if (which != STATS_SINCE_CHARGED) {
   1014                 val -= mLoadedTime;
   1015             }
   1016 
   1017             return val;
   1018         }
   1019 
   1020         @Override
   1021         public int getCountLocked(int which) {
   1022             int val = computeCurrentCountLocked();
   1023             if (which == STATS_SINCE_UNPLUGGED) {
   1024                 val -= mUnpluggedCount;
   1025             } else if (which != STATS_SINCE_CHARGED) {
   1026                 val -= mLoadedCount;
   1027             }
   1028 
   1029             return val;
   1030         }
   1031 
   1032         public void logState(Printer pw, String prefix) {
   1033             pw.println(prefix + "mCount=" + mCount
   1034                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
   1035                     + " mUnpluggedCount=" + mUnpluggedCount);
   1036             pw.println(prefix + "mTotalTime=" + mTotalTime
   1037                     + " mLoadedTime=" + mLoadedTime);
   1038             pw.println(prefix + "mLastTime=" + mLastTime
   1039                     + " mUnpluggedTime=" + mUnpluggedTime);
   1040         }
   1041 
   1042 
   1043         void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
   1044             long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
   1045             out.writeLong(runTime);
   1046             out.writeInt(mCount);
   1047         }
   1048 
   1049         void readSummaryFromParcelLocked(Parcel in) {
   1050             // Multiply by 1000 for backwards compatibility
   1051             mTotalTime = mLoadedTime = in.readLong();
   1052             mLastTime = 0;
   1053             mUnpluggedTime = mTotalTime;
   1054             mCount = mLoadedCount = in.readInt();
   1055             mLastCount = 0;
   1056             mUnpluggedCount = mCount;
   1057         }
   1058     }
   1059 
   1060     public static final class SamplingTimer extends Timer {
   1061 
   1062         /**
   1063          * The most recent reported count from /proc/wakelocks.
   1064          */
   1065         int mCurrentReportedCount;
   1066 
   1067         /**
   1068          * The reported count from /proc/wakelocks when unplug() was last
   1069          * called.
   1070          */
   1071         int mUnpluggedReportedCount;
   1072 
   1073         /**
   1074          * The most recent reported total_time from /proc/wakelocks.
   1075          */
   1076         long mCurrentReportedTotalTime;
   1077 
   1078 
   1079         /**
   1080          * The reported total_time from /proc/wakelocks when unplug() was last
   1081          * called.
   1082          */
   1083         long mUnpluggedReportedTotalTime;
   1084 
   1085         /**
   1086          * Whether we are currently in a discharge cycle.
   1087          */
   1088         boolean mTimeBaseRunning;
   1089 
   1090         /**
   1091          * Whether we are currently recording reported values.
   1092          */
   1093         boolean mTrackingReportedValues;
   1094 
   1095         /*
   1096          * A sequence counter, incremented once for each update of the stats.
   1097          */
   1098         int mUpdateVersion;
   1099 
   1100         SamplingTimer(TimeBase timeBase, Parcel in) {
   1101             super(0, timeBase, in);
   1102             mCurrentReportedCount = in.readInt();
   1103             mUnpluggedReportedCount = in.readInt();
   1104             mCurrentReportedTotalTime = in.readLong();
   1105             mUnpluggedReportedTotalTime = in.readLong();
   1106             mTrackingReportedValues = in.readInt() == 1;
   1107             mTimeBaseRunning = timeBase.isRunning();
   1108         }
   1109 
   1110         SamplingTimer(TimeBase timeBase, boolean trackReportedValues) {
   1111             super(0, timeBase);
   1112             mTrackingReportedValues = trackReportedValues;
   1113             mTimeBaseRunning = timeBase.isRunning();
   1114         }
   1115 
   1116         public void setStale() {
   1117             mTrackingReportedValues = false;
   1118             mUnpluggedReportedTotalTime = 0;
   1119             mUnpluggedReportedCount = 0;
   1120         }
   1121 
   1122         public void setUpdateVersion(int version) {
   1123             mUpdateVersion = version;
   1124         }
   1125 
   1126         public int getUpdateVersion() {
   1127             return mUpdateVersion;
   1128         }
   1129 
   1130         public void updateCurrentReportedCount(int count) {
   1131             if (mTimeBaseRunning && mUnpluggedReportedCount == 0) {
   1132                 // Updating the reported value for the first time.
   1133                 mUnpluggedReportedCount = count;
   1134                 // If we are receiving an update update mTrackingReportedValues;
   1135                 mTrackingReportedValues = true;
   1136             }
   1137             mCurrentReportedCount = count;
   1138         }
   1139 
   1140         public void addCurrentReportedCount(int delta) {
   1141             updateCurrentReportedCount(mCurrentReportedCount + delta);
   1142         }
   1143 
   1144         public void updateCurrentReportedTotalTime(long totalTime) {
   1145             if (mTimeBaseRunning && mUnpluggedReportedTotalTime == 0) {
   1146                 // Updating the reported value for the first time.
   1147                 mUnpluggedReportedTotalTime = totalTime;
   1148                 // If we are receiving an update update mTrackingReportedValues;
   1149                 mTrackingReportedValues = true;
   1150             }
   1151             mCurrentReportedTotalTime = totalTime;
   1152         }
   1153 
   1154         public void addCurrentReportedTotalTime(long delta) {
   1155             updateCurrentReportedTotalTime(mCurrentReportedTotalTime + delta);
   1156         }
   1157 
   1158         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1159             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
   1160             if (mTrackingReportedValues) {
   1161                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
   1162                 mUnpluggedReportedCount = mCurrentReportedCount;
   1163             }
   1164             mTimeBaseRunning = true;
   1165         }
   1166 
   1167         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1168             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
   1169             mTimeBaseRunning = false;
   1170         }
   1171 
   1172         public void logState(Printer pw, String prefix) {
   1173             super.logState(pw, prefix);
   1174             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
   1175                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
   1176                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
   1177                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
   1178         }
   1179 
   1180         protected long computeRunTimeLocked(long curBatteryRealtime) {
   1181             return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
   1182                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
   1183         }
   1184 
   1185         protected int computeCurrentCountLocked() {
   1186             return mCount + (mTimeBaseRunning && mTrackingReportedValues
   1187                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
   1188         }
   1189 
   1190         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   1191             super.writeToParcel(out, elapsedRealtimeUs);
   1192             out.writeInt(mCurrentReportedCount);
   1193             out.writeInt(mUnpluggedReportedCount);
   1194             out.writeLong(mCurrentReportedTotalTime);
   1195             out.writeLong(mUnpluggedReportedTotalTime);
   1196             out.writeInt(mTrackingReportedValues ? 1 : 0);
   1197         }
   1198 
   1199         boolean reset(boolean detachIfReset) {
   1200             super.reset(detachIfReset);
   1201             setStale();
   1202             return true;
   1203         }
   1204 
   1205         void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
   1206             super.writeSummaryFromParcelLocked(out, batteryRealtime);
   1207             out.writeLong(mCurrentReportedTotalTime);
   1208             out.writeInt(mCurrentReportedCount);
   1209             out.writeInt(mTrackingReportedValues ? 1 : 0);
   1210         }
   1211 
   1212         void readSummaryFromParcelLocked(Parcel in) {
   1213             super.readSummaryFromParcelLocked(in);
   1214             mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong();
   1215             mUnpluggedReportedCount = mCurrentReportedCount = in.readInt();
   1216             mTrackingReportedValues = in.readInt() == 1;
   1217         }
   1218     }
   1219 
   1220     /**
   1221      * A timer that increments in batches.  It does not run for durations, but just jumps
   1222      * for a pre-determined amount.
   1223      */
   1224     public static final class BatchTimer extends Timer {
   1225         final Uid mUid;
   1226 
   1227         /**
   1228          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
   1229          */
   1230         long mLastAddedTime;
   1231 
   1232         /**
   1233          * The last duration that we added to the timer.  This is in microseconds.
   1234          */
   1235         long mLastAddedDuration;
   1236 
   1237         /**
   1238          * Whether we are currently in a discharge cycle.
   1239          */
   1240         boolean mInDischarge;
   1241 
   1242         BatchTimer(Uid uid, int type, TimeBase timeBase, Parcel in) {
   1243             super(type, timeBase, in);
   1244             mUid = uid;
   1245             mLastAddedTime = in.readLong();
   1246             mLastAddedDuration = in.readLong();
   1247             mInDischarge = timeBase.isRunning();
   1248         }
   1249 
   1250         BatchTimer(Uid uid, int type, TimeBase timeBase) {
   1251             super(type, timeBase);
   1252             mUid = uid;
   1253             mInDischarge = timeBase.isRunning();
   1254         }
   1255 
   1256         @Override
   1257         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   1258             super.writeToParcel(out, elapsedRealtimeUs);
   1259             out.writeLong(mLastAddedTime);
   1260             out.writeLong(mLastAddedDuration);
   1261         }
   1262 
   1263         @Override
   1264         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1265             recomputeLastDuration(SystemClock.elapsedRealtime() * 1000, false);
   1266             mInDischarge = false;
   1267             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
   1268         }
   1269 
   1270         @Override
   1271         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1272             recomputeLastDuration(elapsedRealtime, false);
   1273             mInDischarge = true;
   1274             // If we are still within the last added duration, then re-added whatever remains.
   1275             if (mLastAddedTime == elapsedRealtime) {
   1276                 mTotalTime += mLastAddedDuration;
   1277             }
   1278             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
   1279         }
   1280 
   1281         @Override
   1282         public void logState(Printer pw, String prefix) {
   1283             super.logState(pw, prefix);
   1284             pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
   1285                     + " mLastAddedDuration=" + mLastAddedDuration);
   1286         }
   1287 
   1288         private long computeOverage(long curTime) {
   1289             if (mLastAddedTime > 0) {
   1290                 return mLastTime + mLastAddedDuration - curTime;
   1291             }
   1292             return 0;
   1293         }
   1294 
   1295         private void recomputeLastDuration(long curTime, boolean abort) {
   1296             final long overage = computeOverage(curTime);
   1297             if (overage > 0) {
   1298                 // Aborting before the duration ran out -- roll back the remaining
   1299                 // duration.  Only do this if currently discharging; otherwise we didn't
   1300                 // actually add the time.
   1301                 if (mInDischarge) {
   1302                     mTotalTime -= overage;
   1303                 }
   1304                 if (abort) {
   1305                     mLastAddedTime = 0;
   1306                 } else {
   1307                     mLastAddedTime = curTime;
   1308                     mLastAddedDuration -= overage;
   1309                 }
   1310             }
   1311         }
   1312 
   1313         public void addDuration(BatteryStatsImpl stats, long durationMillis) {
   1314             final long now = SystemClock.elapsedRealtime() * 1000;
   1315             recomputeLastDuration(now, true);
   1316             mLastAddedTime = now;
   1317             mLastAddedDuration = durationMillis * 1000;
   1318             if (mInDischarge) {
   1319                 mTotalTime += mLastAddedDuration;
   1320                 mCount++;
   1321             }
   1322         }
   1323 
   1324         public void abortLastDuration(BatteryStatsImpl stats) {
   1325             final long now = SystemClock.elapsedRealtime() * 1000;
   1326             recomputeLastDuration(now, true);
   1327         }
   1328 
   1329         @Override
   1330         protected int computeCurrentCountLocked() {
   1331             return mCount;
   1332         }
   1333 
   1334         @Override
   1335         protected long computeRunTimeLocked(long curBatteryRealtime) {
   1336             final long overage = computeOverage(SystemClock.elapsedRealtime() * 1000);
   1337             if (overage > 0) {
   1338                 return mTotalTime = overage;
   1339             }
   1340             return mTotalTime;
   1341         }
   1342 
   1343         @Override
   1344         boolean reset(boolean detachIfReset) {
   1345             final long now = SystemClock.elapsedRealtime() * 1000;
   1346             recomputeLastDuration(now, true);
   1347             boolean stillActive = mLastAddedTime == now;
   1348             super.reset(!stillActive && detachIfReset);
   1349             return !stillActive;
   1350         }
   1351     }
   1352 
   1353     /**
   1354      * State for keeping track of timing information.
   1355      */
   1356     public static final class StopwatchTimer extends Timer {
   1357         final Uid mUid;
   1358         final ArrayList<StopwatchTimer> mTimerPool;
   1359 
   1360         int mNesting;
   1361 
   1362         /**
   1363          * The last time at which we updated the timer.  If mNesting is > 0,
   1364          * subtract this from the current battery time to find the amount of
   1365          * time we have been running since we last computed an update.
   1366          */
   1367         long mUpdateTime;
   1368 
   1369         /**
   1370          * The total time at which the timer was acquired, to determine if it
   1371          * was actually held for an interesting duration.
   1372          */
   1373         long mAcquireTime;
   1374 
   1375         long mTimeout;
   1376 
   1377         /**
   1378          * For partial wake locks, keep track of whether we are in the list
   1379          * to consume CPU cycles.
   1380          */
   1381         boolean mInList;
   1382 
   1383         StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   1384                 TimeBase timeBase, Parcel in) {
   1385             super(type, timeBase, in);
   1386             mUid = uid;
   1387             mTimerPool = timerPool;
   1388             mUpdateTime = in.readLong();
   1389         }
   1390 
   1391         StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   1392                 TimeBase timeBase) {
   1393             super(type, timeBase);
   1394             mUid = uid;
   1395             mTimerPool = timerPool;
   1396         }
   1397 
   1398         void setTimeout(long timeout) {
   1399             mTimeout = timeout;
   1400         }
   1401 
   1402         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   1403             super.writeToParcel(out, elapsedRealtimeUs);
   1404             out.writeLong(mUpdateTime);
   1405         }
   1406 
   1407         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1408             if (mNesting > 0) {
   1409                 if (DEBUG && mType < 0) {
   1410                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
   1411                 }
   1412                 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
   1413                 mUpdateTime = baseRealtime;
   1414                 if (DEBUG && mType < 0) {
   1415                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
   1416                 }
   1417             }
   1418         }
   1419 
   1420         public void logState(Printer pw, String prefix) {
   1421             super.logState(pw, prefix);
   1422             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
   1423                     + " mAcquireTime=" + mAcquireTime);
   1424         }
   1425 
   1426         void startRunningLocked(long elapsedRealtimeMs) {
   1427             if (mNesting++ == 0) {
   1428                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
   1429                 mUpdateTime = batteryRealtime;
   1430                 if (mTimerPool != null) {
   1431                     // Accumulate time to all currently active timers before adding
   1432                     // this new one to the pool.
   1433                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
   1434                     // Add this timer to the active pool
   1435                     mTimerPool.add(this);
   1436                 }
   1437                 // Increment the count
   1438                 mCount++;
   1439                 mAcquireTime = mTotalTime;
   1440                 if (DEBUG && mType < 0) {
   1441                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
   1442                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
   1443                             + " mAcquireTime=" + mAcquireTime);
   1444                 }
   1445             }
   1446         }
   1447 
   1448         boolean isRunningLocked() {
   1449             return mNesting > 0;
   1450         }
   1451 
   1452         long checkpointRunningLocked(long elapsedRealtimeMs) {
   1453             if (mNesting > 0) {
   1454                 // We are running...
   1455                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
   1456                 if (mTimerPool != null) {
   1457                     return refreshTimersLocked(batteryRealtime, mTimerPool, this);
   1458                 }
   1459                 final long heldTime = batteryRealtime - mUpdateTime;
   1460                 mUpdateTime = batteryRealtime;
   1461                 mTotalTime += heldTime;
   1462                 return heldTime;
   1463             }
   1464             return 0;
   1465         }
   1466 
   1467         void stopRunningLocked(long elapsedRealtimeMs) {
   1468             // Ignore attempt to stop a timer that isn't running
   1469             if (mNesting == 0) {
   1470                 return;
   1471             }
   1472             if (--mNesting == 0) {
   1473                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
   1474                 if (mTimerPool != null) {
   1475                     // Accumulate time to all active counters, scaled by the total
   1476                     // active in the pool, before taking this one out of the pool.
   1477                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
   1478                     // Remove this timer from the active pool
   1479                     mTimerPool.remove(this);
   1480                 } else {
   1481                     mNesting = 1;
   1482                     mTotalTime = computeRunTimeLocked(batteryRealtime);
   1483                     mNesting = 0;
   1484                 }
   1485 
   1486                 if (DEBUG && mType < 0) {
   1487                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
   1488                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
   1489                             + " mAcquireTime=" + mAcquireTime);
   1490                 }
   1491 
   1492                 if (mTotalTime == mAcquireTime) {
   1493                     // If there was no change in the time, then discard this
   1494                     // count.  A somewhat cheezy strategy, but hey.
   1495                     mCount--;
   1496                 }
   1497             }
   1498         }
   1499 
   1500         void stopAllRunningLocked(long elapsedRealtimeMs) {
   1501             if (mNesting > 0) {
   1502                 mNesting = 1;
   1503                 stopRunningLocked(elapsedRealtimeMs);
   1504             }
   1505         }
   1506 
   1507         // Update the total time for all other running Timers with the same type as this Timer
   1508         // due to a change in timer count
   1509         private static long refreshTimersLocked(long batteryRealtime,
   1510                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
   1511             long selfTime = 0;
   1512             final int N = pool.size();
   1513             for (int i=N-1; i>= 0; i--) {
   1514                 final StopwatchTimer t = pool.get(i);
   1515                 long heldTime = batteryRealtime - t.mUpdateTime;
   1516                 if (heldTime > 0) {
   1517                     final long myTime = heldTime / N;
   1518                     if (t == self) {
   1519                         selfTime = myTime;
   1520                     }
   1521                     t.mTotalTime += myTime;
   1522                 }
   1523                 t.mUpdateTime = batteryRealtime;
   1524             }
   1525             return selfTime;
   1526         }
   1527 
   1528         @Override
   1529         protected long computeRunTimeLocked(long curBatteryRealtime) {
   1530             if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
   1531                 curBatteryRealtime = mUpdateTime + mTimeout;
   1532             }
   1533             return mTotalTime + (mNesting > 0
   1534                     ? (curBatteryRealtime - mUpdateTime)
   1535                             / (mTimerPool != null ? mTimerPool.size() : 1)
   1536                     : 0);
   1537         }
   1538 
   1539         @Override
   1540         protected int computeCurrentCountLocked() {
   1541             return mCount;
   1542         }
   1543 
   1544         boolean reset(boolean detachIfReset) {
   1545             boolean canDetach = mNesting <= 0;
   1546             super.reset(canDetach && detachIfReset);
   1547             if (mNesting > 0) {
   1548                 mUpdateTime = mTimeBase.getRealtime(SystemClock.elapsedRealtime() * 1000);
   1549             }
   1550             mAcquireTime = mTotalTime;
   1551             return canDetach;
   1552         }
   1553 
   1554         void detach() {
   1555             super.detach();
   1556             if (mTimerPool != null) {
   1557                 mTimerPool.remove(this);
   1558             }
   1559         }
   1560 
   1561         void readSummaryFromParcelLocked(Parcel in) {
   1562             super.readSummaryFromParcelLocked(in);
   1563             mNesting = 0;
   1564         }
   1565     }
   1566 
   1567     public abstract class OverflowArrayMap<T> {
   1568         private static final String OVERFLOW_NAME = "*overflow*";
   1569 
   1570         final ArrayMap<String, T> mMap = new ArrayMap<>();
   1571         T mCurOverflow;
   1572         ArrayMap<String, MutableInt> mActiveOverflow;
   1573 
   1574         public OverflowArrayMap() {
   1575         }
   1576 
   1577         public ArrayMap<String, T> getMap() {
   1578             return mMap;
   1579         }
   1580 
   1581         public void clear() {
   1582             mMap.clear();
   1583             mCurOverflow = null;
   1584             mActiveOverflow = null;
   1585         }
   1586 
   1587         public void add(String name, T obj) {
   1588             mMap.put(name, obj);
   1589             if (OVERFLOW_NAME.equals(name)) {
   1590                 mCurOverflow = obj;
   1591             }
   1592         }
   1593 
   1594         public void cleanup() {
   1595             if (mActiveOverflow != null) {
   1596                 if (mActiveOverflow.size() == 0) {
   1597                     mActiveOverflow = null;
   1598                 }
   1599             }
   1600             if (mActiveOverflow == null) {
   1601                 // There is no currently active overflow, so we should no longer have
   1602                 // an overflow entry.
   1603                 if (mMap.containsKey(OVERFLOW_NAME)) {
   1604                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
   1605                             + mMap.get(OVERFLOW_NAME));
   1606                     mMap.remove(OVERFLOW_NAME);
   1607                 }
   1608                 mCurOverflow = null;
   1609             } else {
   1610                 // There is currently active overflow, so we should still have an overflow entry.
   1611                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
   1612                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
   1613                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
   1614                 }
   1615             }
   1616         }
   1617 
   1618         public T startObject(String name) {
   1619             T obj = mMap.get(name);
   1620             if (obj != null) {
   1621                 return obj;
   1622             }
   1623 
   1624             // No object exists for the given name, but do we currently have it
   1625             // running as part of the overflow?
   1626             if (mActiveOverflow != null) {
   1627                 MutableInt over = mActiveOverflow.get(name);
   1628                 if (over != null) {
   1629                     // We are already actively counting this name in the overflow object.
   1630                     obj = mCurOverflow;
   1631                     if (obj == null) {
   1632                         // Shouldn't be here, but we'll try to recover.
   1633                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
   1634                         obj = mCurOverflow = instantiateObject();
   1635                         mMap.put(OVERFLOW_NAME, obj);
   1636                     }
   1637                     over.value++;
   1638                     return obj;
   1639                 }
   1640             }
   1641 
   1642             // No object exists for given name nor in the overflow; we need to make
   1643             // a new one.
   1644             final int N = mMap.size();
   1645             if (N >= MAX_WAKELOCKS_PER_UID) {
   1646                 // Went over the limit on number of objects to track; this one goes
   1647                 // in to the overflow.
   1648                 obj = mCurOverflow;
   1649                 if (obj == null) {
   1650                     // Need to start overflow now...
   1651                     obj = mCurOverflow = instantiateObject();
   1652                     mMap.put(OVERFLOW_NAME, obj);
   1653                 }
   1654                 if (mActiveOverflow == null) {
   1655                     mActiveOverflow = new ArrayMap<>();
   1656                 }
   1657                 mActiveOverflow.put(name, new MutableInt(1));
   1658                 return obj;
   1659             }
   1660 
   1661             // Normal case where we just need to make a new object.
   1662             obj = instantiateObject();
   1663             mMap.put(name, obj);
   1664             return obj;
   1665         }
   1666 
   1667         public T stopObject(String name) {
   1668             T obj = mMap.get(name);
   1669             if (obj != null) {
   1670                 return obj;
   1671             }
   1672 
   1673             // No object exists for the given name, but do we currently have it
   1674             // running as part of the overflow?
   1675             if (mActiveOverflow != null) {
   1676                 MutableInt over = mActiveOverflow.get(name);
   1677                 if (over != null) {
   1678                     // We are already actively counting this name in the overflow object.
   1679                     obj = mCurOverflow;
   1680                     if (obj != null) {
   1681                         over.value--;
   1682                         if (over.value <= 0) {
   1683                             mActiveOverflow.remove(name);
   1684                         }
   1685                         return obj;
   1686                     }
   1687                 }
   1688             }
   1689 
   1690             // Huh, they are stopping an active operation but we can't find one!
   1691             // That's not good.
   1692             Slog.wtf(TAG, "Unable to find object for " + name + " mapsize="
   1693                     + mMap.size() + " activeoverflow=" + mActiveOverflow
   1694                     + " curoverflow=" + mCurOverflow);
   1695             return null;
   1696         }
   1697 
   1698         public abstract T instantiateObject();
   1699     }
   1700 
   1701     /*
   1702      * Get the wakeup reason counter, and create a new one if one
   1703      * doesn't already exist.
   1704      */
   1705     public SamplingTimer getWakeupReasonTimerLocked(String name) {
   1706         SamplingTimer timer = mWakeupReasonStats.get(name);
   1707         if (timer == null) {
   1708             timer = new SamplingTimer(mOnBatteryTimeBase, true);
   1709             mWakeupReasonStats.put(name, timer);
   1710         }
   1711         return timer;
   1712     }
   1713 
   1714     private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
   1715 
   1716         FileInputStream is;
   1717         byte[] buffer = new byte[8192];
   1718         int len;
   1719         boolean wakeup_sources = false;
   1720 
   1721         try {
   1722             try {
   1723                 is = new FileInputStream("/proc/wakelocks");
   1724             } catch (java.io.FileNotFoundException e) {
   1725                 try {
   1726                     is = new FileInputStream("/d/wakeup_sources");
   1727                     wakeup_sources = true;
   1728                 } catch (java.io.FileNotFoundException e2) {
   1729                     return null;
   1730                 }
   1731             }
   1732 
   1733             len = is.read(buffer);
   1734             is.close();
   1735         } catch (java.io.IOException e) {
   1736             return null;
   1737         }
   1738 
   1739         if (len > 0) {
   1740             int i;
   1741             for (i=0; i<len; i++) {
   1742                 if (buffer[i] == '\0') {
   1743                     len = i;
   1744                     break;
   1745                 }
   1746             }
   1747         }
   1748 
   1749         return parseProcWakelocks(buffer, len, wakeup_sources);
   1750     }
   1751 
   1752     private final Map<String, KernelWakelockStats> parseProcWakelocks(
   1753             byte[] wlBuffer, int len, boolean wakeup_sources) {
   1754         String name;
   1755         int count;
   1756         long totalTime;
   1757         int startIndex;
   1758         int endIndex;
   1759         int numUpdatedWlNames = 0;
   1760 
   1761         // Advance past the first line.
   1762         int i;
   1763         for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++);
   1764         startIndex = endIndex = i + 1;
   1765 
   1766         synchronized(this) {
   1767             Map<String, KernelWakelockStats> m = mProcWakelockFileStats;
   1768 
   1769             sKernelWakelockUpdateVersion++;
   1770             while (endIndex < len) {
   1771                 for (endIndex=startIndex;
   1772                         endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
   1773                         endIndex++);
   1774                 endIndex++; // endIndex is an exclusive upper bound.
   1775                 // Don't go over the end of the buffer, Process.parseProcLine might
   1776                 // write to wlBuffer[endIndex]
   1777                 if (endIndex >= (len - 1) ) {
   1778                     return m;
   1779                 }
   1780 
   1781                 String[] nameStringArray = mProcWakelocksName;
   1782                 long[] wlData = mProcWakelocksData;
   1783                 // Stomp out any bad characters since this is from a circular buffer
   1784                 // A corruption is seen sometimes that results in the vm crashing
   1785                 // This should prevent crashes and the line will probably fail to parse
   1786                 for (int j = startIndex; j < endIndex; j++) {
   1787                     if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?';
   1788                 }
   1789                 boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex,
   1790                         wakeup_sources ? WAKEUP_SOURCES_FORMAT :
   1791                                          PROC_WAKELOCKS_FORMAT,
   1792                         nameStringArray, wlData, null);
   1793 
   1794                 name = nameStringArray[0];
   1795                 count = (int) wlData[1];
   1796 
   1797                 if (wakeup_sources) {
   1798                         // convert milliseconds to microseconds
   1799                         totalTime = wlData[2] * 1000;
   1800                 } else {
   1801                         // convert nanoseconds to microseconds with rounding.
   1802                         totalTime = (wlData[2] + 500) / 1000;
   1803                 }
   1804 
   1805                 if (parsed && name.length() > 0) {
   1806                     if (!m.containsKey(name)) {
   1807                         m.put(name, new KernelWakelockStats(count, totalTime,
   1808                                 sKernelWakelockUpdateVersion));
   1809                         numUpdatedWlNames++;
   1810                     } else {
   1811                         KernelWakelockStats kwlStats = m.get(name);
   1812                         if (kwlStats.mVersion == sKernelWakelockUpdateVersion) {
   1813                             kwlStats.mCount += count;
   1814                             kwlStats.mTotalTime += totalTime;
   1815                         } else {
   1816                             kwlStats.mCount = count;
   1817                             kwlStats.mTotalTime = totalTime;
   1818                             kwlStats.mVersion = sKernelWakelockUpdateVersion;
   1819                             numUpdatedWlNames++;
   1820                         }
   1821                     }
   1822                 }
   1823                 startIndex = endIndex;
   1824             }
   1825 
   1826             if (m.size() != numUpdatedWlNames) {
   1827                 // Don't report old data.
   1828                 Iterator<KernelWakelockStats> itr = m.values().iterator();
   1829                 while (itr.hasNext()) {
   1830                     if (itr.next().mVersion != sKernelWakelockUpdateVersion) {
   1831                         itr.remove();
   1832                     }
   1833                 }
   1834             }
   1835             return m;
   1836         }
   1837     }
   1838 
   1839     private class KernelWakelockStats {
   1840         public int mCount;
   1841         public long mTotalTime;
   1842         public int mVersion;
   1843 
   1844         KernelWakelockStats(int count, long totalTime, int version) {
   1845             mCount = count;
   1846             mTotalTime = totalTime;
   1847             mVersion = version;
   1848         }
   1849     }
   1850 
   1851     /*
   1852      * Get the KernelWakelockTimer associated with name, and create a new one if one
   1853      * doesn't already exist.
   1854      */
   1855     public SamplingTimer getKernelWakelockTimerLocked(String name) {
   1856         SamplingTimer kwlt = mKernelWakelockStats.get(name);
   1857         if (kwlt == null) {
   1858             kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, true /* track reported values */);
   1859             mKernelWakelockStats.put(name, kwlt);
   1860         }
   1861         return kwlt;
   1862     }
   1863 
   1864     private int getCurrentBluetoothPingCount() {
   1865         if (mBtHeadset != null) {
   1866             List<BluetoothDevice> deviceList = mBtHeadset.getConnectedDevices();
   1867             if (deviceList.size() > 0) {
   1868                 return mBtHeadset.getBatteryUsageHint(deviceList.get(0));
   1869             }
   1870         }
   1871         return -1;
   1872     }
   1873 
   1874     public int getBluetoothPingCount() {
   1875         if (mBluetoothPingStart == -1) {
   1876             return mBluetoothPingCount;
   1877         } else if (mBtHeadset != null) {
   1878             return getCurrentBluetoothPingCount() - mBluetoothPingStart;
   1879         }
   1880         return 0;
   1881     }
   1882 
   1883     public void setBtHeadset(BluetoothHeadset headset) {
   1884         if (headset != null && mBtHeadset == null && isOnBattery() && mBluetoothPingStart == -1) {
   1885             mBluetoothPingStart = getCurrentBluetoothPingCount();
   1886         }
   1887         mBtHeadset = headset;
   1888     }
   1889 
   1890     private int writeHistoryTag(HistoryTag tag) {
   1891         Integer idxObj = mHistoryTagPool.get(tag);
   1892         int idx;
   1893         if (idxObj != null) {
   1894             idx = idxObj;
   1895         } else {
   1896             idx = mNextHistoryTagIdx;
   1897             HistoryTag key = new HistoryTag();
   1898             key.setTo(tag);
   1899             tag.poolIdx = idx;
   1900             mHistoryTagPool.put(key, idx);
   1901             mNextHistoryTagIdx++;
   1902             mNumHistoryTagChars += key.string.length() + 1;
   1903         }
   1904         return idx;
   1905     }
   1906 
   1907     private void readHistoryTag(int index, HistoryTag tag) {
   1908         tag.string = mReadHistoryStrings[index];
   1909         tag.uid = mReadHistoryUids[index];
   1910         tag.poolIdx = index;
   1911     }
   1912 
   1913     // Part of initial delta int that specifies the time delta.
   1914     static final int DELTA_TIME_MASK = 0x7ffff;
   1915     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
   1916     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
   1917     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
   1918     // Flag in delta int: a new battery level int follows.
   1919     static final int DELTA_BATTERY_LEVEL_FLAG   = 0x00080000;
   1920     // Flag in delta int: a new full state and battery status int follows.
   1921     static final int DELTA_STATE_FLAG           = 0x00100000;
   1922     // Flag in delta int: a new full state2 int follows.
   1923     static final int DELTA_STATE2_FLAG          = 0x00200000;
   1924     // Flag in delta int: contains a wakelock or wakeReason tag.
   1925     static final int DELTA_WAKELOCK_FLAG        = 0x00400000;
   1926     // Flag in delta int: contains an event description.
   1927     static final int DELTA_EVENT_FLAG           = 0x00800000;
   1928     // These upper bits are the frequently changing state bits.
   1929     static final int DELTA_STATE_MASK           = 0xff000000;
   1930 
   1931     // These are the pieces of battery state that are packed in to the upper bits of
   1932     // the state int that have been packed in to the first delta int.  They must fit
   1933     // in DELTA_STATE_MASK.
   1934     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
   1935     static final int STATE_BATTERY_STATUS_SHIFT = 29;
   1936     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
   1937     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
   1938     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
   1939     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
   1940 
   1941     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
   1942         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
   1943             dest.writeInt(DELTA_TIME_ABS);
   1944             cur.writeToParcel(dest, 0);
   1945             return;
   1946         }
   1947 
   1948         final long deltaTime = cur.time - last.time;
   1949         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
   1950         final int lastStateInt = buildStateInt(last);
   1951 
   1952         int deltaTimeToken;
   1953         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
   1954             deltaTimeToken = DELTA_TIME_LONG;
   1955         } else if (deltaTime >= DELTA_TIME_ABS) {
   1956             deltaTimeToken = DELTA_TIME_INT;
   1957         } else {
   1958             deltaTimeToken = (int)deltaTime;
   1959         }
   1960         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
   1961         final int batteryLevelInt = buildBatteryLevelInt(cur);
   1962         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
   1963         if (batteryLevelIntChanged) {
   1964             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
   1965         }
   1966         final int stateInt = buildStateInt(cur);
   1967         final boolean stateIntChanged = stateInt != lastStateInt;
   1968         if (stateIntChanged) {
   1969             firstToken |= DELTA_STATE_FLAG;
   1970         }
   1971         final boolean state2IntChanged = cur.states2 != last.states2;
   1972         if (state2IntChanged) {
   1973             firstToken |= DELTA_STATE2_FLAG;
   1974         }
   1975         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
   1976             firstToken |= DELTA_WAKELOCK_FLAG;
   1977         }
   1978         if (cur.eventCode != HistoryItem.EVENT_NONE) {
   1979             firstToken |= DELTA_EVENT_FLAG;
   1980         }
   1981         dest.writeInt(firstToken);
   1982         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
   1983                 + " deltaTime=" + deltaTime);
   1984 
   1985         if (deltaTimeToken >= DELTA_TIME_INT) {
   1986             if (deltaTimeToken == DELTA_TIME_INT) {
   1987                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
   1988                 dest.writeInt((int)deltaTime);
   1989             } else {
   1990                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
   1991                 dest.writeLong(deltaTime);
   1992             }
   1993         }
   1994         if (batteryLevelIntChanged) {
   1995             dest.writeInt(batteryLevelInt);
   1996             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
   1997                     + Integer.toHexString(batteryLevelInt)
   1998                     + " batteryLevel=" + cur.batteryLevel
   1999                     + " batteryTemp=" + cur.batteryTemperature
   2000                     + " batteryVolt=" + (int)cur.batteryVoltage);
   2001         }
   2002         if (stateIntChanged) {
   2003             dest.writeInt(stateInt);
   2004             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
   2005                     + Integer.toHexString(stateInt)
   2006                     + " batteryStatus=" + cur.batteryStatus
   2007                     + " batteryHealth=" + cur.batteryHealth
   2008                     + " batteryPlugType=" + cur.batteryPlugType
   2009                     + " states=0x" + Integer.toHexString(cur.states));
   2010         }
   2011         if (state2IntChanged) {
   2012             dest.writeInt(cur.states2);
   2013             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
   2014                     + Integer.toHexString(cur.states2));
   2015         }
   2016         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
   2017             int wakeLockIndex;
   2018             int wakeReasonIndex;
   2019             if (cur.wakelockTag != null) {
   2020                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
   2021                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
   2022                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
   2023             } else {
   2024                 wakeLockIndex = 0xffff;
   2025             }
   2026             if (cur.wakeReasonTag != null) {
   2027                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
   2028                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
   2029                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
   2030             } else {
   2031                 wakeReasonIndex = 0xffff;
   2032             }
   2033             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
   2034         }
   2035         if (cur.eventCode != HistoryItem.EVENT_NONE) {
   2036             int index = writeHistoryTag(cur.eventTag);
   2037             int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
   2038             dest.writeInt(codeAndIndex);
   2039             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
   2040                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
   2041                     + cur.eventTag.string);
   2042         }
   2043     }
   2044 
   2045     private int buildBatteryLevelInt(HistoryItem h) {
   2046         return ((((int)h.batteryLevel)<<25)&0xfe000000)
   2047                 | ((((int)h.batteryTemperature)<<14)&0x01ffc000)
   2048                 | (((int)h.batteryVoltage)&0x00003fff);
   2049     }
   2050 
   2051     private int buildStateInt(HistoryItem h) {
   2052         int plugType = 0;
   2053         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
   2054             plugType = 1;
   2055         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
   2056             plugType = 2;
   2057         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
   2058             plugType = 3;
   2059         }
   2060         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
   2061                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
   2062                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
   2063                 | (h.states&(~DELTA_STATE_MASK));
   2064     }
   2065 
   2066     public void readHistoryDelta(Parcel src, HistoryItem cur) {
   2067         int firstToken = src.readInt();
   2068         int deltaTimeToken = firstToken&DELTA_TIME_MASK;
   2069         cur.cmd = HistoryItem.CMD_UPDATE;
   2070         cur.numReadInts = 1;
   2071         if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
   2072                 + " deltaTimeToken=" + deltaTimeToken);
   2073 
   2074         if (deltaTimeToken < DELTA_TIME_ABS) {
   2075             cur.time += deltaTimeToken;
   2076         } else if (deltaTimeToken == DELTA_TIME_ABS) {
   2077             cur.time = src.readLong();
   2078             cur.numReadInts += 2;
   2079             if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
   2080             cur.readFromParcel(src);
   2081             return;
   2082         } else if (deltaTimeToken == DELTA_TIME_INT) {
   2083             int delta = src.readInt();
   2084             cur.time += delta;
   2085             cur.numReadInts += 1;
   2086             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
   2087         } else {
   2088             long delta = src.readLong();
   2089             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
   2090             cur.time += delta;
   2091             cur.numReadInts += 2;
   2092         }
   2093 
   2094         if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
   2095             int batteryLevelInt = src.readInt();
   2096             cur.batteryLevel = (byte)((batteryLevelInt>>25)&0x7f);
   2097             cur.batteryTemperature = (short)((batteryLevelInt<<7)>>21);
   2098             cur.batteryVoltage = (char)(batteryLevelInt&0x3fff);
   2099             cur.numReadInts += 1;
   2100             if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
   2101                     + Integer.toHexString(batteryLevelInt)
   2102                     + " batteryLevel=" + cur.batteryLevel
   2103                     + " batteryTemp=" + cur.batteryTemperature
   2104                     + " batteryVolt=" + (int)cur.batteryVoltage);
   2105         }
   2106 
   2107         if ((firstToken&DELTA_STATE_FLAG) != 0) {
   2108             int stateInt = src.readInt();
   2109             cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~DELTA_STATE_MASK));
   2110             cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
   2111                     & STATE_BATTERY_STATUS_MASK);
   2112             cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
   2113                     & STATE_BATTERY_HEALTH_MASK);
   2114             cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
   2115                     & STATE_BATTERY_PLUG_MASK);
   2116             switch (cur.batteryPlugType) {
   2117                 case 1:
   2118                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
   2119                     break;
   2120                 case 2:
   2121                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
   2122                     break;
   2123                 case 3:
   2124                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
   2125                     break;
   2126             }
   2127             cur.numReadInts += 1;
   2128             if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
   2129                     + Integer.toHexString(stateInt)
   2130                     + " batteryStatus=" + cur.batteryStatus
   2131                     + " batteryHealth=" + cur.batteryHealth
   2132                     + " batteryPlugType=" + cur.batteryPlugType
   2133                     + " states=0x" + Integer.toHexString(cur.states));
   2134         } else {
   2135             cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~DELTA_STATE_MASK));
   2136         }
   2137 
   2138         if ((firstToken&DELTA_STATE2_FLAG) != 0) {
   2139             cur.states2 = src.readInt();
   2140             if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
   2141                     + Integer.toHexString(cur.states2));
   2142         }
   2143 
   2144         if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
   2145             int indexes = src.readInt();
   2146             int wakeLockIndex = indexes&0xffff;
   2147             int wakeReasonIndex = (indexes>>16)&0xffff;
   2148             if (wakeLockIndex != 0xffff) {
   2149                 cur.wakelockTag = cur.localWakelockTag;
   2150                 readHistoryTag(wakeLockIndex, cur.wakelockTag);
   2151                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
   2152                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
   2153             } else {
   2154                 cur.wakelockTag = null;
   2155             }
   2156             if (wakeReasonIndex != 0xffff) {
   2157                 cur.wakeReasonTag = cur.localWakeReasonTag;
   2158                 readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
   2159                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
   2160                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
   2161             } else {
   2162                 cur.wakeReasonTag = null;
   2163             }
   2164             cur.numReadInts += 1;
   2165         } else {
   2166             cur.wakelockTag = null;
   2167             cur.wakeReasonTag = null;
   2168         }
   2169 
   2170         if ((firstToken&DELTA_EVENT_FLAG) != 0) {
   2171             cur.eventTag = cur.localEventTag;
   2172             final int codeAndIndex = src.readInt();
   2173             cur.eventCode = (codeAndIndex&0xffff);
   2174             final int index = ((codeAndIndex>>16)&0xffff);
   2175             readHistoryTag(index, cur.eventTag);
   2176             cur.numReadInts += 1;
   2177             if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
   2178                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
   2179                     + cur.eventTag.string);
   2180         } else {
   2181             cur.eventCode = HistoryItem.EVENT_NONE;
   2182         }
   2183     }
   2184 
   2185     @Override
   2186     public void commitCurrentHistoryBatchLocked() {
   2187         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
   2188     }
   2189 
   2190     void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
   2191         if (!mHaveBatteryLevel || !mRecordingHistory) {
   2192             return;
   2193         }
   2194 
   2195         final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
   2196         final int diffStates = mHistoryLastWritten.states^cur.states;
   2197         final int diffStates2 = mHistoryLastWritten.states2^cur.states2;
   2198         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
   2199         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
   2200         if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
   2201                 + Integer.toHexString(diffStates) + " lastDiff="
   2202                 + Integer.toHexString(lastDiffStates) + " diff2="
   2203                 + Integer.toHexString(diffStates2) + " lastDiff2="
   2204                 + Integer.toHexString(lastDiffStates2));
   2205         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
   2206                 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
   2207                 && (diffStates2&lastDiffStates2) == 0
   2208                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
   2209                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
   2210                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
   2211                         || cur.eventCode == HistoryItem.EVENT_NONE)
   2212                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
   2213                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
   2214                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
   2215                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
   2216                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
   2217                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
   2218             // We can merge this new change in with the last one.  Merging is
   2219             // allowed as long as only the states have changed, and within those states
   2220             // as long as no bit has changed both between now and the last entry, as
   2221             // well as the last entry and the one before it (so we capture any toggles).
   2222             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
   2223             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
   2224             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
   2225             mHistoryBufferLastPos = -1;
   2226             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
   2227             // If the last written history had a wakelock tag, we need to retain it.
   2228             // Note that the condition above made sure that we aren't in a case where
   2229             // both it and the current history item have a wakelock tag.
   2230             if (mHistoryLastWritten.wakelockTag != null) {
   2231                 cur.wakelockTag = cur.localWakelockTag;
   2232                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
   2233             }
   2234             // If the last written history had a wake reason tag, we need to retain it.
   2235             // Note that the condition above made sure that we aren't in a case where
   2236             // both it and the current history item have a wakelock tag.
   2237             if (mHistoryLastWritten.wakeReasonTag != null) {
   2238                 cur.wakeReasonTag = cur.localWakeReasonTag;
   2239                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
   2240             }
   2241             // If the last written history had an event, we need to retain it.
   2242             // Note that the condition above made sure that we aren't in a case where
   2243             // both it and the current history item have an event.
   2244             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
   2245                 cur.eventCode = mHistoryLastWritten.eventCode;
   2246                 cur.eventTag = cur.localEventTag;
   2247                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
   2248             }
   2249             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
   2250         }
   2251 
   2252         final int dataSize = mHistoryBuffer.dataSize();
   2253         if (dataSize >= MAX_HISTORY_BUFFER) {
   2254             if (!mHistoryOverflow) {
   2255                 mHistoryOverflow = true;
   2256                 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
   2257                 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_OVERFLOW, cur);
   2258                 return;
   2259             }
   2260 
   2261             // Once we've reached the maximum number of items, we only
   2262             // record changes to the battery level and the most interesting states.
   2263             // Once we've reached the maximum maximum number of items, we only
   2264             // record changes to the battery level.
   2265             if (mHistoryLastWritten.batteryLevel == cur.batteryLevel &&
   2266                     (dataSize >= MAX_MAX_HISTORY_BUFFER
   2267                             || ((mHistoryLastWritten.states^cur.states)
   2268                                     & HistoryItem.MOST_INTERESTING_STATES) == 0
   2269                             || ((mHistoryLastWritten.states2^cur.states2)
   2270                                     & HistoryItem.MOST_INTERESTING_STATES2) == 0)) {
   2271                 return;
   2272             }
   2273 
   2274             addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
   2275             return;
   2276         }
   2277 
   2278         if (dataSize == 0) {
   2279             // The history is currently empty; we need it to start with a time stamp.
   2280             cur.currentTime = System.currentTimeMillis();
   2281             mLastRecordedClockTime = cur.currentTime;
   2282             mLastRecordedClockRealtime = elapsedRealtimeMs;
   2283             addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_RESET, cur);
   2284         }
   2285         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
   2286     }
   2287 
   2288     private void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd,
   2289             HistoryItem cur) {
   2290         if (mIteratingHistory) {
   2291             throw new IllegalStateException("Can't do this while iterating history!");
   2292         }
   2293         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
   2294         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
   2295         mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
   2296         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
   2297         mLastHistoryElapsedRealtime = elapsedRealtimeMs;
   2298         cur.wakelockTag = null;
   2299         cur.wakeReasonTag = null;
   2300         cur.eventCode = HistoryItem.EVENT_NONE;
   2301         cur.eventTag = null;
   2302         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
   2303                 + " now " + mHistoryBuffer.dataPosition()
   2304                 + " size is now " + mHistoryBuffer.dataSize());
   2305     }
   2306 
   2307     int mChangedStates = 0;
   2308     int mChangedStates2 = 0;
   2309 
   2310     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
   2311         if (mTrackRunningHistoryElapsedRealtime != 0) {
   2312             final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
   2313             final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
   2314             if (diffUptime < (diffElapsed-20)) {
   2315                 final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
   2316                 mHistoryAddTmp.setTo(mHistoryLastWritten);
   2317                 mHistoryAddTmp.wakelockTag = null;
   2318                 mHistoryAddTmp.wakeReasonTag = null;
   2319                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
   2320                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
   2321                 addHistoryRecordInnerLocked(wakeElapsedTime, uptimeMs, mHistoryAddTmp);
   2322             }
   2323         }
   2324         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
   2325         mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
   2326         mTrackRunningHistoryUptime = uptimeMs;
   2327         addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
   2328     }
   2329 
   2330     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
   2331         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
   2332 
   2333         if (!USE_OLD_HISTORY) {
   2334             return;
   2335         }
   2336 
   2337         if (!mHaveBatteryLevel || !mRecordingHistory) {
   2338             return;
   2339         }
   2340 
   2341         // If the current time is basically the same as the last time,
   2342         // and no states have since the last recorded entry changed and
   2343         // are now resetting back to their original value, then just collapse
   2344         // into one record.
   2345         if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
   2346                 && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
   2347                 && ((mHistoryEnd.states^cur.states)&mChangedStates) == 0
   2348                 && ((mHistoryEnd.states2^cur.states2)&mChangedStates2) == 0) {
   2349             // If the current is the same as the one before, then we no
   2350             // longer need the entry.
   2351             if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
   2352                     && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
   2353                     && mHistoryLastEnd.sameNonEvent(cur)) {
   2354                 mHistoryLastEnd.next = null;
   2355                 mHistoryEnd.next = mHistoryCache;
   2356                 mHistoryCache = mHistoryEnd;
   2357                 mHistoryEnd = mHistoryLastEnd;
   2358                 mHistoryLastEnd = null;
   2359             } else {
   2360                 mChangedStates |= mHistoryEnd.states^cur.states;
   2361                 mChangedStates2 |= mHistoryEnd.states^cur.states2;
   2362                 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
   2363             }
   2364             return;
   2365         }
   2366 
   2367         mChangedStates = 0;
   2368         mChangedStates2 = 0;
   2369 
   2370         if (mNumHistoryItems == MAX_HISTORY_ITEMS
   2371                 || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
   2372             addHistoryRecordLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW);
   2373         }
   2374 
   2375         if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
   2376             // Once we've reached the maximum number of items, we only
   2377             // record changes to the battery level and the most interesting states.
   2378             // Once we've reached the maximum maximum number of items, we only
   2379             // record changes to the battery level.
   2380             if (mHistoryEnd != null && mHistoryEnd.batteryLevel
   2381                     == cur.batteryLevel &&
   2382                     (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
   2383                             || ((mHistoryEnd.states^cur.states)
   2384                                     & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
   2385                 return;
   2386             }
   2387         }
   2388 
   2389         addHistoryRecordLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE);
   2390     }
   2391 
   2392     void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
   2393             String name, int uid) {
   2394         mHistoryCur.eventCode = code;
   2395         mHistoryCur.eventTag = mHistoryCur.localEventTag;
   2396         mHistoryCur.eventTag.string = name;
   2397         mHistoryCur.eventTag.uid = uid;
   2398         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
   2399     }
   2400 
   2401     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
   2402         HistoryItem rec = mHistoryCache;
   2403         if (rec != null) {
   2404             mHistoryCache = rec.next;
   2405         } else {
   2406             rec = new HistoryItem();
   2407         }
   2408         rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
   2409 
   2410         addHistoryRecordLocked(rec);
   2411     }
   2412 
   2413     void addHistoryRecordLocked(HistoryItem rec) {
   2414         mNumHistoryItems++;
   2415         rec.next = null;
   2416         mHistoryLastEnd = mHistoryEnd;
   2417         if (mHistoryEnd != null) {
   2418             mHistoryEnd.next = rec;
   2419             mHistoryEnd = rec;
   2420         } else {
   2421             mHistory = mHistoryEnd = rec;
   2422         }
   2423     }
   2424 
   2425     void clearHistoryLocked() {
   2426         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
   2427         if (USE_OLD_HISTORY) {
   2428             if (mHistory != null) {
   2429                 mHistoryEnd.next = mHistoryCache;
   2430                 mHistoryCache = mHistory;
   2431                 mHistory = mHistoryLastEnd = mHistoryEnd = null;
   2432             }
   2433             mNumHistoryItems = 0;
   2434         }
   2435 
   2436         mHistoryBaseTime = 0;
   2437         mLastHistoryElapsedRealtime = 0;
   2438         mTrackRunningHistoryElapsedRealtime = 0;
   2439         mTrackRunningHistoryUptime = 0;
   2440 
   2441         mHistoryBuffer.setDataSize(0);
   2442         mHistoryBuffer.setDataPosition(0);
   2443         mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER / 2);
   2444         mHistoryLastLastWritten.clear();
   2445         mHistoryLastWritten.clear();
   2446         mHistoryTagPool.clear();
   2447         mNextHistoryTagIdx = 0;
   2448         mNumHistoryTagChars = 0;
   2449         mHistoryBufferLastPos = -1;
   2450         mHistoryOverflow = false;
   2451         mLastRecordedClockTime = 0;
   2452         mLastRecordedClockRealtime = 0;
   2453     }
   2454 
   2455     public void updateTimeBasesLocked(boolean unplugged, boolean screenOff, long uptime,
   2456             long realtime) {
   2457         if (mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime)) {
   2458             if (unplugged) {
   2459                 // Track bt headset ping count
   2460                 mBluetoothPingStart = getCurrentBluetoothPingCount();
   2461                 mBluetoothPingCount = 0;
   2462             } else {
   2463                 // Track bt headset ping count
   2464                 mBluetoothPingCount = getBluetoothPingCount();
   2465                 mBluetoothPingStart = -1;
   2466             }
   2467         }
   2468 
   2469         boolean unpluggedScreenOff = unplugged && screenOff;
   2470         if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) {
   2471             updateKernelWakelocksLocked();
   2472             requestWakelockCpuUpdate();
   2473             if (!unpluggedScreenOff) {
   2474                 // We are switching to no longer tracking wake locks, but we want
   2475                 // the next CPU update we receive to take them in to account.
   2476                 mDistributeWakelockCpu = true;
   2477             }
   2478             mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime);
   2479         }
   2480     }
   2481 
   2482     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
   2483         mIsolatedUids.put(isolatedUid, appUid);
   2484     }
   2485 
   2486     public void removeIsolatedUidLocked(int isolatedUid, int appUid) {
   2487         int curUid = mIsolatedUids.get(isolatedUid, -1);
   2488         if (curUid == appUid) {
   2489             mIsolatedUids.delete(isolatedUid);
   2490         }
   2491     }
   2492 
   2493     public int mapUid(int uid) {
   2494         int isolated = mIsolatedUids.get(uid, -1);
   2495         return isolated > 0 ? isolated : uid;
   2496     }
   2497 
   2498     public void noteEventLocked(int code, String name, int uid) {
   2499         uid = mapUid(uid);
   2500         if (!mActiveEvents.updateState(code, name, uid, 0)) {
   2501             return;
   2502         }
   2503         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2504         final long uptime = SystemClock.uptimeMillis();
   2505         addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
   2506     }
   2507 
   2508     public void noteCurrentTimeChangedLocked() {
   2509         final long currentTime = System.currentTimeMillis();
   2510         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2511         final long uptime = SystemClock.uptimeMillis();
   2512         if (isStartClockTimeValid()) {
   2513             // Has the time changed sufficiently that it is really worth recording?
   2514             if (mLastRecordedClockTime != 0) {
   2515                 long expectedClockTime = mLastRecordedClockTime
   2516                         + (elapsedRealtime - mLastRecordedClockRealtime);
   2517                 if (currentTime >= (expectedClockTime-500)
   2518                         && currentTime <= (expectedClockTime+500)) {
   2519                     // Not sufficiently changed, skip!
   2520                     return;
   2521                 }
   2522             }
   2523         }
   2524         recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
   2525         if (isStartClockTimeValid()) {
   2526             mStartClockTime = currentTime;
   2527         }
   2528     }
   2529 
   2530     public void noteProcessStartLocked(String name, int uid) {
   2531         uid = mapUid(uid);
   2532         if (isOnBattery()) {
   2533             Uid u = getUidStatsLocked(uid);
   2534             u.getProcessStatsLocked(name).incStartsLocked();
   2535         }
   2536         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
   2537             return;
   2538         }
   2539         if (!mRecordAllHistory) {
   2540             return;
   2541         }
   2542         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2543         final long uptime = SystemClock.uptimeMillis();
   2544         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
   2545     }
   2546 
   2547     public void noteProcessCrashLocked(String name, int uid) {
   2548         uid = mapUid(uid);
   2549         if (isOnBattery()) {
   2550             Uid u = getUidStatsLocked(uid);
   2551             u.getProcessStatsLocked(name).incNumCrashesLocked();
   2552         }
   2553     }
   2554 
   2555     public void noteProcessAnrLocked(String name, int uid) {
   2556         uid = mapUid(uid);
   2557         if (isOnBattery()) {
   2558             Uid u = getUidStatsLocked(uid);
   2559             u.getProcessStatsLocked(name).incNumAnrsLocked();
   2560         }
   2561     }
   2562 
   2563     public void noteProcessStateLocked(String name, int uid, int state) {
   2564         uid = mapUid(uid);
   2565         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2566         getUidStatsLocked(uid).updateProcessStateLocked(name, state, elapsedRealtime);
   2567     }
   2568 
   2569     public void noteProcessFinishLocked(String name, int uid) {
   2570         uid = mapUid(uid);
   2571         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
   2572             return;
   2573         }
   2574         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2575         final long uptime = SystemClock.uptimeMillis();
   2576         getUidStatsLocked(uid).updateProcessStateLocked(name, Uid.PROCESS_STATE_NONE,
   2577                 elapsedRealtime);
   2578         if (!mRecordAllHistory) {
   2579             return;
   2580         }
   2581         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
   2582     }
   2583 
   2584     public void noteSyncStartLocked(String name, int uid) {
   2585         uid = mapUid(uid);
   2586         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2587         final long uptime = SystemClock.uptimeMillis();
   2588         getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
   2589         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
   2590             return;
   2591         }
   2592         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
   2593     }
   2594 
   2595     public void noteSyncFinishLocked(String name, int uid) {
   2596         uid = mapUid(uid);
   2597         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2598         final long uptime = SystemClock.uptimeMillis();
   2599         getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
   2600         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
   2601             return;
   2602         }
   2603         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
   2604     }
   2605 
   2606     public void noteJobStartLocked(String name, int uid) {
   2607         uid = mapUid(uid);
   2608         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2609         final long uptime = SystemClock.uptimeMillis();
   2610         getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
   2611         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
   2612             return;
   2613         }
   2614         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
   2615     }
   2616 
   2617     public void noteJobFinishLocked(String name, int uid) {
   2618         uid = mapUid(uid);
   2619         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2620         final long uptime = SystemClock.uptimeMillis();
   2621         getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime);
   2622         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
   2623             return;
   2624         }
   2625         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
   2626     }
   2627 
   2628     private void requestWakelockCpuUpdate() {
   2629         if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
   2630             Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
   2631             mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
   2632         }
   2633     }
   2634 
   2635     public void setRecordAllHistoryLocked(boolean enabled) {
   2636         mRecordAllHistory = enabled;
   2637         if (!enabled) {
   2638             // Clear out any existing state.
   2639             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
   2640             // Record the currently running processes as stopping, now that we are no
   2641             // longer tracking them.
   2642             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
   2643                     HistoryItem.EVENT_PROC);
   2644             if (active != null) {
   2645                 long mSecRealtime = SystemClock.elapsedRealtime();
   2646                 final long mSecUptime = SystemClock.uptimeMillis();
   2647                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
   2648                     SparseIntArray uids = ent.getValue();
   2649                     for (int j=0; j<uids.size(); j++) {
   2650                         addHistoryEventLocked(mSecRealtime, mSecUptime,
   2651                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
   2652                     }
   2653                 }
   2654             }
   2655         } else {
   2656             // Record the currently running processes as starting, now that we are tracking them.
   2657             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
   2658                     HistoryItem.EVENT_PROC);
   2659             if (active != null) {
   2660                 long mSecRealtime = SystemClock.elapsedRealtime();
   2661                 final long mSecUptime = SystemClock.uptimeMillis();
   2662                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
   2663                     SparseIntArray uids = ent.getValue();
   2664                     for (int j=0; j<uids.size(); j++) {
   2665                         addHistoryEventLocked(mSecRealtime, mSecUptime,
   2666                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
   2667                     }
   2668                 }
   2669             }
   2670         }
   2671     }
   2672 
   2673     public void setNoAutoReset(boolean enabled) {
   2674         mNoAutoReset = enabled;
   2675     }
   2676 
   2677     private String mInitialAcquireWakeName;
   2678     private int mInitialAcquireWakeUid = -1;
   2679 
   2680     public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type,
   2681             boolean unimportantForLogging, long elapsedRealtime, long uptime) {
   2682         uid = mapUid(uid);
   2683         if (type == WAKE_TYPE_PARTIAL) {
   2684             // Only care about partial wake locks, since full wake locks
   2685             // will be canceled when the user puts the screen to sleep.
   2686             aggregateLastWakeupUptimeLocked(uptime);
   2687             if (historyName == null) {
   2688                 historyName = name;
   2689             }
   2690             if (mRecordAllHistory) {
   2691                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
   2692                         uid, 0)) {
   2693                     addHistoryEventLocked(elapsedRealtime, uptime,
   2694                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
   2695                 }
   2696             }
   2697             if (mWakeLockNesting == 0) {
   2698                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
   2699                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
   2700                         + Integer.toHexString(mHistoryCur.states));
   2701                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
   2702                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
   2703                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
   2704                 mWakeLockImportant = !unimportantForLogging;
   2705                 addHistoryRecordLocked(elapsedRealtime, uptime);
   2706             } else if (!mWakeLockImportant && !unimportantForLogging
   2707                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
   2708                 if (mHistoryLastWritten.wakelockTag != null) {
   2709                     // We'll try to update the last tag.
   2710                     mHistoryLastWritten.wakelockTag = null;
   2711                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
   2712                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
   2713                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
   2714                     addHistoryRecordLocked(elapsedRealtime, uptime);
   2715                 }
   2716                 mWakeLockImportant = true;
   2717             }
   2718             mWakeLockNesting++;
   2719         }
   2720         if (uid >= 0) {
   2721             //if (uid == 0) {
   2722             //    Slog.wtf(TAG, "Acquiring wake lock from root: " + name);
   2723             //}
   2724             requestWakelockCpuUpdate();
   2725             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
   2726         }
   2727     }
   2728 
   2729     public void noteStopWakeLocked(int uid, int pid, String name, String historyName, int type,
   2730             long elapsedRealtime, long uptime) {
   2731         uid = mapUid(uid);
   2732         if (type == WAKE_TYPE_PARTIAL) {
   2733             mWakeLockNesting--;
   2734             if (mRecordAllHistory) {
   2735                 if (historyName == null) {
   2736                     historyName = name;
   2737                 }
   2738                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
   2739                         uid, 0)) {
   2740                     addHistoryEventLocked(elapsedRealtime, uptime,
   2741                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
   2742                 }
   2743             }
   2744             if (mWakeLockNesting == 0) {
   2745                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
   2746                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
   2747                         + Integer.toHexString(mHistoryCur.states));
   2748                 mInitialAcquireWakeName = null;
   2749                 mInitialAcquireWakeUid = -1;
   2750                 addHistoryRecordLocked(elapsedRealtime, uptime);
   2751             }
   2752         }
   2753         if (uid >= 0) {
   2754             requestWakelockCpuUpdate();
   2755             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
   2756         }
   2757     }
   2758 
   2759     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
   2760             String historyName, int type, boolean unimportantForLogging) {
   2761         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2762         final long uptime = SystemClock.uptimeMillis();
   2763         final int N = ws.size();
   2764         for (int i=0; i<N; i++) {
   2765             noteStartWakeLocked(ws.get(i), pid, name, historyName, type, unimportantForLogging,
   2766                     elapsedRealtime, uptime);
   2767         }
   2768     }
   2769 
   2770     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
   2771             String historyName, int type, WorkSource newWs, int newPid, String newName,
   2772             String newHistoryName, int newType, boolean newUnimportantForLogging) {
   2773         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2774         final long uptime = SystemClock.uptimeMillis();
   2775         // For correct semantics, we start the need worksources first, so that we won't
   2776         // make inappropriate history items as if all wake locks went away and new ones
   2777         // appeared.  This is okay because tracking of wake locks allows nesting.
   2778         final int NN = newWs.size();
   2779         for (int i=0; i<NN; i++) {
   2780             noteStartWakeLocked(newWs.get(i), newPid, newName, newHistoryName, newType,
   2781                     newUnimportantForLogging, elapsedRealtime, uptime);
   2782         }
   2783         final int NO = ws.size();
   2784         for (int i=0; i<NO; i++) {
   2785             noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
   2786         }
   2787     }
   2788 
   2789     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
   2790             String historyName, int type) {
   2791         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2792         final long uptime = SystemClock.uptimeMillis();
   2793         final int N = ws.size();
   2794         for (int i=0; i<N; i++) {
   2795             noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
   2796         }
   2797     }
   2798 
   2799     void aggregateLastWakeupUptimeLocked(long uptimeMs) {
   2800         if (mLastWakeupReason != null) {
   2801             long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
   2802             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
   2803             timer.addCurrentReportedCount(1);
   2804             timer.addCurrentReportedTotalTime(deltaUptime * 1000); // time is in microseconds
   2805             mLastWakeupReason = null;
   2806         }
   2807     }
   2808 
   2809     public void noteWakeupReasonLocked(String reason) {
   2810         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2811         final long uptime = SystemClock.uptimeMillis();
   2812         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
   2813                 + Integer.toHexString(mHistoryCur.states));
   2814         aggregateLastWakeupUptimeLocked(uptime);
   2815         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
   2816         mHistoryCur.wakeReasonTag.string = reason;
   2817         mHistoryCur.wakeReasonTag.uid = 0;
   2818         mLastWakeupReason = reason;
   2819         mLastWakeupUptimeMs = uptime;
   2820         addHistoryRecordLocked(elapsedRealtime, uptime);
   2821     }
   2822 
   2823     public int startAddingCpuLocked() {
   2824         mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
   2825 
   2826         final int N = mPartialTimers.size();
   2827         if (N == 0) {
   2828             mLastPartialTimers.clear();
   2829             mDistributeWakelockCpu = false;
   2830             return 0;
   2831         }
   2832 
   2833         if (!mOnBatteryScreenOffTimeBase.isRunning() && !mDistributeWakelockCpu) {
   2834             return 0;
   2835         }
   2836 
   2837         mDistributeWakelockCpu = false;
   2838 
   2839         // How many timers should consume CPU?  Only want to include ones
   2840         // that have already been in the list.
   2841         for (int i=0; i<N; i++) {
   2842             StopwatchTimer st = mPartialTimers.get(i);
   2843             if (st.mInList) {
   2844                 Uid uid = st.mUid;
   2845                 // We don't include the system UID, because it so often
   2846                 // holds wake locks at one request or another of an app.
   2847                 if (uid != null && uid.mUid != Process.SYSTEM_UID) {
   2848                     return 50;
   2849                 }
   2850             }
   2851         }
   2852 
   2853         return 0;
   2854     }
   2855 
   2856     public void finishAddingCpuLocked(int perc, int utime, int stime, long[] cpuSpeedTimes) {
   2857         final int N = mPartialTimers.size();
   2858         if (perc != 0) {
   2859             int num = 0;
   2860             for (int i=0; i<N; i++) {
   2861                 StopwatchTimer st = mPartialTimers.get(i);
   2862                 if (st.mInList) {
   2863                     Uid uid = st.mUid;
   2864                     // We don't include the system UID, because it so often
   2865                     // holds wake locks at one request or another of an app.
   2866                     if (uid != null && uid.mUid != Process.SYSTEM_UID) {
   2867                         num++;
   2868                     }
   2869                 }
   2870             }
   2871             if (num != 0) {
   2872                 for (int i=0; i<N; i++) {
   2873                     StopwatchTimer st = mPartialTimers.get(i);
   2874                     if (st.mInList) {
   2875                         Uid uid = st.mUid;
   2876                         if (uid != null && uid.mUid != Process.SYSTEM_UID) {
   2877                             int myUTime = utime/num;
   2878                             int mySTime = stime/num;
   2879                             utime -= myUTime;
   2880                             stime -= mySTime;
   2881                             num--;
   2882                             Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
   2883                             proc.addCpuTimeLocked(myUTime, mySTime);
   2884                             proc.addSpeedStepTimes(cpuSpeedTimes);
   2885                         }
   2886                     }
   2887                 }
   2888             }
   2889 
   2890             // Just in case, collect any lost CPU time.
   2891             if (utime != 0 || stime != 0) {
   2892                 Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
   2893                 if (uid != null) {
   2894                     Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
   2895                     proc.addCpuTimeLocked(utime, stime);
   2896                     proc.addSpeedStepTimes(cpuSpeedTimes);
   2897                 }
   2898             }
   2899         }
   2900 
   2901         final int NL = mLastPartialTimers.size();
   2902         boolean diff = N != NL;
   2903         for (int i=0; i<NL && !diff; i++) {
   2904             diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i);
   2905         }
   2906         if (!diff) {
   2907             for (int i=0; i<NL; i++) {
   2908                 mPartialTimers.get(i).mInList = true;
   2909             }
   2910             return;
   2911         }
   2912 
   2913         for (int i=0; i<NL; i++) {
   2914             mLastPartialTimers.get(i).mInList = false;
   2915         }
   2916         mLastPartialTimers.clear();
   2917         for (int i=0; i<N; i++) {
   2918             StopwatchTimer st = mPartialTimers.get(i);
   2919             st.mInList = true;
   2920             mLastPartialTimers.add(st);
   2921         }
   2922     }
   2923 
   2924     public void noteProcessDiedLocked(int uid, int pid) {
   2925         uid = mapUid(uid);
   2926         Uid u = mUidStats.get(uid);
   2927         if (u != null) {
   2928             u.mPids.remove(pid);
   2929         }
   2930     }
   2931 
   2932     public long getProcessWakeTime(int uid, int pid, long realtime) {
   2933         uid = mapUid(uid);
   2934         Uid u = mUidStats.get(uid);
   2935         if (u != null) {
   2936             Uid.Pid p = u.mPids.get(pid);
   2937             if (p != null) {
   2938                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
   2939             }
   2940         }
   2941         return 0;
   2942     }
   2943 
   2944     public void reportExcessiveWakeLocked(int uid, String proc, long overTime, long usedTime) {
   2945         uid = mapUid(uid);
   2946         Uid u = mUidStats.get(uid);
   2947         if (u != null) {
   2948             u.reportExcessiveWakeLocked(proc, overTime, usedTime);
   2949         }
   2950     }
   2951 
   2952     public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
   2953         uid = mapUid(uid);
   2954         Uid u = mUidStats.get(uid);
   2955         if (u != null) {
   2956             u.reportExcessiveCpuLocked(proc, overTime, usedTime);
   2957         }
   2958     }
   2959 
   2960     int mSensorNesting;
   2961 
   2962     public void noteStartSensorLocked(int uid, int sensor) {
   2963         uid = mapUid(uid);
   2964         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2965         final long uptime = SystemClock.uptimeMillis();
   2966         if (mSensorNesting == 0) {
   2967             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
   2968             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
   2969                     + Integer.toHexString(mHistoryCur.states));
   2970             addHistoryRecordLocked(elapsedRealtime, uptime);
   2971         }
   2972         mSensorNesting++;
   2973         getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
   2974     }
   2975 
   2976     public void noteStopSensorLocked(int uid, int sensor) {
   2977         uid = mapUid(uid);
   2978         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2979         final long uptime = SystemClock.uptimeMillis();
   2980         mSensorNesting--;
   2981         if (mSensorNesting == 0) {
   2982             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
   2983             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
   2984                     + Integer.toHexString(mHistoryCur.states));
   2985             addHistoryRecordLocked(elapsedRealtime, uptime);
   2986         }
   2987         getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
   2988     }
   2989 
   2990     int mGpsNesting;
   2991 
   2992     public void noteStartGpsLocked(int uid) {
   2993         uid = mapUid(uid);
   2994         final long elapsedRealtime = SystemClock.elapsedRealtime();
   2995         final long uptime = SystemClock.uptimeMillis();
   2996         if (mGpsNesting == 0) {
   2997             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
   2998             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
   2999                     + Integer.toHexString(mHistoryCur.states));
   3000             addHistoryRecordLocked(elapsedRealtime, uptime);
   3001         }
   3002         mGpsNesting++;
   3003         getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
   3004     }
   3005 
   3006     public void noteStopGpsLocked(int uid) {
   3007         uid = mapUid(uid);
   3008         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3009         final long uptime = SystemClock.uptimeMillis();
   3010         mGpsNesting--;
   3011         if (mGpsNesting == 0) {
   3012             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
   3013             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
   3014                     + Integer.toHexString(mHistoryCur.states));
   3015             addHistoryRecordLocked(elapsedRealtime, uptime);
   3016         }
   3017         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
   3018     }
   3019 
   3020     public void noteScreenStateLocked(int state) {
   3021         if (mScreenState != state) {
   3022             final int oldState = mScreenState;
   3023             mScreenState = state;
   3024             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
   3025                     + ", newState=" + Display.stateToString(state));
   3026 
   3027             if (state != Display.STATE_UNKNOWN) {
   3028                 int stepState = state-1;
   3029                 if (stepState < 4) {
   3030                     mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
   3031                     mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
   3032                 } else {
   3033                     Slog.wtf(TAG, "Unexpected screen state: " + state);
   3034                 }
   3035             }
   3036 
   3037             if (state == Display.STATE_ON) {
   3038                 // Screen turning on.
   3039                 final long elapsedRealtime = SystemClock.elapsedRealtime();
   3040                 final long uptime = SystemClock.uptimeMillis();
   3041                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
   3042                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
   3043                         + Integer.toHexString(mHistoryCur.states));
   3044                 addHistoryRecordLocked(elapsedRealtime, uptime);
   3045                 mScreenOnTimer.startRunningLocked(elapsedRealtime);
   3046                 if (mScreenBrightnessBin >= 0) {
   3047                     mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
   3048                 }
   3049 
   3050                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
   3051                         SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
   3052 
   3053                 // Fake a wake lock, so we consider the device waked as long
   3054                 // as the screen is on.
   3055                 noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
   3056                         elapsedRealtime, uptime);
   3057 
   3058                 // Update discharge amounts.
   3059                 if (mOnBatteryInternal) {
   3060                     updateDischargeScreenLevelsLocked(false, true);
   3061                 }
   3062             } else if (oldState == Display.STATE_ON) {
   3063                 // Screen turning off or dozing.
   3064                 final long elapsedRealtime = SystemClock.elapsedRealtime();
   3065                 final long uptime = SystemClock.uptimeMillis();
   3066                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
   3067                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
   3068                         + Integer.toHexString(mHistoryCur.states));
   3069                 addHistoryRecordLocked(elapsedRealtime, uptime);
   3070                 mScreenOnTimer.stopRunningLocked(elapsedRealtime);
   3071                 if (mScreenBrightnessBin >= 0) {
   3072                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
   3073                 }
   3074 
   3075                 noteStopWakeLocked(-1, -1, "screen", "screen", WAKE_TYPE_PARTIAL,
   3076                         elapsedRealtime, uptime);
   3077 
   3078                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
   3079                         SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
   3080 
   3081                 // Update discharge amounts.
   3082                 if (mOnBatteryInternal) {
   3083                     updateDischargeScreenLevelsLocked(true, false);
   3084                 }
   3085             }
   3086         }
   3087     }
   3088 
   3089     public void noteScreenBrightnessLocked(int brightness) {
   3090         // Bin the brightness.
   3091         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
   3092         if (bin < 0) bin = 0;
   3093         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
   3094         if (mScreenBrightnessBin != bin) {
   3095             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3096             final long uptime = SystemClock.uptimeMillis();
   3097             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
   3098                     | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
   3099             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
   3100                     + Integer.toHexString(mHistoryCur.states));
   3101             addHistoryRecordLocked(elapsedRealtime, uptime);
   3102             if (mScreenState == Display.STATE_ON) {
   3103                 if (mScreenBrightnessBin >= 0) {
   3104                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
   3105                 }
   3106                 mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
   3107             }
   3108             mScreenBrightnessBin = bin;
   3109         }
   3110     }
   3111 
   3112     public void noteUserActivityLocked(int uid, int event) {
   3113         if (mOnBatteryInternal) {
   3114             uid = mapUid(uid);
   3115             getUidStatsLocked(uid).noteUserActivityLocked(event);
   3116         }
   3117     }
   3118 
   3119     public void noteInteractiveLocked(boolean interactive) {
   3120         if (mInteractive != interactive) {
   3121             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3122             mInteractive = interactive;
   3123             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
   3124             if (interactive) {
   3125                 mInteractiveTimer.startRunningLocked(elapsedRealtime);
   3126             } else {
   3127                 mInteractiveTimer.stopRunningLocked(elapsedRealtime);
   3128             }
   3129         }
   3130     }
   3131 
   3132     public void noteConnectivityChangedLocked(int type, String extra) {
   3133         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3134         final long uptime = SystemClock.uptimeMillis();
   3135         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
   3136                 extra, type);
   3137         mNumConnectivityChange++;
   3138     }
   3139 
   3140     public void noteMobileRadioPowerState(int powerState, long timestampNs) {
   3141         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3142         final long uptime = SystemClock.uptimeMillis();
   3143         if (mMobileRadioPowerState != powerState) {
   3144             long realElapsedRealtimeMs;
   3145             final boolean active =
   3146                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
   3147                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
   3148             if (active) {
   3149                 mMobileRadioActiveStartTime = realElapsedRealtimeMs = elapsedRealtime;
   3150                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
   3151             } else {
   3152                 realElapsedRealtimeMs = timestampNs / (1000*1000);
   3153                 long lastUpdateTimeMs = mMobileRadioActiveStartTime;
   3154                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
   3155                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
   3156                             + " is before start time " + lastUpdateTimeMs);
   3157                     realElapsedRealtimeMs = elapsedRealtime;
   3158                 } else if (realElapsedRealtimeMs < elapsedRealtime) {
   3159                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
   3160                             - realElapsedRealtimeMs);
   3161                 }
   3162                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
   3163             }
   3164             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
   3165                     + Integer.toHexString(mHistoryCur.states));
   3166             addHistoryRecordLocked(elapsedRealtime, uptime);
   3167             mMobileRadioPowerState = powerState;
   3168             if (active) {
   3169                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
   3170                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
   3171             } else {
   3172                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
   3173                 updateNetworkActivityLocked(NET_UPDATE_MOBILE, realElapsedRealtimeMs);
   3174                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
   3175             }
   3176         }
   3177     }
   3178 
   3179     public void noteLowPowerMode(boolean enabled) {
   3180         if (mLowPowerModeEnabled != enabled) {
   3181             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
   3182             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
   3183             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
   3184             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3185             final long uptime = SystemClock.uptimeMillis();
   3186             mLowPowerModeEnabled = enabled;
   3187             if (enabled) {
   3188                 mHistoryCur.states2 |= HistoryItem.STATE2_LOW_POWER_FLAG;
   3189                 if (DEBUG_HISTORY) Slog.v(TAG, "Low power mode enabled to: "
   3190                         + Integer.toHexString(mHistoryCur.states2));
   3191                 mLowPowerModeEnabledTimer.startRunningLocked(elapsedRealtime);
   3192             } else {
   3193                 mHistoryCur.states2 &= ~HistoryItem.STATE2_LOW_POWER_FLAG;
   3194                 if (DEBUG_HISTORY) Slog.v(TAG, "Low power mode disabled to: "
   3195                         + Integer.toHexString(mHistoryCur.states2));
   3196                 mLowPowerModeEnabledTimer.stopRunningLocked(elapsedRealtime);
   3197             }
   3198             addHistoryRecordLocked(elapsedRealtime, uptime);
   3199         }
   3200     }
   3201 
   3202     public void notePhoneOnLocked() {
   3203         if (!mPhoneOn) {
   3204             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3205             final long uptime = SystemClock.uptimeMillis();
   3206             mHistoryCur.states |= HistoryItem.STATE_PHONE_IN_CALL_FLAG;
   3207             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
   3208                     + Integer.toHexString(mHistoryCur.states));
   3209             addHistoryRecordLocked(elapsedRealtime, uptime);
   3210             mPhoneOn = true;
   3211             mPhoneOnTimer.startRunningLocked(elapsedRealtime);
   3212         }
   3213     }
   3214 
   3215     public void notePhoneOffLocked() {
   3216         if (mPhoneOn) {
   3217             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3218             final long uptime = SystemClock.uptimeMillis();
   3219             mHistoryCur.states &= ~HistoryItem.STATE_PHONE_IN_CALL_FLAG;
   3220             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
   3221                     + Integer.toHexString(mHistoryCur.states));
   3222             addHistoryRecordLocked(elapsedRealtime, uptime);
   3223             mPhoneOn = false;
   3224             mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
   3225         }
   3226     }
   3227 
   3228     void stopAllPhoneSignalStrengthTimersLocked(int except) {
   3229         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3230         for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   3231             if (i == except) {
   3232                 continue;
   3233             }
   3234             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
   3235                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
   3236             }
   3237         }
   3238     }
   3239 
   3240     private int fixPhoneServiceState(int state, int signalBin) {
   3241         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
   3242             // In this case we will always be STATE_OUT_OF_SERVICE, so need
   3243             // to infer that we are scanning from other data.
   3244             if (state == ServiceState.STATE_OUT_OF_SERVICE
   3245                     && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
   3246                 state = ServiceState.STATE_IN_SERVICE;
   3247             }
   3248         }
   3249 
   3250         return state;
   3251     }
   3252 
   3253     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
   3254         boolean scanning = false;
   3255         boolean newHistory = false;
   3256 
   3257         mPhoneServiceStateRaw = state;
   3258         mPhoneSimStateRaw = simState;
   3259         mPhoneSignalStrengthBinRaw = strengthBin;
   3260 
   3261         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3262         final long uptime = SystemClock.uptimeMillis();
   3263 
   3264         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
   3265             // In this case we will always be STATE_OUT_OF_SERVICE, so need
   3266             // to infer that we are scanning from other data.
   3267             if (state == ServiceState.STATE_OUT_OF_SERVICE
   3268                     && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
   3269                 state = ServiceState.STATE_IN_SERVICE;
   3270             }
   3271         }
   3272 
   3273         // If the phone is powered off, stop all timers.
   3274         if (state == ServiceState.STATE_POWER_OFF) {
   3275             strengthBin = -1;
   3276 
   3277         // If we are in service, make sure the correct signal string timer is running.
   3278         } else if (state == ServiceState.STATE_IN_SERVICE) {
   3279             // Bin will be changed below.
   3280 
   3281         // If we're out of service, we are in the lowest signal strength
   3282         // bin and have the scanning bit set.
   3283         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
   3284             scanning = true;
   3285             strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
   3286             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
   3287                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
   3288                 newHistory = true;
   3289                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
   3290                         + Integer.toHexString(mHistoryCur.states));
   3291                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
   3292             }
   3293         }
   3294 
   3295         if (!scanning) {
   3296             // If we are no longer scanning, then stop the scanning timer.
   3297             if (mPhoneSignalScanningTimer.isRunningLocked()) {
   3298                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
   3299                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
   3300                         + Integer.toHexString(mHistoryCur.states));
   3301                 newHistory = true;
   3302                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
   3303             }
   3304         }
   3305 
   3306         if (mPhoneServiceState != state) {
   3307             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
   3308                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
   3309             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
   3310                     + Integer.toHexString(mHistoryCur.states));
   3311             newHistory = true;
   3312             mPhoneServiceState = state;
   3313         }
   3314 
   3315         if (mPhoneSignalStrengthBin != strengthBin) {
   3316             if (mPhoneSignalStrengthBin >= 0) {
   3317                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
   3318                         elapsedRealtime);
   3319             }
   3320             if (strengthBin >= 0) {
   3321                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
   3322                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
   3323                 }
   3324                 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
   3325                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
   3326                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
   3327                         + Integer.toHexString(mHistoryCur.states));
   3328                 newHistory = true;
   3329             } else {
   3330                 stopAllPhoneSignalStrengthTimersLocked(-1);
   3331             }
   3332             mPhoneSignalStrengthBin = strengthBin;
   3333         }
   3334 
   3335         if (newHistory) {
   3336             addHistoryRecordLocked(elapsedRealtime, uptime);
   3337         }
   3338     }
   3339 
   3340     /**
   3341      * Telephony stack updates the phone state.
   3342      * @param state phone state from ServiceState.getState()
   3343      */
   3344     public void notePhoneStateLocked(int state, int simState) {
   3345         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
   3346     }
   3347 
   3348     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
   3349         // Bin the strength.
   3350         int bin = signalStrength.getLevel();
   3351         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
   3352     }
   3353 
   3354     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
   3355         int bin = DATA_CONNECTION_NONE;
   3356         if (hasData) {
   3357             switch (dataType) {
   3358                 case TelephonyManager.NETWORK_TYPE_EDGE:
   3359                     bin = DATA_CONNECTION_EDGE;
   3360                     break;
   3361                 case TelephonyManager.NETWORK_TYPE_GPRS:
   3362                     bin = DATA_CONNECTION_GPRS;
   3363                     break;
   3364                 case TelephonyManager.NETWORK_TYPE_UMTS:
   3365                     bin = DATA_CONNECTION_UMTS;
   3366                     break;
   3367                 case TelephonyManager.NETWORK_TYPE_CDMA:
   3368                     bin = DATA_CONNECTION_CDMA;
   3369                     break;
   3370                 case TelephonyManager.NETWORK_TYPE_EVDO_0:
   3371                     bin = DATA_CONNECTION_EVDO_0;
   3372                     break;
   3373                 case TelephonyManager.NETWORK_TYPE_EVDO_A:
   3374                     bin = DATA_CONNECTION_EVDO_A;
   3375                     break;
   3376                 case TelephonyManager.NETWORK_TYPE_1xRTT:
   3377                     bin = DATA_CONNECTION_1xRTT;
   3378                     break;
   3379                 case TelephonyManager.NETWORK_TYPE_HSDPA:
   3380                     bin = DATA_CONNECTION_HSDPA;
   3381                     break;
   3382                 case TelephonyManager.NETWORK_TYPE_HSUPA:
   3383                     bin = DATA_CONNECTION_HSUPA;
   3384                     break;
   3385                 case TelephonyManager.NETWORK_TYPE_HSPA:
   3386                     bin = DATA_CONNECTION_HSPA;
   3387                     break;
   3388                 case TelephonyManager.NETWORK_TYPE_IDEN:
   3389                     bin = DATA_CONNECTION_IDEN;
   3390                     break;
   3391                 case TelephonyManager.NETWORK_TYPE_EVDO_B:
   3392                     bin = DATA_CONNECTION_EVDO_B;
   3393                     break;
   3394                 case TelephonyManager.NETWORK_TYPE_LTE:
   3395                     bin = DATA_CONNECTION_LTE;
   3396                     break;
   3397                 case TelephonyManager.NETWORK_TYPE_EHRPD:
   3398                     bin = DATA_CONNECTION_EHRPD;
   3399                     break;
   3400                 case TelephonyManager.NETWORK_TYPE_HSPAP:
   3401                     bin = DATA_CONNECTION_HSPAP;
   3402                     break;
   3403                 default:
   3404                     bin = DATA_CONNECTION_OTHER;
   3405                     break;
   3406             }
   3407         }
   3408         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
   3409         if (mPhoneDataConnectionType != bin) {
   3410             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3411             final long uptime = SystemClock.uptimeMillis();
   3412             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
   3413                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
   3414             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
   3415                     + Integer.toHexString(mHistoryCur.states));
   3416             addHistoryRecordLocked(elapsedRealtime, uptime);
   3417             if (mPhoneDataConnectionType >= 0) {
   3418                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
   3419                         elapsedRealtime);
   3420             }
   3421             mPhoneDataConnectionType = bin;
   3422             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
   3423         }
   3424     }
   3425 
   3426     public void noteWifiOnLocked() {
   3427         if (!mWifiOn) {
   3428             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3429             final long uptime = SystemClock.uptimeMillis();
   3430             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
   3431             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
   3432                     + Integer.toHexString(mHistoryCur.states));
   3433             addHistoryRecordLocked(elapsedRealtime, uptime);
   3434             mWifiOn = true;
   3435             mWifiOnTimer.startRunningLocked(elapsedRealtime);
   3436         }
   3437     }
   3438 
   3439     public void noteWifiOffLocked() {
   3440         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3441         final long uptime = SystemClock.uptimeMillis();
   3442         if (mWifiOn) {
   3443             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
   3444             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
   3445                     + Integer.toHexString(mHistoryCur.states));
   3446             addHistoryRecordLocked(elapsedRealtime, uptime);
   3447             mWifiOn = false;
   3448             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
   3449         }
   3450     }
   3451 
   3452     public void noteAudioOnLocked(int uid) {
   3453         uid = mapUid(uid);
   3454         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3455         final long uptime = SystemClock.uptimeMillis();
   3456         if (mAudioOnNesting == 0) {
   3457             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
   3458             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
   3459                     + Integer.toHexString(mHistoryCur.states));
   3460             addHistoryRecordLocked(elapsedRealtime, uptime);
   3461             mAudioOnTimer.startRunningLocked(elapsedRealtime);
   3462         }
   3463         mAudioOnNesting++;
   3464         getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
   3465     }
   3466 
   3467     public void noteAudioOffLocked(int uid) {
   3468         if (mAudioOnNesting == 0) {
   3469             return;
   3470         }
   3471         uid = mapUid(uid);
   3472         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3473         final long uptime = SystemClock.uptimeMillis();
   3474         if (--mAudioOnNesting == 0) {
   3475             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
   3476             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
   3477                     + Integer.toHexString(mHistoryCur.states));
   3478             addHistoryRecordLocked(elapsedRealtime, uptime);
   3479             mAudioOnTimer.stopRunningLocked(elapsedRealtime);
   3480         }
   3481         getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
   3482     }
   3483 
   3484     public void noteVideoOnLocked(int uid) {
   3485         uid = mapUid(uid);
   3486         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3487         final long uptime = SystemClock.uptimeMillis();
   3488         if (mVideoOnNesting == 0) {
   3489             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
   3490             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
   3491                     + Integer.toHexString(mHistoryCur.states));
   3492             addHistoryRecordLocked(elapsedRealtime, uptime);
   3493             mVideoOnTimer.startRunningLocked(elapsedRealtime);
   3494         }
   3495         mVideoOnNesting++;
   3496         getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
   3497     }
   3498 
   3499     public void noteVideoOffLocked(int uid) {
   3500         if (mVideoOnNesting == 0) {
   3501             return;
   3502         }
   3503         uid = mapUid(uid);
   3504         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3505         final long uptime = SystemClock.uptimeMillis();
   3506         if (--mVideoOnNesting == 0) {
   3507             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
   3508             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
   3509                     + Integer.toHexString(mHistoryCur.states));
   3510             addHistoryRecordLocked(elapsedRealtime, uptime);
   3511             mVideoOnTimer.stopRunningLocked(elapsedRealtime);
   3512         }
   3513         getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
   3514     }
   3515 
   3516     public void noteResetAudioLocked() {
   3517         if (mAudioOnNesting > 0) {
   3518             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3519             final long uptime = SystemClock.uptimeMillis();
   3520             mAudioOnNesting = 0;
   3521             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
   3522             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
   3523                     + Integer.toHexString(mHistoryCur.states));
   3524             addHistoryRecordLocked(elapsedRealtime, uptime);
   3525             mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
   3526             for (int i=0; i<mUidStats.size(); i++) {
   3527                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   3528                 uid.noteResetAudioLocked(elapsedRealtime);
   3529             }
   3530         }
   3531     }
   3532 
   3533     public void noteResetVideoLocked() {
   3534         if (mVideoOnNesting > 0) {
   3535             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3536             final long uptime = SystemClock.uptimeMillis();
   3537             mAudioOnNesting = 0;
   3538             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
   3539             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
   3540                     + Integer.toHexString(mHistoryCur.states));
   3541             addHistoryRecordLocked(elapsedRealtime, uptime);
   3542             mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
   3543             for (int i=0; i<mUidStats.size(); i++) {
   3544                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   3545                 uid.noteResetVideoLocked(elapsedRealtime);
   3546             }
   3547         }
   3548     }
   3549 
   3550     public void noteActivityResumedLocked(int uid) {
   3551         uid = mapUid(uid);
   3552         getUidStatsLocked(uid).noteActivityResumedLocked(SystemClock.elapsedRealtime());
   3553     }
   3554 
   3555     public void noteActivityPausedLocked(int uid) {
   3556         uid = mapUid(uid);
   3557         getUidStatsLocked(uid).noteActivityPausedLocked(SystemClock.elapsedRealtime());
   3558     }
   3559 
   3560     public void noteVibratorOnLocked(int uid, long durationMillis) {
   3561         uid = mapUid(uid);
   3562         getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
   3563     }
   3564 
   3565     public void noteVibratorOffLocked(int uid) {
   3566         uid = mapUid(uid);
   3567         getUidStatsLocked(uid).noteVibratorOffLocked();
   3568     }
   3569 
   3570     public void noteFlashlightOnLocked() {
   3571         if (!mFlashlightOn) {
   3572             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3573             final long uptime = SystemClock.uptimeMillis();
   3574             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
   3575             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
   3576                     + Integer.toHexString(mHistoryCur.states));
   3577             addHistoryRecordLocked(elapsedRealtime, uptime);
   3578             mFlashlightOn = true;
   3579             mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
   3580         }
   3581     }
   3582 
   3583     public void noteFlashlightOffLocked() {
   3584         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3585         final long uptime = SystemClock.uptimeMillis();
   3586         if (mFlashlightOn) {
   3587             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
   3588             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
   3589                     + Integer.toHexString(mHistoryCur.states));
   3590             addHistoryRecordLocked(elapsedRealtime, uptime);
   3591             mFlashlightOn = false;
   3592             mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
   3593         }
   3594     }
   3595 
   3596     public void noteWifiRunningLocked(WorkSource ws) {
   3597         if (!mGlobalWifiRunning) {
   3598             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3599             final long uptime = SystemClock.uptimeMillis();
   3600             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
   3601             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
   3602                     + Integer.toHexString(mHistoryCur.states));
   3603             addHistoryRecordLocked(elapsedRealtime, uptime);
   3604             mGlobalWifiRunning = true;
   3605             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
   3606             int N = ws.size();
   3607             for (int i=0; i<N; i++) {
   3608                 int uid = mapUid(ws.get(i));
   3609                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
   3610             }
   3611         } else {
   3612             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
   3613         }
   3614     }
   3615 
   3616     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
   3617         if (mGlobalWifiRunning) {
   3618             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3619             int N = oldWs.size();
   3620             for (int i=0; i<N; i++) {
   3621                 int uid = mapUid(oldWs.get(i));
   3622                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
   3623             }
   3624             N = newWs.size();
   3625             for (int i=0; i<N; i++) {
   3626                 int uid = mapUid(newWs.get(i));
   3627                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
   3628             }
   3629         } else {
   3630             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
   3631         }
   3632     }
   3633 
   3634     public void noteWifiStoppedLocked(WorkSource ws) {
   3635         if (mGlobalWifiRunning) {
   3636             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3637             final long uptime = SystemClock.uptimeMillis();
   3638             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
   3639             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
   3640                     + Integer.toHexString(mHistoryCur.states));
   3641             addHistoryRecordLocked(elapsedRealtime, uptime);
   3642             mGlobalWifiRunning = false;
   3643             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
   3644             int N = ws.size();
   3645             for (int i=0; i<N; i++) {
   3646                 int uid = mapUid(ws.get(i));
   3647                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
   3648             }
   3649         } else {
   3650             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
   3651         }
   3652     }
   3653 
   3654     public void noteWifiStateLocked(int wifiState, String accessPoint) {
   3655         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
   3656         if (mWifiState != wifiState) {
   3657             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3658             if (mWifiState >= 0) {
   3659                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
   3660             }
   3661             mWifiState = wifiState;
   3662             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
   3663         }
   3664     }
   3665 
   3666     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
   3667         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
   3668         if (mWifiSupplState != supplState) {
   3669             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3670             final long uptime = SystemClock.uptimeMillis();
   3671             if (mWifiSupplState >= 0) {
   3672                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
   3673             }
   3674             mWifiSupplState = supplState;
   3675             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
   3676             mHistoryCur.states2 =
   3677                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
   3678                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
   3679             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
   3680                     + Integer.toHexString(mHistoryCur.states2));
   3681             addHistoryRecordLocked(elapsedRealtime, uptime);
   3682         }
   3683     }
   3684 
   3685     void stopAllWifiSignalStrengthTimersLocked(int except) {
   3686         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3687         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   3688             if (i == except) {
   3689                 continue;
   3690             }
   3691             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
   3692                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
   3693             }
   3694         }
   3695     }
   3696 
   3697     public void noteWifiRssiChangedLocked(int newRssi) {
   3698         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
   3699         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
   3700         if (mWifiSignalStrengthBin != strengthBin) {
   3701             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3702             final long uptime = SystemClock.uptimeMillis();
   3703             if (mWifiSignalStrengthBin >= 0) {
   3704                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
   3705                         elapsedRealtime);
   3706             }
   3707             if (strengthBin >= 0) {
   3708                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
   3709                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
   3710                 }
   3711                 mHistoryCur.states2 =
   3712                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
   3713                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
   3714                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
   3715                         + Integer.toHexString(mHistoryCur.states2));
   3716                 addHistoryRecordLocked(elapsedRealtime, uptime);
   3717             } else {
   3718                 stopAllWifiSignalStrengthTimersLocked(-1);
   3719             }
   3720             mWifiSignalStrengthBin = strengthBin;
   3721         }
   3722     }
   3723 
   3724     public void noteBluetoothOnLocked() {
   3725         if (!mBluetoothOn) {
   3726             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3727             final long uptime = SystemClock.uptimeMillis();
   3728             mHistoryCur.states |= HistoryItem.STATE_BLUETOOTH_ON_FLAG;
   3729             if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth on to: "
   3730                     + Integer.toHexString(mHistoryCur.states));
   3731             addHistoryRecordLocked(elapsedRealtime, uptime);
   3732             mBluetoothOn = true;
   3733             mBluetoothOnTimer.startRunningLocked(elapsedRealtime);
   3734         }
   3735     }
   3736 
   3737     public void noteBluetoothOffLocked() {
   3738         if (mBluetoothOn) {
   3739             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3740             final long uptime = SystemClock.uptimeMillis();
   3741             mHistoryCur.states &= ~HistoryItem.STATE_BLUETOOTH_ON_FLAG;
   3742             if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth off to: "
   3743                     + Integer.toHexString(mHistoryCur.states));
   3744             addHistoryRecordLocked(elapsedRealtime, uptime);
   3745             mBluetoothOn = false;
   3746             mBluetoothOnTimer.stopRunningLocked(elapsedRealtime);
   3747         }
   3748     }
   3749 
   3750     public void noteBluetoothStateLocked(int bluetoothState) {
   3751         if (DEBUG) Log.i(TAG, "Bluetooth state -> " + bluetoothState);
   3752         if (mBluetoothState != bluetoothState) {
   3753             final long elapsedRealtime = SystemClock.elapsedRealtime();
   3754             if (mBluetoothState >= 0) {
   3755                 mBluetoothStateTimer[mBluetoothState].stopRunningLocked(elapsedRealtime);
   3756             }
   3757             mBluetoothState = bluetoothState;
   3758             mBluetoothStateTimer[bluetoothState].startRunningLocked(elapsedRealtime);
   3759         }
   3760     }
   3761 
   3762     int mWifiFullLockNesting = 0;
   3763 
   3764     public void noteFullWifiLockAcquiredLocked(int uid) {
   3765         uid = mapUid(uid);
   3766         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3767         final long uptime = SystemClock.uptimeMillis();
   3768         if (mWifiFullLockNesting == 0) {
   3769             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
   3770             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
   3771                     + Integer.toHexString(mHistoryCur.states));
   3772             addHistoryRecordLocked(elapsedRealtime, uptime);
   3773         }
   3774         mWifiFullLockNesting++;
   3775         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
   3776     }
   3777 
   3778     public void noteFullWifiLockReleasedLocked(int uid) {
   3779         uid = mapUid(uid);
   3780         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3781         final long uptime = SystemClock.uptimeMillis();
   3782         mWifiFullLockNesting--;
   3783         if (mWifiFullLockNesting == 0) {
   3784             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
   3785             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
   3786                     + Integer.toHexString(mHistoryCur.states));
   3787             addHistoryRecordLocked(elapsedRealtime, uptime);
   3788         }
   3789         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
   3790     }
   3791 
   3792     int mWifiScanNesting = 0;
   3793 
   3794     public void noteWifiScanStartedLocked(int uid) {
   3795         uid = mapUid(uid);
   3796         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3797         final long uptime = SystemClock.uptimeMillis();
   3798         if (mWifiScanNesting == 0) {
   3799             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
   3800             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
   3801                     + Integer.toHexString(mHistoryCur.states));
   3802             addHistoryRecordLocked(elapsedRealtime, uptime);
   3803         }
   3804         mWifiScanNesting++;
   3805         getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
   3806     }
   3807 
   3808     public void noteWifiScanStoppedLocked(int uid) {
   3809         uid = mapUid(uid);
   3810         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3811         final long uptime = SystemClock.uptimeMillis();
   3812         mWifiScanNesting--;
   3813         if (mWifiScanNesting == 0) {
   3814             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
   3815             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
   3816                     + Integer.toHexString(mHistoryCur.states));
   3817             addHistoryRecordLocked(elapsedRealtime, uptime);
   3818         }
   3819         getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
   3820     }
   3821 
   3822     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
   3823         uid = mapUid(uid);
   3824         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3825         getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
   3826     }
   3827 
   3828     public void noteWifiBatchedScanStoppedLocked(int uid) {
   3829         uid = mapUid(uid);
   3830         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3831         getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
   3832     }
   3833 
   3834     int mWifiMulticastNesting = 0;
   3835 
   3836     public void noteWifiMulticastEnabledLocked(int uid) {
   3837         uid = mapUid(uid);
   3838         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3839         final long uptime = SystemClock.uptimeMillis();
   3840         if (mWifiMulticastNesting == 0) {
   3841             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
   3842             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
   3843                     + Integer.toHexString(mHistoryCur.states));
   3844             addHistoryRecordLocked(elapsedRealtime, uptime);
   3845         }
   3846         mWifiMulticastNesting++;
   3847         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
   3848     }
   3849 
   3850     public void noteWifiMulticastDisabledLocked(int uid) {
   3851         uid = mapUid(uid);
   3852         final long elapsedRealtime = SystemClock.elapsedRealtime();
   3853         final long uptime = SystemClock.uptimeMillis();
   3854         mWifiMulticastNesting--;
   3855         if (mWifiMulticastNesting == 0) {
   3856             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
   3857             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
   3858                     + Integer.toHexString(mHistoryCur.states));
   3859             addHistoryRecordLocked(elapsedRealtime, uptime);
   3860         }
   3861         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
   3862     }
   3863 
   3864     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
   3865         int N = ws.size();
   3866         for (int i=0; i<N; i++) {
   3867             noteFullWifiLockAcquiredLocked(ws.get(i));
   3868         }
   3869     }
   3870 
   3871     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
   3872         int N = ws.size();
   3873         for (int i=0; i<N; i++) {
   3874             noteFullWifiLockReleasedLocked(ws.get(i));
   3875         }
   3876     }
   3877 
   3878     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
   3879         int N = ws.size();
   3880         for (int i=0; i<N; i++) {
   3881             noteWifiScanStartedLocked(ws.get(i));
   3882         }
   3883     }
   3884 
   3885     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
   3886         int N = ws.size();
   3887         for (int i=0; i<N; i++) {
   3888             noteWifiScanStoppedLocked(ws.get(i));
   3889         }
   3890     }
   3891 
   3892     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
   3893         int N = ws.size();
   3894         for (int i=0; i<N; i++) {
   3895             noteWifiBatchedScanStartedLocked(ws.get(i), csph);
   3896         }
   3897     }
   3898 
   3899     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
   3900         int N = ws.size();
   3901         for (int i=0; i<N; i++) {
   3902             noteWifiBatchedScanStoppedLocked(ws.get(i));
   3903         }
   3904     }
   3905 
   3906     public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) {
   3907         int N = ws.size();
   3908         for (int i=0; i<N; i++) {
   3909             noteWifiMulticastEnabledLocked(ws.get(i));
   3910         }
   3911     }
   3912 
   3913     public void noteWifiMulticastDisabledFromSourceLocked(WorkSource ws) {
   3914         int N = ws.size();
   3915         for (int i=0; i<N; i++) {
   3916             noteWifiMulticastDisabledLocked(ws.get(i));
   3917         }
   3918     }
   3919 
   3920     private static String[] includeInStringArray(String[] array, String str) {
   3921         if (ArrayUtils.indexOf(array, str) >= 0) {
   3922             return array;
   3923         }
   3924         String[] newArray = new String[array.length+1];
   3925         System.arraycopy(array, 0, newArray, 0, array.length);
   3926         newArray[array.length] = str;
   3927         return newArray;
   3928     }
   3929 
   3930     private static String[] excludeFromStringArray(String[] array, String str) {
   3931         int index = ArrayUtils.indexOf(array, str);
   3932         if (index >= 0) {
   3933             String[] newArray = new String[array.length-1];
   3934             if (index > 0) {
   3935                 System.arraycopy(array, 0, newArray, 0, index);
   3936             }
   3937             if (index < array.length-1) {
   3938                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
   3939             }
   3940             return newArray;
   3941         }
   3942         return array;
   3943     }
   3944 
   3945     public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
   3946         if (TextUtils.isEmpty(iface)) return;
   3947         if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
   3948             mMobileIfaces = includeInStringArray(mMobileIfaces, iface);
   3949             if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces);
   3950         } else {
   3951             mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface);
   3952             if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces);
   3953         }
   3954         if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
   3955             mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
   3956             if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
   3957         } else {
   3958             mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
   3959             if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
   3960         }
   3961     }
   3962 
   3963     public void noteNetworkStatsEnabledLocked() {
   3964         // During device boot, qtaguid isn't enabled until after the inital
   3965         // loading of battery stats. Now that they're enabled, take our initial
   3966         // snapshot for future delta calculation.
   3967         updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
   3968     }
   3969 
   3970     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
   3971         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   3972     }
   3973 
   3974     @Override public int getScreenOnCount(int which) {
   3975         return mScreenOnTimer.getCountLocked(which);
   3976     }
   3977 
   3978     @Override public long getScreenBrightnessTime(int brightnessBin,
   3979             long elapsedRealtimeUs, int which) {
   3980         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
   3981                 elapsedRealtimeUs, which);
   3982     }
   3983 
   3984     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
   3985         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   3986     }
   3987 
   3988     @Override public long getLowPowerModeEnabledTime(long elapsedRealtimeUs, int which) {
   3989         return mLowPowerModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   3990     }
   3991 
   3992     @Override public int getLowPowerModeEnabledCount(int which) {
   3993         return mLowPowerModeEnabledTimer.getCountLocked(which);
   3994     }
   3995 
   3996     @Override public int getNumConnectivityChange(int which) {
   3997         int val = mNumConnectivityChange;
   3998         if (which == STATS_CURRENT) {
   3999             val -= mLoadedNumConnectivityChange;
   4000         } else if (which == STATS_SINCE_UNPLUGGED) {
   4001             val -= mUnpluggedNumConnectivityChange;
   4002         }
   4003         return val;
   4004     }
   4005 
   4006     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
   4007         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4008     }
   4009 
   4010     @Override public int getPhoneOnCount(int which) {
   4011         return mPhoneOnTimer.getCountLocked(which);
   4012     }
   4013 
   4014     @Override public long getPhoneSignalStrengthTime(int strengthBin,
   4015             long elapsedRealtimeUs, int which) {
   4016         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
   4017                 elapsedRealtimeUs, which);
   4018     }
   4019 
   4020     @Override public long getPhoneSignalScanningTime(
   4021             long elapsedRealtimeUs, int which) {
   4022         return mPhoneSignalScanningTimer.getTotalTimeLocked(
   4023                 elapsedRealtimeUs, which);
   4024     }
   4025 
   4026     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
   4027         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
   4028     }
   4029 
   4030     @Override public long getPhoneDataConnectionTime(int dataType,
   4031             long elapsedRealtimeUs, int which) {
   4032         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
   4033                 elapsedRealtimeUs, which);
   4034     }
   4035 
   4036     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
   4037         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
   4038     }
   4039 
   4040     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
   4041         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4042     }
   4043 
   4044     @Override public int getMobileRadioActiveCount(int which) {
   4045         return mMobileRadioActiveTimer.getCountLocked(which);
   4046     }
   4047 
   4048     @Override public long getMobileRadioActiveAdjustedTime(int which) {
   4049         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
   4050     }
   4051 
   4052     @Override public long getMobileRadioActiveUnknownTime(int which) {
   4053         return mMobileRadioActiveUnknownTime.getCountLocked(which);
   4054     }
   4055 
   4056     @Override public int getMobileRadioActiveUnknownCount(int which) {
   4057         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
   4058     }
   4059 
   4060     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
   4061         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4062     }
   4063 
   4064     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
   4065         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4066     }
   4067 
   4068     @Override public long getWifiStateTime(int wifiState,
   4069             long elapsedRealtimeUs, int which) {
   4070         return mWifiStateTimer[wifiState].getTotalTimeLocked(
   4071                 elapsedRealtimeUs, which);
   4072     }
   4073 
   4074     @Override public int getWifiStateCount(int wifiState, int which) {
   4075         return mWifiStateTimer[wifiState].getCountLocked(which);
   4076     }
   4077 
   4078     @Override public long getWifiSupplStateTime(int state,
   4079             long elapsedRealtimeUs, int which) {
   4080         return mWifiSupplStateTimer[state].getTotalTimeLocked(
   4081                 elapsedRealtimeUs, which);
   4082     }
   4083 
   4084     @Override public int getWifiSupplStateCount(int state, int which) {
   4085         return mWifiSupplStateTimer[state].getCountLocked(which);
   4086     }
   4087 
   4088     @Override public long getWifiSignalStrengthTime(int strengthBin,
   4089             long elapsedRealtimeUs, int which) {
   4090         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
   4091                 elapsedRealtimeUs, which);
   4092     }
   4093 
   4094     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
   4095         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
   4096     }
   4097 
   4098     @Override public long getBluetoothOnTime(long elapsedRealtimeUs, int which) {
   4099         return mBluetoothOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4100     }
   4101 
   4102     @Override public long getBluetoothStateTime(int bluetoothState,
   4103             long elapsedRealtimeUs, int which) {
   4104         return mBluetoothStateTimer[bluetoothState].getTotalTimeLocked(
   4105                 elapsedRealtimeUs, which);
   4106     }
   4107 
   4108     @Override public int getBluetoothStateCount(int bluetoothState, int which) {
   4109         return mBluetoothStateTimer[bluetoothState].getCountLocked(which);
   4110     }
   4111 
   4112     @Override public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
   4113         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4114     }
   4115 
   4116     @Override public long getFlashlightOnCount(int which) {
   4117         return mFlashlightOnTimer.getCountLocked(which);
   4118     }
   4119 
   4120     @Override
   4121     public long getNetworkActivityBytes(int type, int which) {
   4122         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
   4123             return mNetworkByteActivityCounters[type].getCountLocked(which);
   4124         } else {
   4125             return 0;
   4126         }
   4127     }
   4128 
   4129     @Override
   4130     public long getNetworkActivityPackets(int type, int which) {
   4131         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
   4132             return mNetworkPacketActivityCounters[type].getCountLocked(which);
   4133         } else {
   4134             return 0;
   4135         }
   4136     }
   4137 
   4138     boolean isStartClockTimeValid() {
   4139         return mStartClockTime > 365*24*60*60*1000L;
   4140     }
   4141 
   4142     @Override public long getStartClockTime() {
   4143         if (!isStartClockTimeValid()) {
   4144             // If the last clock time we got was very small, then we hadn't had a real
   4145             // time yet, so try to get it again.
   4146             mStartClockTime = System.currentTimeMillis();
   4147             if (isStartClockTimeValid()) {
   4148                 recordCurrentTimeChangeLocked(mStartClockTime, SystemClock.elapsedRealtime(),
   4149                         SystemClock.uptimeMillis());
   4150             }
   4151         }
   4152         return mStartClockTime;
   4153     }
   4154 
   4155     @Override public String getStartPlatformVersion() {
   4156         return mStartPlatformVersion;
   4157     }
   4158 
   4159     @Override public String getEndPlatformVersion() {
   4160         return mEndPlatformVersion;
   4161     }
   4162 
   4163     @Override public int getParcelVersion() {
   4164         return VERSION;
   4165     }
   4166 
   4167     @Override public boolean getIsOnBattery() {
   4168         return mOnBattery;
   4169     }
   4170 
   4171     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
   4172         return mUidStats;
   4173     }
   4174 
   4175     /**
   4176      * The statistics associated with a particular uid.
   4177      */
   4178     public final class Uid extends BatteryStats.Uid {
   4179 
   4180         final int mUid;
   4181 
   4182         boolean mWifiRunning;
   4183         StopwatchTimer mWifiRunningTimer;
   4184 
   4185         boolean mFullWifiLockOut;
   4186         StopwatchTimer mFullWifiLockTimer;
   4187 
   4188         boolean mWifiScanStarted;
   4189         StopwatchTimer mWifiScanTimer;
   4190 
   4191         static final int NO_BATCHED_SCAN_STARTED = -1;
   4192         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
   4193         StopwatchTimer[] mWifiBatchedScanTimer;
   4194 
   4195         boolean mWifiMulticastEnabled;
   4196         StopwatchTimer mWifiMulticastTimer;
   4197 
   4198         StopwatchTimer mAudioTurnedOnTimer;
   4199         StopwatchTimer mVideoTurnedOnTimer;
   4200 
   4201         StopwatchTimer mForegroundActivityTimer;
   4202 
   4203         static final int PROCESS_STATE_NONE = NUM_PROCESS_STATE;
   4204         int mProcessState = PROCESS_STATE_NONE;
   4205         StopwatchTimer[] mProcessStateTimer;
   4206 
   4207         BatchTimer mVibratorOnTimer;
   4208 
   4209         Counter[] mUserActivityCounters;
   4210 
   4211         LongSamplingCounter[] mNetworkByteActivityCounters;
   4212         LongSamplingCounter[] mNetworkPacketActivityCounters;
   4213         LongSamplingCounter mMobileRadioActiveTime;
   4214         LongSamplingCounter mMobileRadioActiveCount;
   4215 
   4216         /**
   4217          * The statistics we have collected for this uid's wake locks.
   4218          */
   4219         final OverflowArrayMap<Wakelock> mWakelockStats = new OverflowArrayMap<Wakelock>() {
   4220             @Override public Wakelock instantiateObject() { return new Wakelock(); }
   4221         };
   4222 
   4223         /**
   4224          * The statistics we have collected for this uid's syncs.
   4225          */
   4226         final OverflowArrayMap<StopwatchTimer> mSyncStats = new OverflowArrayMap<StopwatchTimer>() {
   4227             @Override public StopwatchTimer instantiateObject() {
   4228                 return new StopwatchTimer(Uid.this, SYNC, null, mOnBatteryTimeBase);
   4229             }
   4230         };
   4231 
   4232         /**
   4233          * The statistics we have collected for this uid's jobs.
   4234          */
   4235         final OverflowArrayMap<StopwatchTimer> mJobStats = new OverflowArrayMap<StopwatchTimer>() {
   4236             @Override public StopwatchTimer instantiateObject() {
   4237                 return new StopwatchTimer(Uid.this, JOB, null, mOnBatteryTimeBase);
   4238             }
   4239         };
   4240 
   4241         /**
   4242          * The statistics we have collected for this uid's sensor activations.
   4243          */
   4244         final SparseArray<Sensor> mSensorStats = new SparseArray<Sensor>();
   4245 
   4246         /**
   4247          * The statistics we have collected for this uid's processes.
   4248          */
   4249         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<String, Proc>();
   4250 
   4251         /**
   4252          * The statistics we have collected for this uid's processes.
   4253          */
   4254         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<String, Pkg>();
   4255 
   4256         /**
   4257          * The transient wake stats we have collected for this uid's pids.
   4258          */
   4259         final SparseArray<Pid> mPids = new SparseArray<Pid>();
   4260 
   4261         public Uid(int uid) {
   4262             mUid = uid;
   4263             mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
   4264                     mWifiRunningTimers, mOnBatteryTimeBase);
   4265             mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
   4266                     mFullWifiLockTimers, mOnBatteryTimeBase);
   4267             mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
   4268                     mWifiScanTimers, mOnBatteryTimeBase);
   4269             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
   4270             mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
   4271                     mWifiMulticastTimers, mOnBatteryTimeBase);
   4272             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
   4273         }
   4274 
   4275         @Override
   4276         public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
   4277             return mWakelockStats.getMap();
   4278         }
   4279 
   4280         @Override
   4281         public Map<String, ? extends BatteryStats.Timer> getSyncStats() {
   4282             return mSyncStats.getMap();
   4283         }
   4284 
   4285         @Override
   4286         public Map<String, ? extends BatteryStats.Timer> getJobStats() {
   4287             return mJobStats.getMap();
   4288         }
   4289 
   4290         @Override
   4291         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
   4292             return mSensorStats;
   4293         }
   4294 
   4295         @Override
   4296         public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
   4297             return mProcessStats;
   4298         }
   4299 
   4300         @Override
   4301         public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
   4302             return mPackageStats;
   4303         }
   4304 
   4305         @Override
   4306         public int getUid() {
   4307             return mUid;
   4308         }
   4309 
   4310         @Override
   4311         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
   4312             if (!mWifiRunning) {
   4313                 mWifiRunning = true;
   4314                 if (mWifiRunningTimer == null) {
   4315                     mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
   4316                             mWifiRunningTimers, mOnBatteryTimeBase);
   4317                 }
   4318                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
   4319             }
   4320         }
   4321 
   4322         @Override
   4323         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
   4324             if (mWifiRunning) {
   4325                 mWifiRunning = false;
   4326                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
   4327             }
   4328         }
   4329 
   4330         @Override
   4331         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
   4332             if (!mFullWifiLockOut) {
   4333                 mFullWifiLockOut = true;
   4334                 if (mFullWifiLockTimer == null) {
   4335                     mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
   4336                             mFullWifiLockTimers, mOnBatteryTimeBase);
   4337                 }
   4338                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
   4339             }
   4340         }
   4341 
   4342         @Override
   4343         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
   4344             if (mFullWifiLockOut) {
   4345                 mFullWifiLockOut = false;
   4346                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
   4347             }
   4348         }
   4349 
   4350         @Override
   4351         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
   4352             if (!mWifiScanStarted) {
   4353                 mWifiScanStarted = true;
   4354                 if (mWifiScanTimer == null) {
   4355                     mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
   4356                             mWifiScanTimers, mOnBatteryTimeBase);
   4357                 }
   4358                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
   4359             }
   4360         }
   4361 
   4362         @Override
   4363         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
   4364             if (mWifiScanStarted) {
   4365                 mWifiScanStarted = false;
   4366                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
   4367             }
   4368         }
   4369 
   4370         @Override
   4371         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
   4372             int bin = 0;
   4373             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS) {
   4374                 csph = csph >> 3;
   4375                 bin++;
   4376             }
   4377 
   4378             if (mWifiBatchedScanBinStarted == bin) return;
   4379 
   4380             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
   4381                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
   4382                         stopRunningLocked(elapsedRealtimeMs);
   4383             }
   4384             mWifiBatchedScanBinStarted = bin;
   4385             if (mWifiBatchedScanTimer[bin] == null) {
   4386                 makeWifiBatchedScanBin(bin, null);
   4387             }
   4388             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
   4389         }
   4390 
   4391         @Override
   4392         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
   4393             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
   4394                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
   4395                         stopRunningLocked(elapsedRealtimeMs);
   4396                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
   4397             }
   4398         }
   4399 
   4400         @Override
   4401         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
   4402             if (!mWifiMulticastEnabled) {
   4403                 mWifiMulticastEnabled = true;
   4404                 if (mWifiMulticastTimer == null) {
   4405                     mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
   4406                             mWifiMulticastTimers, mOnBatteryTimeBase);
   4407                 }
   4408                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
   4409             }
   4410         }
   4411 
   4412         @Override
   4413         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
   4414             if (mWifiMulticastEnabled) {
   4415                 mWifiMulticastEnabled = false;
   4416                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
   4417             }
   4418         }
   4419 
   4420         public StopwatchTimer createAudioTurnedOnTimerLocked() {
   4421             if (mAudioTurnedOnTimer == null) {
   4422                 mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
   4423                         mAudioTurnedOnTimers, mOnBatteryTimeBase);
   4424             }
   4425             return mAudioTurnedOnTimer;
   4426         }
   4427 
   4428         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
   4429             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
   4430         }
   4431 
   4432         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
   4433             if (mAudioTurnedOnTimer != null) {
   4434                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
   4435             }
   4436         }
   4437 
   4438         public void noteResetAudioLocked(long elapsedRealtimeMs) {
   4439             if (mAudioTurnedOnTimer != null) {
   4440                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
   4441             }
   4442         }
   4443 
   4444         public StopwatchTimer createVideoTurnedOnTimerLocked() {
   4445             if (mVideoTurnedOnTimer == null) {
   4446                 mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
   4447                         mVideoTurnedOnTimers, mOnBatteryTimeBase);
   4448             }
   4449             return mVideoTurnedOnTimer;
   4450         }
   4451 
   4452         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
   4453             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
   4454         }
   4455 
   4456         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
   4457             if (mVideoTurnedOnTimer != null) {
   4458                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
   4459             }
   4460         }
   4461 
   4462         public void noteResetVideoLocked(long elapsedRealtimeMs) {
   4463             if (mVideoTurnedOnTimer != null) {
   4464                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
   4465             }
   4466         }
   4467 
   4468         public StopwatchTimer createForegroundActivityTimerLocked() {
   4469             if (mForegroundActivityTimer == null) {
   4470                 mForegroundActivityTimer = new StopwatchTimer(
   4471                         Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase);
   4472             }
   4473             return mForegroundActivityTimer;
   4474         }
   4475 
   4476         @Override
   4477         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
   4478             // We always start, since we want multiple foreground PIDs to nest
   4479             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
   4480         }
   4481 
   4482         @Override
   4483         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
   4484             if (mForegroundActivityTimer != null) {
   4485                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
   4486             }
   4487         }
   4488 
   4489         void updateUidProcessStateLocked(int state, long elapsedRealtimeMs) {
   4490             if (mProcessState == state) return;
   4491 
   4492             if (mProcessState != PROCESS_STATE_NONE) {
   4493                 mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
   4494             }
   4495             mProcessState = state;
   4496             if (state != PROCESS_STATE_NONE) {
   4497                 if (mProcessStateTimer[state] == null) {
   4498                     makeProcessState(state, null);
   4499                 }
   4500                 mProcessStateTimer[state].startRunningLocked(elapsedRealtimeMs);
   4501             }
   4502         }
   4503 
   4504         public BatchTimer createVibratorOnTimerLocked() {
   4505             if (mVibratorOnTimer == null) {
   4506                 mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase);
   4507             }
   4508             return mVibratorOnTimer;
   4509         }
   4510 
   4511         public void noteVibratorOnLocked(long durationMillis) {
   4512             createVibratorOnTimerLocked().addDuration(BatteryStatsImpl.this, durationMillis);
   4513         }
   4514 
   4515         public void noteVibratorOffLocked() {
   4516             if (mVibratorOnTimer != null) {
   4517                 mVibratorOnTimer.abortLastDuration(BatteryStatsImpl.this);
   4518             }
   4519         }
   4520 
   4521         @Override
   4522         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
   4523             if (mWifiRunningTimer == null) {
   4524                 return 0;
   4525             }
   4526             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4527         }
   4528 
   4529         @Override
   4530         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
   4531             if (mFullWifiLockTimer == null) {
   4532                 return 0;
   4533             }
   4534             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4535         }
   4536 
   4537         @Override
   4538         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
   4539             if (mWifiScanTimer == null) {
   4540                 return 0;
   4541             }
   4542             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4543         }
   4544 
   4545         @Override
   4546         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
   4547             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
   4548             if (mWifiBatchedScanTimer[csphBin] == null) {
   4549                 return 0;
   4550             }
   4551             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
   4552         }
   4553 
   4554         @Override
   4555         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
   4556             if (mWifiMulticastTimer == null) {
   4557                 return 0;
   4558             }
   4559             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4560         }
   4561 
   4562         @Override
   4563         public long getAudioTurnedOnTime(long elapsedRealtimeUs, int which) {
   4564             if (mAudioTurnedOnTimer == null) {
   4565                 return 0;
   4566             }
   4567             return mAudioTurnedOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4568         }
   4569 
   4570         @Override
   4571         public long getVideoTurnedOnTime(long elapsedRealtimeUs, int which) {
   4572             if (mVideoTurnedOnTimer == null) {
   4573                 return 0;
   4574             }
   4575             return mVideoTurnedOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4576         }
   4577 
   4578         @Override
   4579         public Timer getForegroundActivityTimer() {
   4580             return mForegroundActivityTimer;
   4581         }
   4582 
   4583         void makeProcessState(int i, Parcel in) {
   4584             if (i < 0 || i >= NUM_PROCESS_STATE) return;
   4585 
   4586             if (in == null) {
   4587                 mProcessStateTimer[i] = new StopwatchTimer(this, PROCESS_STATE, null,
   4588                         mOnBatteryTimeBase);
   4589             } else {
   4590                 mProcessStateTimer[i] = new StopwatchTimer(this, PROCESS_STATE, null,
   4591                         mOnBatteryTimeBase, in);
   4592             }
   4593         }
   4594 
   4595         @Override
   4596         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
   4597             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
   4598             if (mProcessStateTimer[state] == null) {
   4599                 return 0;
   4600             }
   4601             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
   4602         }
   4603 
   4604         @Override
   4605         public Timer getVibratorOnTimer() {
   4606             return mVibratorOnTimer;
   4607         }
   4608 
   4609         @Override
   4610         public void noteUserActivityLocked(int type) {
   4611             if (mUserActivityCounters == null) {
   4612                 initUserActivityLocked();
   4613             }
   4614             if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
   4615                 mUserActivityCounters[type].stepAtomic();
   4616             } else {
   4617                 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
   4618                         new Throwable());
   4619             }
   4620         }
   4621 
   4622         @Override
   4623         public boolean hasUserActivity() {
   4624             return mUserActivityCounters != null;
   4625         }
   4626 
   4627         @Override
   4628         public int getUserActivityCount(int type, int which) {
   4629             if (mUserActivityCounters == null) {
   4630                 return 0;
   4631             }
   4632             return mUserActivityCounters[type].getCountLocked(which);
   4633         }
   4634 
   4635         void makeWifiBatchedScanBin(int i, Parcel in) {
   4636             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
   4637 
   4638             ArrayList<StopwatchTimer> collected = mWifiBatchedScanTimers.get(i);
   4639             if (collected == null) {
   4640                 collected = new ArrayList<StopwatchTimer>();
   4641                 mWifiBatchedScanTimers.put(i, collected);
   4642             }
   4643             if (in == null) {
   4644                 mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
   4645                         mOnBatteryTimeBase);
   4646             } else {
   4647                 mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
   4648                         mOnBatteryTimeBase, in);
   4649             }
   4650         }
   4651 
   4652 
   4653         void initUserActivityLocked() {
   4654             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
   4655             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   4656                 mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase);
   4657             }
   4658         }
   4659 
   4660         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
   4661             if (mNetworkByteActivityCounters == null) {
   4662                 initNetworkActivityLocked();
   4663             }
   4664             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
   4665                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
   4666                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
   4667             } else {
   4668                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
   4669                         new Throwable());
   4670             }
   4671         }
   4672 
   4673         void noteMobileRadioActiveTimeLocked(long batteryUptime) {
   4674             if (mNetworkByteActivityCounters == null) {
   4675                 initNetworkActivityLocked();
   4676             }
   4677             mMobileRadioActiveTime.addCountLocked(batteryUptime);
   4678             mMobileRadioActiveCount.addCountLocked(1);
   4679         }
   4680 
   4681         @Override
   4682         public boolean hasNetworkActivity() {
   4683             return mNetworkByteActivityCounters != null;
   4684         }
   4685 
   4686         @Override
   4687         public long getNetworkActivityBytes(int type, int which) {
   4688             if (mNetworkByteActivityCounters != null && type >= 0
   4689                     && type < mNetworkByteActivityCounters.length) {
   4690                 return mNetworkByteActivityCounters[type].getCountLocked(which);
   4691             } else {
   4692                 return 0;
   4693             }
   4694         }
   4695 
   4696         @Override
   4697         public long getNetworkActivityPackets(int type, int which) {
   4698             if (mNetworkPacketActivityCounters != null && type >= 0
   4699                     && type < mNetworkPacketActivityCounters.length) {
   4700                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
   4701             } else {
   4702                 return 0;
   4703             }
   4704         }
   4705 
   4706         @Override
   4707         public long getMobileRadioActiveTime(int which) {
   4708             return mMobileRadioActiveTime != null
   4709                     ? mMobileRadioActiveTime.getCountLocked(which) : 0;
   4710         }
   4711 
   4712         @Override
   4713         public int getMobileRadioActiveCount(int which) {
   4714             return mMobileRadioActiveCount != null
   4715                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
   4716         }
   4717 
   4718         void initNetworkActivityLocked() {
   4719             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   4720             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   4721             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   4722                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
   4723                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
   4724             }
   4725             mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase);
   4726             mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase);
   4727         }
   4728 
   4729         /**
   4730          * Clear all stats for this uid.  Returns true if the uid is completely
   4731          * inactive so can be dropped.
   4732          */
   4733         boolean reset() {
   4734             boolean active = false;
   4735 
   4736             if (mWifiRunningTimer != null) {
   4737                 active |= !mWifiRunningTimer.reset(false);
   4738                 active |= mWifiRunning;
   4739             }
   4740             if (mFullWifiLockTimer != null) {
   4741                 active |= !mFullWifiLockTimer.reset(false);
   4742                 active |= mFullWifiLockOut;
   4743             }
   4744             if (mWifiScanTimer != null) {
   4745                 active |= !mWifiScanTimer.reset(false);
   4746                 active |= mWifiScanStarted;
   4747             }
   4748             if (mWifiBatchedScanTimer != null) {
   4749                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   4750                     if (mWifiBatchedScanTimer[i] != null) {
   4751                         active |= !mWifiBatchedScanTimer[i].reset(false);
   4752                     }
   4753                 }
   4754                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
   4755             }
   4756             if (mWifiMulticastTimer != null) {
   4757                 active |= !mWifiMulticastTimer.reset(false);
   4758                 active |= mWifiMulticastEnabled;
   4759             }
   4760             if (mAudioTurnedOnTimer != null) {
   4761                 active |= !mAudioTurnedOnTimer.reset(false);
   4762             }
   4763             if (mVideoTurnedOnTimer != null) {
   4764                 active |= !mVideoTurnedOnTimer.reset(false);
   4765             }
   4766             if (mForegroundActivityTimer != null) {
   4767                 active |= !mForegroundActivityTimer.reset(false);
   4768             }
   4769             if (mProcessStateTimer != null) {
   4770                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
   4771                     if (mProcessStateTimer[i] != null) {
   4772                         active |= !mProcessStateTimer[i].reset(false);
   4773                     }
   4774                 }
   4775                 active |= (mProcessState != PROCESS_STATE_NONE);
   4776             }
   4777             if (mVibratorOnTimer != null) {
   4778                 if (mVibratorOnTimer.reset(false)) {
   4779                     mVibratorOnTimer.detach();
   4780                     mVibratorOnTimer = null;
   4781                 } else {
   4782                     active = true;
   4783                 }
   4784             }
   4785 
   4786             if (mUserActivityCounters != null) {
   4787                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   4788                     mUserActivityCounters[i].reset(false);
   4789                 }
   4790             }
   4791 
   4792             if (mNetworkByteActivityCounters != null) {
   4793                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   4794                     mNetworkByteActivityCounters[i].reset(false);
   4795                     mNetworkPacketActivityCounters[i].reset(false);
   4796                 }
   4797                 mMobileRadioActiveTime.reset(false);
   4798                 mMobileRadioActiveCount.reset(false);
   4799             }
   4800 
   4801             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
   4802             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
   4803                 Wakelock wl = wakeStats.valueAt(iw);
   4804                 if (wl.reset()) {
   4805                     wakeStats.removeAt(iw);
   4806                 } else {
   4807                     active = true;
   4808                 }
   4809             }
   4810             mWakelockStats.cleanup();
   4811             final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
   4812             for (int is=syncStats.size()-1; is>=0; is--) {
   4813                 StopwatchTimer timer = syncStats.valueAt(is);
   4814                 if (timer.reset(false)) {
   4815                     syncStats.removeAt(is);
   4816                     timer.detach();
   4817                 } else {
   4818                     active = true;
   4819                 }
   4820             }
   4821             mSyncStats.cleanup();
   4822             final ArrayMap<String, StopwatchTimer> jobStats = mJobStats.getMap();
   4823             for (int ij=jobStats.size()-1; ij>=0; ij--) {
   4824                 StopwatchTimer timer = jobStats.valueAt(ij);
   4825                 if (timer.reset(false)) {
   4826                     jobStats.removeAt(ij);
   4827                     timer.detach();
   4828                 } else {
   4829                     active = true;
   4830                 }
   4831             }
   4832             mJobStats.cleanup();
   4833             for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
   4834                 Sensor s = mSensorStats.valueAt(ise);
   4835                 if (s.reset()) {
   4836                     mSensorStats.removeAt(ise);
   4837                 } else {
   4838                     active = true;
   4839                 }
   4840             }
   4841             for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
   4842                 Proc proc = mProcessStats.valueAt(ip);
   4843                 if (proc.mProcessState == PROCESS_STATE_NONE) {
   4844                     proc.detach();
   4845                     mProcessStats.removeAt(ip);
   4846                 } else {
   4847                     proc.reset();
   4848                     active = true;
   4849                 }
   4850             }
   4851             if (mPids.size() > 0) {
   4852                 for (int i=mPids.size()-1; i>=0; i--) {
   4853                     Pid pid = mPids.valueAt(i);
   4854                     if (pid.mWakeNesting > 0) {
   4855                         active = true;
   4856                     } else {
   4857                         mPids.removeAt(i);
   4858                     }
   4859                 }
   4860             }
   4861             if (mPackageStats.size() > 0) {
   4862                 Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
   4863                 while (it.hasNext()) {
   4864                     Map.Entry<String, Pkg> pkgEntry = it.next();
   4865                     Pkg p = pkgEntry.getValue();
   4866                     p.detach();
   4867                     if (p.mServiceStats.size() > 0) {
   4868                         Iterator<Map.Entry<String, Pkg.Serv>> it2
   4869                                 = p.mServiceStats.entrySet().iterator();
   4870                         while (it2.hasNext()) {
   4871                             Map.Entry<String, Pkg.Serv> servEntry = it2.next();
   4872                             servEntry.getValue().detach();
   4873                         }
   4874                     }
   4875                 }
   4876                 mPackageStats.clear();
   4877             }
   4878 
   4879             if (!active) {
   4880                 if (mWifiRunningTimer != null) {
   4881                     mWifiRunningTimer.detach();
   4882                 }
   4883                 if (mFullWifiLockTimer != null) {
   4884                     mFullWifiLockTimer.detach();
   4885                 }
   4886                 if (mWifiScanTimer != null) {
   4887                     mWifiScanTimer.detach();
   4888                 }
   4889                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   4890                     if (mWifiBatchedScanTimer[i] != null) {
   4891                         mWifiBatchedScanTimer[i].detach();
   4892                     }
   4893                 }
   4894                 if (mWifiMulticastTimer != null) {
   4895                     mWifiMulticastTimer.detach();
   4896                 }
   4897                 if (mAudioTurnedOnTimer != null) {
   4898                     mAudioTurnedOnTimer.detach();
   4899                     mAudioTurnedOnTimer = null;
   4900                 }
   4901                 if (mVideoTurnedOnTimer != null) {
   4902                     mVideoTurnedOnTimer.detach();
   4903                     mVideoTurnedOnTimer = null;
   4904                 }
   4905                 if (mForegroundActivityTimer != null) {
   4906                     mForegroundActivityTimer.detach();
   4907                     mForegroundActivityTimer = null;
   4908                 }
   4909                 if (mUserActivityCounters != null) {
   4910                     for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   4911                         mUserActivityCounters[i].detach();
   4912                     }
   4913                 }
   4914                 if (mNetworkByteActivityCounters != null) {
   4915                     for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   4916                         mNetworkByteActivityCounters[i].detach();
   4917                         mNetworkPacketActivityCounters[i].detach();
   4918                     }
   4919                 }
   4920                 mPids.clear();
   4921             }
   4922 
   4923             return !active;
   4924         }
   4925 
   4926         void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
   4927             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
   4928             int NW = wakeStats.size();
   4929             out.writeInt(NW);
   4930             for (int iw=0; iw<NW; iw++) {
   4931                 out.writeString(wakeStats.keyAt(iw));
   4932                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
   4933                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
   4934             }
   4935 
   4936             final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
   4937             int NS = syncStats.size();
   4938             out.writeInt(NS);
   4939             for (int is=0; is<NS; is++) {
   4940                 out.writeString(syncStats.keyAt(is));
   4941                 StopwatchTimer timer = syncStats.valueAt(is);
   4942                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
   4943             }
   4944 
   4945             final ArrayMap<String, StopwatchTimer> jobStats = mJobStats.getMap();
   4946             int NJ = jobStats.size();
   4947             out.writeInt(NJ);
   4948             for (int ij=0; ij<NJ; ij++) {
   4949                 out.writeString(jobStats.keyAt(ij));
   4950                 StopwatchTimer timer = jobStats.valueAt(ij);
   4951                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
   4952             }
   4953 
   4954             int NSE = mSensorStats.size();
   4955             out.writeInt(NSE);
   4956             for (int ise=0; ise<NSE; ise++) {
   4957                 out.writeInt(mSensorStats.keyAt(ise));
   4958                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
   4959                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
   4960             }
   4961 
   4962             int NP = mProcessStats.size();
   4963             out.writeInt(NP);
   4964             for (int ip=0; ip<NP; ip++) {
   4965                 out.writeString(mProcessStats.keyAt(ip));
   4966                 Uid.Proc proc = mProcessStats.valueAt(ip);
   4967                 proc.writeToParcelLocked(out);
   4968             }
   4969 
   4970             out.writeInt(mPackageStats.size());
   4971             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
   4972                 out.writeString(pkgEntry.getKey());
   4973                 Uid.Pkg pkg = pkgEntry.getValue();
   4974                 pkg.writeToParcelLocked(out);
   4975             }
   4976 
   4977             if (mWifiRunningTimer != null) {
   4978                 out.writeInt(1);
   4979                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
   4980             } else {
   4981                 out.writeInt(0);
   4982             }
   4983             if (mFullWifiLockTimer != null) {
   4984                 out.writeInt(1);
   4985                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
   4986             } else {
   4987                 out.writeInt(0);
   4988             }
   4989             if (mWifiScanTimer != null) {
   4990                 out.writeInt(1);
   4991                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
   4992             } else {
   4993                 out.writeInt(0);
   4994             }
   4995             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   4996                 if (mWifiBatchedScanTimer[i] != null) {
   4997                     out.writeInt(1);
   4998                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
   4999                 } else {
   5000                     out.writeInt(0);
   5001                 }
   5002             }
   5003             if (mWifiMulticastTimer != null) {
   5004                 out.writeInt(1);
   5005                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
   5006             } else {
   5007                 out.writeInt(0);
   5008             }
   5009             if (mAudioTurnedOnTimer != null) {
   5010                 out.writeInt(1);
   5011                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
   5012             } else {
   5013                 out.writeInt(0);
   5014             }
   5015             if (mVideoTurnedOnTimer != null) {
   5016                 out.writeInt(1);
   5017                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
   5018             } else {
   5019                 out.writeInt(0);
   5020             }
   5021             if (mForegroundActivityTimer != null) {
   5022                 out.writeInt(1);
   5023                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
   5024             } else {
   5025                 out.writeInt(0);
   5026             }
   5027             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
   5028                 if (mProcessStateTimer[i] != null) {
   5029                     out.writeInt(1);
   5030                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
   5031                 } else {
   5032                     out.writeInt(0);
   5033                 }
   5034             }
   5035             if (mVibratorOnTimer != null) {
   5036                 out.writeInt(1);
   5037                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
   5038             } else {
   5039                 out.writeInt(0);
   5040             }
   5041             if (mUserActivityCounters != null) {
   5042                 out.writeInt(1);
   5043                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   5044                     mUserActivityCounters[i].writeToParcel(out);
   5045                 }
   5046             } else {
   5047                 out.writeInt(0);
   5048             }
   5049             if (mNetworkByteActivityCounters != null) {
   5050                 out.writeInt(1);
   5051                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   5052                     mNetworkByteActivityCounters[i].writeToParcel(out);
   5053                     mNetworkPacketActivityCounters[i].writeToParcel(out);
   5054                 }
   5055                 mMobileRadioActiveTime.writeToParcel(out);
   5056                 mMobileRadioActiveCount.writeToParcel(out);
   5057             } else {
   5058                 out.writeInt(0);
   5059             }
   5060         }
   5061 
   5062         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
   5063             int numWakelocks = in.readInt();
   5064             mWakelockStats.clear();
   5065             for (int j = 0; j < numWakelocks; j++) {
   5066                 String wakelockName = in.readString();
   5067                 Uid.Wakelock wakelock = new Wakelock();
   5068                 wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in);
   5069                 mWakelockStats.add(wakelockName, wakelock);
   5070             }
   5071 
   5072             int numSyncs = in.readInt();
   5073             mSyncStats.clear();
   5074             for (int j = 0; j < numSyncs; j++) {
   5075                 String syncName = in.readString();
   5076                 if (in.readInt() != 0) {
   5077                     mSyncStats.add(syncName,
   5078                             new StopwatchTimer(Uid.this, SYNC, null, timeBase, in));
   5079                 }
   5080             }
   5081 
   5082             int numJobs = in.readInt();
   5083             mJobStats.clear();
   5084             for (int j = 0; j < numJobs; j++) {
   5085                 String jobName = in.readString();
   5086                 if (in.readInt() != 0) {
   5087                     mJobStats.add(jobName, new StopwatchTimer(Uid.this, JOB, null, timeBase, in));
   5088                 }
   5089             }
   5090 
   5091             int numSensors = in.readInt();
   5092             mSensorStats.clear();
   5093             for (int k = 0; k < numSensors; k++) {
   5094                 int sensorNumber = in.readInt();
   5095                 Uid.Sensor sensor = new Sensor(sensorNumber);
   5096                 sensor.readFromParcelLocked(mOnBatteryTimeBase, in);
   5097                 mSensorStats.put(sensorNumber, sensor);
   5098             }
   5099 
   5100             int numProcs = in.readInt();
   5101             mProcessStats.clear();
   5102             for (int k = 0; k < numProcs; k++) {
   5103                 String processName = in.readString();
   5104                 Uid.Proc proc = new Proc(processName);
   5105                 proc.readFromParcelLocked(in);
   5106                 mProcessStats.put(processName, proc);
   5107             }
   5108 
   5109             int numPkgs = in.readInt();
   5110             mPackageStats.clear();
   5111             for (int l = 0; l < numPkgs; l++) {
   5112                 String packageName = in.readString();
   5113                 Uid.Pkg pkg = new Pkg();
   5114                 pkg.readFromParcelLocked(in);
   5115                 mPackageStats.put(packageName, pkg);
   5116             }
   5117 
   5118             mWifiRunning = false;
   5119             if (in.readInt() != 0) {
   5120                 mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
   5121                         mWifiRunningTimers, mOnBatteryTimeBase, in);
   5122             } else {
   5123                 mWifiRunningTimer = null;
   5124             }
   5125             mFullWifiLockOut = false;
   5126             if (in.readInt() != 0) {
   5127                 mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
   5128                         mFullWifiLockTimers, mOnBatteryTimeBase, in);
   5129             } else {
   5130                 mFullWifiLockTimer = null;
   5131             }
   5132             mWifiScanStarted = false;
   5133             if (in.readInt() != 0) {
   5134                 mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
   5135                         mWifiScanTimers, mOnBatteryTimeBase, in);
   5136             } else {
   5137                 mWifiScanTimer = null;
   5138             }
   5139             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
   5140             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   5141                 if (in.readInt() != 0) {
   5142                     makeWifiBatchedScanBin(i, in);
   5143                 } else {
   5144                     mWifiBatchedScanTimer[i] = null;
   5145                 }
   5146             }
   5147             mWifiMulticastEnabled = false;
   5148             if (in.readInt() != 0) {
   5149                 mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
   5150                         mWifiMulticastTimers, mOnBatteryTimeBase, in);
   5151             } else {
   5152                 mWifiMulticastTimer = null;
   5153             }
   5154             if (in.readInt() != 0) {
   5155                 mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
   5156                         mAudioTurnedOnTimers, mOnBatteryTimeBase, in);
   5157             } else {
   5158                 mAudioTurnedOnTimer = null;
   5159             }
   5160             if (in.readInt() != 0) {
   5161                 mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
   5162                         mVideoTurnedOnTimers, mOnBatteryTimeBase, in);
   5163             } else {
   5164                 mVideoTurnedOnTimer = null;
   5165             }
   5166             if (in.readInt() != 0) {
   5167                 mForegroundActivityTimer = new StopwatchTimer(
   5168                         Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase, in);
   5169             } else {
   5170                 mForegroundActivityTimer = null;
   5171             }
   5172             mProcessState = PROCESS_STATE_NONE;
   5173             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
   5174                 if (in.readInt() != 0) {
   5175                     makeProcessState(i, in);
   5176                 } else {
   5177                     mProcessStateTimer[i] = null;
   5178                 }
   5179             }
   5180             if (in.readInt() != 0) {
   5181                 mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase, in);
   5182             } else {
   5183                 mVibratorOnTimer = null;
   5184             }
   5185             if (in.readInt() != 0) {
   5186                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
   5187                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   5188                     mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase, in);
   5189                 }
   5190             } else {
   5191                 mUserActivityCounters = null;
   5192             }
   5193             if (in.readInt() != 0) {
   5194                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   5195                 mNetworkPacketActivityCounters
   5196                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   5197                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   5198                     mNetworkByteActivityCounters[i]
   5199                             = new LongSamplingCounter(mOnBatteryTimeBase, in);
   5200                     mNetworkPacketActivityCounters[i]
   5201                             = new LongSamplingCounter(mOnBatteryTimeBase, in);
   5202                 }
   5203                 mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
   5204                 mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
   5205             } else {
   5206                 mNetworkByteActivityCounters = null;
   5207                 mNetworkPacketActivityCounters = null;
   5208             }
   5209         }
   5210 
   5211         /**
   5212          * The statistics associated with a particular wake lock.
   5213          */
   5214         public final class Wakelock extends BatteryStats.Uid.Wakelock {
   5215             /**
   5216              * How long (in ms) this uid has been keeping the device partially awake.
   5217              */
   5218             StopwatchTimer mTimerPartial;
   5219 
   5220             /**
   5221              * How long (in ms) this uid has been keeping the device fully awake.
   5222              */
   5223             StopwatchTimer mTimerFull;
   5224 
   5225             /**
   5226              * How long (in ms) this uid has had a window keeping the device awake.
   5227              */
   5228             StopwatchTimer mTimerWindow;
   5229 
   5230             /**
   5231              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
   5232              * proper timer pool from the given BatteryStatsImpl object.
   5233              *
   5234              * @param in the Parcel to be read from.
   5235              * return a new Timer, or null.
   5236              */
   5237             private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
   5238                     TimeBase timeBase, Parcel in) {
   5239                 if (in.readInt() == 0) {
   5240                     return null;
   5241                 }
   5242 
   5243                 return new StopwatchTimer(Uid.this, type, pool, timeBase, in);
   5244             }
   5245 
   5246             boolean reset() {
   5247                 boolean wlactive = false;
   5248                 if (mTimerFull != null) {
   5249                     wlactive |= !mTimerFull.reset(false);
   5250                 }
   5251                 if (mTimerPartial != null) {
   5252                     wlactive |= !mTimerPartial.reset(false);
   5253                 }
   5254                 if (mTimerWindow != null) {
   5255                     wlactive |= !mTimerWindow.reset(false);
   5256                 }
   5257                 if (!wlactive) {
   5258                     if (mTimerFull != null) {
   5259                         mTimerFull.detach();
   5260                         mTimerFull = null;
   5261                     }
   5262                     if (mTimerPartial != null) {
   5263                         mTimerPartial.detach();
   5264                         mTimerPartial = null;
   5265                     }
   5266                     if (mTimerWindow != null) {
   5267                         mTimerWindow.detach();
   5268                         mTimerWindow = null;
   5269                     }
   5270                 }
   5271                 return !wlactive;
   5272             }
   5273 
   5274             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
   5275                 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
   5276                         mPartialTimers, screenOffTimeBase, in);
   5277                 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL,
   5278                         mFullTimers, timeBase, in);
   5279                 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW,
   5280                         mWindowTimers, timeBase, in);
   5281             }
   5282 
   5283             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
   5284                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
   5285                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
   5286                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
   5287             }
   5288 
   5289             @Override
   5290             public Timer getWakeTime(int type) {
   5291                 switch (type) {
   5292                 case WAKE_TYPE_FULL: return mTimerFull;
   5293                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
   5294                 case WAKE_TYPE_WINDOW: return mTimerWindow;
   5295                 default: throw new IllegalArgumentException("type = " + type);
   5296                 }
   5297             }
   5298 
   5299             public StopwatchTimer getStopwatchTimer(int type) {
   5300                 StopwatchTimer t;
   5301                 switch (type) {
   5302                     case WAKE_TYPE_PARTIAL:
   5303                         t = mTimerPartial;
   5304                         if (t == null) {
   5305                             t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL,
   5306                                     mPartialTimers, mOnBatteryScreenOffTimeBase);
   5307                             mTimerPartial = t;
   5308                         }
   5309                         return t;
   5310                     case WAKE_TYPE_FULL:
   5311                         t = mTimerFull;
   5312                         if (t == null) {
   5313                             t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL,
   5314                                     mFullTimers, mOnBatteryTimeBase);
   5315                             mTimerFull = t;
   5316                         }
   5317                         return t;
   5318                     case WAKE_TYPE_WINDOW:
   5319                         t = mTimerWindow;
   5320                         if (t == null) {
   5321                             t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW,
   5322                                     mWindowTimers, mOnBatteryTimeBase);
   5323                             mTimerWindow = t;
   5324                         }
   5325                         return t;
   5326                     default:
   5327                         throw new IllegalArgumentException("type=" + type);
   5328                 }
   5329             }
   5330         }
   5331 
   5332         public final class Sensor extends BatteryStats.Uid.Sensor {
   5333             final int mHandle;
   5334             StopwatchTimer mTimer;
   5335 
   5336             public Sensor(int handle) {
   5337                 mHandle = handle;
   5338             }
   5339 
   5340             private StopwatchTimer readTimerFromParcel(TimeBase timeBase, Parcel in) {
   5341                 if (in.readInt() == 0) {
   5342                     return null;
   5343                 }
   5344 
   5345                 ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle);
   5346                 if (pool == null) {
   5347                     pool = new ArrayList<StopwatchTimer>();
   5348                     mSensorTimers.put(mHandle, pool);
   5349                 }
   5350                 return new StopwatchTimer(Uid.this, 0, pool, timeBase, in);
   5351             }
   5352 
   5353             boolean reset() {
   5354                 if (mTimer.reset(true)) {
   5355                     mTimer = null;
   5356                     return true;
   5357                 }
   5358                 return false;
   5359             }
   5360 
   5361             void readFromParcelLocked(TimeBase timeBase, Parcel in) {
   5362                 mTimer = readTimerFromParcel(timeBase, in);
   5363             }
   5364 
   5365             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
   5366                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
   5367             }
   5368 
   5369             @Override
   5370             public Timer getSensorTime() {
   5371                 return mTimer;
   5372             }
   5373 
   5374             @Override
   5375             public int getHandle() {
   5376                 return mHandle;
   5377             }
   5378         }
   5379 
   5380         /**
   5381          * The statistics associated with a particular process.
   5382          */
   5383         public final class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
   5384             /**
   5385              * The name of this process.
   5386              */
   5387             final String mName;
   5388 
   5389             /**
   5390              * Remains true until removed from the stats.
   5391              */
   5392             boolean mActive = true;
   5393 
   5394             /**
   5395              * Total time (in 1/100 sec) spent executing in user code.
   5396              */
   5397             long mUserTime;
   5398 
   5399             /**
   5400              * Total time (in 1/100 sec) spent executing in kernel code.
   5401              */
   5402             long mSystemTime;
   5403 
   5404             /**
   5405              * Amount of time the process was running in the foreground.
   5406              */
   5407             long mForegroundTime;
   5408 
   5409             /**
   5410              * Number of times the process has been started.
   5411              */
   5412             int mStarts;
   5413 
   5414             /**
   5415              * Number of times the process has crashed.
   5416              */
   5417             int mNumCrashes;
   5418 
   5419             /**
   5420              * Number of times the process has had an ANR.
   5421              */
   5422             int mNumAnrs;
   5423 
   5424             /**
   5425              * The amount of user time loaded from a previous save.
   5426              */
   5427             long mLoadedUserTime;
   5428 
   5429             /**
   5430              * The amount of system time loaded from a previous save.
   5431              */
   5432             long mLoadedSystemTime;
   5433 
   5434             /**
   5435              * The amount of foreground time loaded from a previous save.
   5436              */
   5437             long mLoadedForegroundTime;
   5438 
   5439             /**
   5440              * The number of times the process has started from a previous save.
   5441              */
   5442             int mLoadedStarts;
   5443 
   5444             /**
   5445              * Number of times the process has crashed from a previous save.
   5446              */
   5447             int mLoadedNumCrashes;
   5448 
   5449             /**
   5450              * Number of times the process has had an ANR from a previous save.
   5451              */
   5452             int mLoadedNumAnrs;
   5453 
   5454             /**
   5455              * The amount of user time when last unplugged.
   5456              */
   5457             long mUnpluggedUserTime;
   5458 
   5459             /**
   5460              * The amount of system time when last unplugged.
   5461              */
   5462             long mUnpluggedSystemTime;
   5463 
   5464             /**
   5465              * The amount of foreground time since unplugged.
   5466              */
   5467             long mUnpluggedForegroundTime;
   5468 
   5469             /**
   5470              * The number of times the process has started before unplugged.
   5471              */
   5472             int mUnpluggedStarts;
   5473 
   5474             /**
   5475              * Number of times the process has crashed before unplugged.
   5476              */
   5477             int mUnpluggedNumCrashes;
   5478 
   5479             /**
   5480              * Number of times the process has had an ANR before unplugged.
   5481              */
   5482             int mUnpluggedNumAnrs;
   5483 
   5484             /**
   5485              * Current process state.
   5486              */
   5487             int mProcessState = PROCESS_STATE_NONE;
   5488 
   5489             SamplingCounter[] mSpeedBins;
   5490 
   5491             ArrayList<ExcessivePower> mExcessivePower;
   5492 
   5493             Proc(String name) {
   5494                 mName = name;
   5495                 mOnBatteryTimeBase.add(this);
   5496                 mSpeedBins = new SamplingCounter[getCpuSpeedSteps()];
   5497             }
   5498 
   5499             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   5500                 mUnpluggedUserTime = mUserTime;
   5501                 mUnpluggedSystemTime = mSystemTime;
   5502                 mUnpluggedForegroundTime = mForegroundTime;
   5503                 mUnpluggedStarts = mStarts;
   5504                 mUnpluggedNumCrashes = mNumCrashes;
   5505                 mUnpluggedNumAnrs = mNumAnrs;
   5506             }
   5507 
   5508             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   5509             }
   5510 
   5511             void reset() {
   5512                 mUserTime = mSystemTime = mForegroundTime = 0;
   5513                 mStarts = mNumCrashes = mNumAnrs = 0;
   5514                 mLoadedUserTime = mLoadedSystemTime = mLoadedForegroundTime = 0;
   5515                 mLoadedStarts = mLoadedNumCrashes = mLoadedNumAnrs = 0;
   5516                 mUnpluggedUserTime = mUnpluggedSystemTime = mUnpluggedForegroundTime = 0;
   5517                 mUnpluggedStarts = mUnpluggedNumCrashes = mUnpluggedNumAnrs = 0;
   5518                 for (int i = 0; i < mSpeedBins.length; i++) {
   5519                     SamplingCounter c = mSpeedBins[i];
   5520                     if (c != null) {
   5521                         c.reset(false);
   5522                     }
   5523                 }
   5524                 mExcessivePower = null;
   5525             }
   5526 
   5527             void detach() {
   5528                 mActive = false;
   5529                 mOnBatteryTimeBase.remove(this);
   5530                 for (int i = 0; i < mSpeedBins.length; i++) {
   5531                     SamplingCounter c = mSpeedBins[i];
   5532                     if (c != null) {
   5533                         mOnBatteryTimeBase.remove(c);
   5534                         mSpeedBins[i] = null;
   5535                     }
   5536                 }
   5537             }
   5538 
   5539             public int countExcessivePowers() {
   5540                 return mExcessivePower != null ? mExcessivePower.size() : 0;
   5541             }
   5542 
   5543             public ExcessivePower getExcessivePower(int i) {
   5544                 if (mExcessivePower != null) {
   5545                     return mExcessivePower.get(i);
   5546                 }
   5547                 return null;
   5548             }
   5549 
   5550             public void addExcessiveWake(long overTime, long usedTime) {
   5551                 if (mExcessivePower == null) {
   5552                     mExcessivePower = new ArrayList<ExcessivePower>();
   5553                 }
   5554                 ExcessivePower ew = new ExcessivePower();
   5555                 ew.type = ExcessivePower.TYPE_WAKE;
   5556                 ew.overTime = overTime;
   5557                 ew.usedTime = usedTime;
   5558                 mExcessivePower.add(ew);
   5559             }
   5560 
   5561             public void addExcessiveCpu(long overTime, long usedTime) {
   5562                 if (mExcessivePower == null) {
   5563                     mExcessivePower = new ArrayList<ExcessivePower>();
   5564                 }
   5565                 ExcessivePower ew = new ExcessivePower();
   5566                 ew.type = ExcessivePower.TYPE_CPU;
   5567                 ew.overTime = overTime;
   5568                 ew.usedTime = usedTime;
   5569                 mExcessivePower.add(ew);
   5570             }
   5571 
   5572             void writeExcessivePowerToParcelLocked(Parcel out) {
   5573                 if (mExcessivePower == null) {
   5574                     out.writeInt(0);
   5575                     return;
   5576                 }
   5577 
   5578                 final int N = mExcessivePower.size();
   5579                 out.writeInt(N);
   5580                 for (int i=0; i<N; i++) {
   5581                     ExcessivePower ew = mExcessivePower.get(i);
   5582                     out.writeInt(ew.type);
   5583                     out.writeLong(ew.overTime);
   5584                     out.writeLong(ew.usedTime);
   5585                 }
   5586             }
   5587 
   5588             boolean readExcessivePowerFromParcelLocked(Parcel in) {
   5589                 final int N = in.readInt();
   5590                 if (N == 0) {
   5591                     mExcessivePower = null;
   5592                     return true;
   5593                 }
   5594 
   5595                 if (N > 10000) {
   5596                     Slog.w(TAG, "File corrupt: too many excessive power entries " + N);
   5597                     return false;
   5598                 }
   5599 
   5600                 mExcessivePower = new ArrayList<ExcessivePower>();
   5601                 for (int i=0; i<N; i++) {
   5602                     ExcessivePower ew = new ExcessivePower();
   5603                     ew.type = in.readInt();
   5604                     ew.overTime = in.readLong();
   5605                     ew.usedTime = in.readLong();
   5606                     mExcessivePower.add(ew);
   5607                 }
   5608                 return true;
   5609             }
   5610 
   5611             void writeToParcelLocked(Parcel out) {
   5612                 out.writeLong(mUserTime);
   5613                 out.writeLong(mSystemTime);
   5614                 out.writeLong(mForegroundTime);
   5615                 out.writeInt(mStarts);
   5616                 out.writeInt(mNumCrashes);
   5617                 out.writeInt(mNumAnrs);
   5618                 out.writeLong(mLoadedUserTime);
   5619                 out.writeLong(mLoadedSystemTime);
   5620                 out.writeLong(mLoadedForegroundTime);
   5621                 out.writeInt(mLoadedStarts);
   5622                 out.writeInt(mLoadedNumCrashes);
   5623                 out.writeInt(mLoadedNumAnrs);
   5624                 out.writeLong(mUnpluggedUserTime);
   5625                 out.writeLong(mUnpluggedSystemTime);
   5626                 out.writeLong(mUnpluggedForegroundTime);
   5627                 out.writeInt(mUnpluggedStarts);
   5628                 out.writeInt(mUnpluggedNumCrashes);
   5629                 out.writeInt(mUnpluggedNumAnrs);
   5630 
   5631                 out.writeInt(mSpeedBins.length);
   5632                 for (int i = 0; i < mSpeedBins.length; i++) {
   5633                     SamplingCounter c = mSpeedBins[i];
   5634                     if (c != null) {
   5635                         out.writeInt(1);
   5636                         c.writeToParcel(out);
   5637                     } else {
   5638                         out.writeInt(0);
   5639                     }
   5640                 }
   5641 
   5642                 writeExcessivePowerToParcelLocked(out);
   5643             }
   5644 
   5645             void readFromParcelLocked(Parcel in) {
   5646                 mUserTime = in.readLong();
   5647                 mSystemTime = in.readLong();
   5648                 mForegroundTime = in.readLong();
   5649                 mStarts = in.readInt();
   5650                 mNumCrashes = in.readInt();
   5651                 mNumAnrs = in.readInt();
   5652                 mLoadedUserTime = in.readLong();
   5653                 mLoadedSystemTime = in.readLong();
   5654                 mLoadedForegroundTime = in.readLong();
   5655                 mLoadedStarts = in.readInt();
   5656                 mLoadedNumCrashes = in.readInt();
   5657                 mLoadedNumAnrs = in.readInt();
   5658                 mUnpluggedUserTime = in.readLong();
   5659                 mUnpluggedSystemTime = in.readLong();
   5660                 mUnpluggedForegroundTime = in.readLong();
   5661                 mUnpluggedStarts = in.readInt();
   5662                 mUnpluggedNumCrashes = in.readInt();
   5663                 mUnpluggedNumAnrs = in.readInt();
   5664 
   5665                 int bins = in.readInt();
   5666                 int steps = getCpuSpeedSteps();
   5667                 mSpeedBins = new SamplingCounter[bins >= steps ? bins : steps];
   5668                 for (int i = 0; i < bins; i++) {
   5669                     if (in.readInt() != 0) {
   5670                         mSpeedBins[i] = new SamplingCounter(mOnBatteryTimeBase, in);
   5671                     }
   5672                 }
   5673 
   5674                 readExcessivePowerFromParcelLocked(in);
   5675             }
   5676 
   5677             public BatteryStatsImpl getBatteryStats() {
   5678                 return BatteryStatsImpl.this;
   5679             }
   5680 
   5681             public void addCpuTimeLocked(int utime, int stime) {
   5682                 mUserTime += utime;
   5683                 mSystemTime += stime;
   5684             }
   5685 
   5686             public void addForegroundTimeLocked(long ttime) {
   5687                 mForegroundTime += ttime;
   5688             }
   5689 
   5690             public void incStartsLocked() {
   5691                 mStarts++;
   5692             }
   5693 
   5694             public void incNumCrashesLocked() {
   5695                 mNumCrashes++;
   5696             }
   5697 
   5698             public void incNumAnrsLocked() {
   5699                 mNumAnrs++;
   5700             }
   5701 
   5702             @Override
   5703             public boolean isActive() {
   5704                 return mActive;
   5705             }
   5706 
   5707             @Override
   5708             public long getUserTime(int which) {
   5709                 long val = mUserTime;
   5710                 if (which == STATS_CURRENT) {
   5711                     val -= mLoadedUserTime;
   5712                 } else if (which == STATS_SINCE_UNPLUGGED) {
   5713                     val -= mUnpluggedUserTime;
   5714                 }
   5715                 return val;
   5716             }
   5717 
   5718             @Override
   5719             public long getSystemTime(int which) {
   5720                 long val = mSystemTime;
   5721                 if (which == STATS_CURRENT) {
   5722                     val -= mLoadedSystemTime;
   5723                 } else if (which == STATS_SINCE_UNPLUGGED) {
   5724                     val -= mUnpluggedSystemTime;
   5725                 }
   5726                 return val;
   5727             }
   5728 
   5729             @Override
   5730             public long getForegroundTime(int which) {
   5731                 long val = mForegroundTime;
   5732                 if (which == STATS_CURRENT) {
   5733                     val -= mLoadedForegroundTime;
   5734                 } else if (which == STATS_SINCE_UNPLUGGED) {
   5735                     val -= mUnpluggedForegroundTime;
   5736                 }
   5737                 return val;
   5738             }
   5739 
   5740             @Override
   5741             public int getStarts(int which) {
   5742                 int val = mStarts;
   5743                 if (which == STATS_CURRENT) {
   5744                     val -= mLoadedStarts;
   5745                 } else if (which == STATS_SINCE_UNPLUGGED) {
   5746                     val -= mUnpluggedStarts;
   5747                 }
   5748                 return val;
   5749             }
   5750 
   5751             @Override
   5752             public int getNumCrashes(int which) {
   5753                 int val = mNumCrashes;
   5754                 if (which == STATS_CURRENT) {
   5755                     val -= mLoadedNumCrashes;
   5756                 } else if (which == STATS_SINCE_UNPLUGGED) {
   5757                     val -= mUnpluggedNumCrashes;
   5758                 }
   5759                 return val;
   5760             }
   5761 
   5762             @Override
   5763             public int getNumAnrs(int which) {
   5764                 int val = mNumAnrs;
   5765                 if (which == STATS_CURRENT) {
   5766                     val -= mLoadedNumAnrs;
   5767                 } else if (which == STATS_SINCE_UNPLUGGED) {
   5768                     val -= mUnpluggedNumAnrs;
   5769                 }
   5770                 return val;
   5771             }
   5772 
   5773             /* Called by ActivityManagerService when CPU times are updated. */
   5774             public void addSpeedStepTimes(long[] values) {
   5775                 for (int i = 0; i < mSpeedBins.length && i < values.length; i++) {
   5776                     long amt = values[i];
   5777                     if (amt != 0) {
   5778                         SamplingCounter c = mSpeedBins[i];
   5779                         if (c == null) {
   5780                             mSpeedBins[i] = c = new SamplingCounter(mOnBatteryTimeBase);
   5781                         }
   5782                         c.addCountAtomic(values[i]);
   5783                     }
   5784                 }
   5785             }
   5786 
   5787             @Override
   5788             public long getTimeAtCpuSpeedStep(int speedStep, int which) {
   5789                 if (speedStep < mSpeedBins.length) {
   5790                     SamplingCounter c = mSpeedBins[speedStep];
   5791                     return c != null ? c.getCountLocked(which) : 0;
   5792                 } else {
   5793                     return 0;
   5794                 }
   5795             }
   5796         }
   5797 
   5798         /**
   5799          * The statistics associated with a particular package.
   5800          */
   5801         public final class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
   5802             /**
   5803              * Number of times this package has done something that could wake up the
   5804              * device from sleep.
   5805              */
   5806             int mWakeups;
   5807 
   5808             /**
   5809              * Number of things that could wake up the device loaded from a
   5810              * previous save.
   5811              */
   5812             int mLoadedWakeups;
   5813 
   5814             /**
   5815              * Number of things that could wake up the device as of the
   5816              * last run.
   5817              */
   5818             int mLastWakeups;
   5819 
   5820             /**
   5821              * Number of things that could wake up the device as of the
   5822              * last run.
   5823              */
   5824             int mUnpluggedWakeups;
   5825 
   5826             /**
   5827              * The statics we have collected for this package's services.
   5828              */
   5829             final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>();
   5830 
   5831             Pkg() {
   5832                 mOnBatteryScreenOffTimeBase.add(this);
   5833             }
   5834 
   5835             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   5836                 mUnpluggedWakeups = mWakeups;
   5837             }
   5838 
   5839             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   5840             }
   5841 
   5842             void detach() {
   5843                 mOnBatteryScreenOffTimeBase.remove(this);
   5844             }
   5845 
   5846             void readFromParcelLocked(Parcel in) {
   5847                 mWakeups = in.readInt();
   5848                 mLoadedWakeups = in.readInt();
   5849                 mLastWakeups = 0;
   5850                 mUnpluggedWakeups = in.readInt();
   5851 
   5852                 int numServs = in.readInt();
   5853                 mServiceStats.clear();
   5854                 for (int m = 0; m < numServs; m++) {
   5855                     String serviceName = in.readString();
   5856                     Uid.Pkg.Serv serv = new Serv();
   5857                     mServiceStats.put(serviceName, serv);
   5858 
   5859                     serv.readFromParcelLocked(in);
   5860                 }
   5861             }
   5862 
   5863             void writeToParcelLocked(Parcel out) {
   5864                 out.writeInt(mWakeups);
   5865                 out.writeInt(mLoadedWakeups);
   5866                 out.writeInt(mUnpluggedWakeups);
   5867 
   5868                 out.writeInt(mServiceStats.size());
   5869                 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) {
   5870                     out.writeString(servEntry.getKey());
   5871                     Uid.Pkg.Serv serv = servEntry.getValue();
   5872 
   5873                     serv.writeToParcelLocked(out);
   5874                 }
   5875             }
   5876 
   5877             @Override
   5878             public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
   5879                 return mServiceStats;
   5880             }
   5881 
   5882             @Override
   5883             public int getWakeups(int which) {
   5884                 int val = mWakeups;
   5885                 if (which == STATS_CURRENT) {
   5886                     val -= mLoadedWakeups;
   5887                 } else if (which == STATS_SINCE_UNPLUGGED) {
   5888                     val -= mUnpluggedWakeups;
   5889                 }
   5890 
   5891                 return val;
   5892             }
   5893 
   5894             /**
   5895              * The statistics associated with a particular service.
   5896              */
   5897             public final class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
   5898                 /**
   5899                  * Total time (ms in battery uptime) the service has been left started.
   5900                  */
   5901                 long mStartTime;
   5902 
   5903                 /**
   5904                  * If service has been started and not yet stopped, this is
   5905                  * when it was started.
   5906                  */
   5907                 long mRunningSince;
   5908 
   5909                 /**
   5910                  * True if we are currently running.
   5911                  */
   5912                 boolean mRunning;
   5913 
   5914                 /**
   5915                  * Total number of times startService() has been called.
   5916                  */
   5917                 int mStarts;
   5918 
   5919                 /**
   5920                  * Total time (ms in battery uptime) the service has been left launched.
   5921                  */
   5922                 long mLaunchedTime;
   5923 
   5924                 /**
   5925                  * If service has been launched and not yet exited, this is
   5926                  * when it was launched (ms in battery uptime).
   5927                  */
   5928                 long mLaunchedSince;
   5929 
   5930                 /**
   5931                  * True if we are currently launched.
   5932                  */
   5933                 boolean mLaunched;
   5934 
   5935                 /**
   5936                  * Total number times the service has been launched.
   5937                  */
   5938                 int mLaunches;
   5939 
   5940                 /**
   5941                  * The amount of time spent started loaded from a previous save
   5942                  * (ms in battery uptime).
   5943                  */
   5944                 long mLoadedStartTime;
   5945 
   5946                 /**
   5947                  * The number of starts loaded from a previous save.
   5948                  */
   5949                 int mLoadedStarts;
   5950 
   5951                 /**
   5952                  * The number of launches loaded from a previous save.
   5953                  */
   5954                 int mLoadedLaunches;
   5955 
   5956                 /**
   5957                  * The amount of time spent started as of the last run (ms
   5958                  * in battery uptime).
   5959                  */
   5960                 long mLastStartTime;
   5961 
   5962                 /**
   5963                  * The number of starts as of the last run.
   5964                  */
   5965                 int mLastStarts;
   5966 
   5967                 /**
   5968                  * The number of launches as of the last run.
   5969                  */
   5970                 int mLastLaunches;
   5971 
   5972                 /**
   5973                  * The amount of time spent started when last unplugged (ms
   5974                  * in battery uptime).
   5975                  */
   5976                 long mUnpluggedStartTime;
   5977 
   5978                 /**
   5979                  * The number of starts when last unplugged.
   5980                  */
   5981                 int mUnpluggedStarts;
   5982 
   5983                 /**
   5984                  * The number of launches when last unplugged.
   5985                  */
   5986                 int mUnpluggedLaunches;
   5987 
   5988                 Serv() {
   5989                     mOnBatteryTimeBase.add(this);
   5990                 }
   5991 
   5992                 public void onTimeStarted(long elapsedRealtime, long baseUptime,
   5993                         long baseRealtime) {
   5994                     mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
   5995                     mUnpluggedStarts = mStarts;
   5996                     mUnpluggedLaunches = mLaunches;
   5997                 }
   5998 
   5999                 public void onTimeStopped(long elapsedRealtime, long baseUptime,
   6000                         long baseRealtime) {
   6001                 }
   6002 
   6003                 void detach() {
   6004                     mOnBatteryTimeBase.remove(this);
   6005                 }
   6006 
   6007                 void readFromParcelLocked(Parcel in) {
   6008                     mStartTime = in.readLong();
   6009                     mRunningSince = in.readLong();
   6010                     mRunning = in.readInt() != 0;
   6011                     mStarts = in.readInt();
   6012                     mLaunchedTime = in.readLong();
   6013                     mLaunchedSince = in.readLong();
   6014                     mLaunched = in.readInt() != 0;
   6015                     mLaunches = in.readInt();
   6016                     mLoadedStartTime = in.readLong();
   6017                     mLoadedStarts = in.readInt();
   6018                     mLoadedLaunches = in.readInt();
   6019                     mLastStartTime = 0;
   6020                     mLastStarts = 0;
   6021                     mLastLaunches = 0;
   6022                     mUnpluggedStartTime = in.readLong();
   6023                     mUnpluggedStarts = in.readInt();
   6024                     mUnpluggedLaunches = in.readInt();
   6025                 }
   6026 
   6027                 void writeToParcelLocked(Parcel out) {
   6028                     out.writeLong(mStartTime);
   6029                     out.writeLong(mRunningSince);
   6030                     out.writeInt(mRunning ? 1 : 0);
   6031                     out.writeInt(mStarts);
   6032                     out.writeLong(mLaunchedTime);
   6033                     out.writeLong(mLaunchedSince);
   6034                     out.writeInt(mLaunched ? 1 : 0);
   6035                     out.writeInt(mLaunches);
   6036                     out.writeLong(mLoadedStartTime);
   6037                     out.writeInt(mLoadedStarts);
   6038                     out.writeInt(mLoadedLaunches);
   6039                     out.writeLong(mUnpluggedStartTime);
   6040                     out.writeInt(mUnpluggedStarts);
   6041                     out.writeInt(mUnpluggedLaunches);
   6042                 }
   6043 
   6044                 long getLaunchTimeToNowLocked(long batteryUptime) {
   6045                     if (!mLaunched) return mLaunchedTime;
   6046                     return mLaunchedTime + batteryUptime - mLaunchedSince;
   6047                 }
   6048 
   6049                 long getStartTimeToNowLocked(long batteryUptime) {
   6050                     if (!mRunning) return mStartTime;
   6051                     return mStartTime + batteryUptime - mRunningSince;
   6052                 }
   6053 
   6054                 public void startLaunchedLocked() {
   6055                     if (!mLaunched) {
   6056                         mLaunches++;
   6057                         mLaunchedSince = getBatteryUptimeLocked();
   6058                         mLaunched = true;
   6059                     }
   6060                 }
   6061 
   6062                 public void stopLaunchedLocked() {
   6063                     if (mLaunched) {
   6064                         long time = getBatteryUptimeLocked() - mLaunchedSince;
   6065                         if (time > 0) {
   6066                             mLaunchedTime += time;
   6067                         } else {
   6068                             mLaunches--;
   6069                         }
   6070                         mLaunched = false;
   6071                     }
   6072                 }
   6073 
   6074                 public void startRunningLocked() {
   6075                     if (!mRunning) {
   6076                         mStarts++;
   6077                         mRunningSince = getBatteryUptimeLocked();
   6078                         mRunning = true;
   6079                     }
   6080                 }
   6081 
   6082                 public void stopRunningLocked() {
   6083                     if (mRunning) {
   6084                         long time = getBatteryUptimeLocked() - mRunningSince;
   6085                         if (time > 0) {
   6086                             mStartTime += time;
   6087                         } else {
   6088                             mStarts--;
   6089                         }
   6090                         mRunning = false;
   6091                     }
   6092                 }
   6093 
   6094                 public BatteryStatsImpl getBatteryStats() {
   6095                     return BatteryStatsImpl.this;
   6096                 }
   6097 
   6098                 @Override
   6099                 public int getLaunches(int which) {
   6100                     int val = mLaunches;
   6101                     if (which == STATS_CURRENT) {
   6102                         val -= mLoadedLaunches;
   6103                     } else if (which == STATS_SINCE_UNPLUGGED) {
   6104                         val -= mUnpluggedLaunches;
   6105                     }
   6106                     return val;
   6107                 }
   6108 
   6109                 @Override
   6110                 public long getStartTime(long now, int which) {
   6111                     long val = getStartTimeToNowLocked(now);
   6112                     if (which == STATS_CURRENT) {
   6113                         val -= mLoadedStartTime;
   6114                     } else if (which == STATS_SINCE_UNPLUGGED) {
   6115                         val -= mUnpluggedStartTime;
   6116                     }
   6117                     return val;
   6118                 }
   6119 
   6120                 @Override
   6121                 public int getStarts(int which) {
   6122                     int val = mStarts;
   6123                     if (which == STATS_CURRENT) {
   6124                         val -= mLoadedStarts;
   6125                     } else if (which == STATS_SINCE_UNPLUGGED) {
   6126                         val -= mUnpluggedStarts;
   6127                     }
   6128 
   6129                     return val;
   6130                 }
   6131             }
   6132 
   6133             public BatteryStatsImpl getBatteryStats() {
   6134                 return BatteryStatsImpl.this;
   6135             }
   6136 
   6137             public void incWakeupsLocked() {
   6138                 mWakeups++;
   6139             }
   6140 
   6141             final Serv newServiceStatsLocked() {
   6142                 return new Serv();
   6143             }
   6144         }
   6145 
   6146         /**
   6147          * Retrieve the statistics object for a particular process, creating
   6148          * if needed.
   6149          */
   6150         public Proc getProcessStatsLocked(String name) {
   6151             Proc ps = mProcessStats.get(name);
   6152             if (ps == null) {
   6153                 ps = new Proc(name);
   6154                 mProcessStats.put(name, ps);
   6155             }
   6156 
   6157             return ps;
   6158         }
   6159 
   6160         public void updateProcessStateLocked(String procName, int state, long elapsedRealtimeMs) {
   6161             int procState;
   6162             if (state <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
   6163                 procState = PROCESS_STATE_FOREGROUND;
   6164             } else if (state <= ActivityManager.PROCESS_STATE_RECEIVER) {
   6165                 procState = PROCESS_STATE_ACTIVE;
   6166             } else {
   6167                 procState = PROCESS_STATE_RUNNING;
   6168             }
   6169             updateRealProcessStateLocked(procName, procState, elapsedRealtimeMs);
   6170         }
   6171 
   6172         public void updateRealProcessStateLocked(String procName, int procState,
   6173                 long elapsedRealtimeMs) {
   6174             Proc proc = getProcessStatsLocked(procName);
   6175             if (proc.mProcessState != procState) {
   6176                 boolean changed;
   6177                 if (procState < proc.mProcessState) {
   6178                     // Has this process become more important?  If so,
   6179                     // we may need to change the uid if the currrent uid proc state
   6180                     // is not as important as what we are now setting.
   6181                     changed = mProcessState > procState;
   6182                 } else {
   6183                     // Has this process become less important?  If so,
   6184                     // we may need to change the uid if the current uid proc state
   6185                     // is the same importance as the old setting.
   6186                     changed = mProcessState == proc.mProcessState;
   6187                 }
   6188                 proc.mProcessState = procState;
   6189                 if (changed) {
   6190                     // uid's state may have changed; compute what the new state should be.
   6191                     int uidProcState = PROCESS_STATE_NONE;
   6192                     for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
   6193                         proc = mProcessStats.valueAt(ip);
   6194                         if (proc.mProcessState < uidProcState) {
   6195                             uidProcState = proc.mProcessState;
   6196                         }
   6197                     }
   6198                     updateUidProcessStateLocked(uidProcState, elapsedRealtimeMs);
   6199                 }
   6200             }
   6201         }
   6202 
   6203         public SparseArray<? extends Pid> getPidStats() {
   6204             return mPids;
   6205         }
   6206 
   6207         public Pid getPidStatsLocked(int pid) {
   6208             Pid p = mPids.get(pid);
   6209             if (p == null) {
   6210                 p = new Pid();
   6211                 mPids.put(pid, p);
   6212             }
   6213             return p;
   6214         }
   6215 
   6216         /**
   6217          * Retrieve the statistics object for a particular service, creating
   6218          * if needed.
   6219          */
   6220         public Pkg getPackageStatsLocked(String name) {
   6221             Pkg ps = mPackageStats.get(name);
   6222             if (ps == null) {
   6223                 ps = new Pkg();
   6224                 mPackageStats.put(name, ps);
   6225             }
   6226 
   6227             return ps;
   6228         }
   6229 
   6230         /**
   6231          * Retrieve the statistics object for a particular service, creating
   6232          * if needed.
   6233          */
   6234         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
   6235             Pkg ps = getPackageStatsLocked(pkg);
   6236             Pkg.Serv ss = ps.mServiceStats.get(serv);
   6237             if (ss == null) {
   6238                 ss = ps.newServiceStatsLocked();
   6239                 ps.mServiceStats.put(serv, ss);
   6240             }
   6241 
   6242             return ss;
   6243         }
   6244 
   6245         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
   6246             StopwatchTimer timer = mSyncStats.instantiateObject();
   6247             timer.readSummaryFromParcelLocked(in);
   6248             mSyncStats.add(name, timer);
   6249         }
   6250 
   6251         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
   6252             StopwatchTimer timer = mJobStats.instantiateObject();
   6253             timer.readSummaryFromParcelLocked(in);
   6254             mJobStats.add(name, timer);
   6255         }
   6256 
   6257         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
   6258             Wakelock wl = new Wakelock();
   6259             mWakelockStats.add(wlName, wl);
   6260             if (in.readInt() != 0) {
   6261                 wl.getStopwatchTimer(WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
   6262             }
   6263             if (in.readInt() != 0) {
   6264                 wl.getStopwatchTimer(WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
   6265             }
   6266             if (in.readInt() != 0) {
   6267                 wl.getStopwatchTimer(WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
   6268             }
   6269         }
   6270 
   6271         public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
   6272             Sensor se = mSensorStats.get(sensor);
   6273             if (se == null) {
   6274                 if (!create) {
   6275                     return null;
   6276                 }
   6277                 se = new Sensor(sensor);
   6278                 mSensorStats.put(sensor, se);
   6279             }
   6280             StopwatchTimer t = se.mTimer;
   6281             if (t != null) {
   6282                 return t;
   6283             }
   6284             ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor);
   6285             if (timers == null) {
   6286                 timers = new ArrayList<StopwatchTimer>();
   6287                 mSensorTimers.put(sensor, timers);
   6288             }
   6289             t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mOnBatteryTimeBase);
   6290             se.mTimer = t;
   6291             return t;
   6292         }
   6293 
   6294         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
   6295             StopwatchTimer t = mSyncStats.startObject(name);
   6296             if (t != null) {
   6297                 t.startRunningLocked(elapsedRealtimeMs);
   6298             }
   6299         }
   6300 
   6301         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
   6302             StopwatchTimer t = mSyncStats.stopObject(name);
   6303             if (t != null) {
   6304                 t.stopRunningLocked(elapsedRealtimeMs);
   6305             }
   6306         }
   6307 
   6308         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
   6309             StopwatchTimer t = mJobStats.startObject(name);
   6310             if (t != null) {
   6311                 t.startRunningLocked(elapsedRealtimeMs);
   6312             }
   6313         }
   6314 
   6315         public void noteStopJobLocked(String name, long elapsedRealtimeMs) {
   6316             StopwatchTimer t = mJobStats.stopObject(name);
   6317             if (t != null) {
   6318                 t.stopRunningLocked(elapsedRealtimeMs);
   6319             }
   6320         }
   6321 
   6322         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
   6323             Wakelock wl = mWakelockStats.startObject(name);
   6324             if (wl != null) {
   6325                 wl.getStopwatchTimer(type).startRunningLocked(elapsedRealtimeMs);
   6326             }
   6327             if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
   6328                 Pid p = getPidStatsLocked(pid);
   6329                 if (p.mWakeNesting++ == 0) {
   6330                     p.mWakeStartMs = elapsedRealtimeMs;
   6331                 }
   6332             }
   6333         }
   6334 
   6335         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
   6336             Wakelock wl = mWakelockStats.stopObject(name);
   6337             if (wl != null) {
   6338                 wl.getStopwatchTimer(type).stopRunningLocked(elapsedRealtimeMs);
   6339             }
   6340             if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
   6341                 Pid p = mPids.get(pid);
   6342                 if (p != null && p.mWakeNesting > 0) {
   6343                     if (p.mWakeNesting-- == 1) {
   6344                         p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
   6345                         p.mWakeStartMs = 0;
   6346                     }
   6347                 }
   6348             }
   6349         }
   6350 
   6351         public void reportExcessiveWakeLocked(String proc, long overTime, long usedTime) {
   6352             Proc p = getProcessStatsLocked(proc);
   6353             if (p != null) {
   6354                 p.addExcessiveWake(overTime, usedTime);
   6355             }
   6356         }
   6357 
   6358         public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
   6359             Proc p = getProcessStatsLocked(proc);
   6360             if (p != null) {
   6361                 p.addExcessiveCpu(overTime, usedTime);
   6362             }
   6363         }
   6364 
   6365         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
   6366             StopwatchTimer t = getSensorTimerLocked(sensor, true);
   6367             if (t != null) {
   6368                 t.startRunningLocked(elapsedRealtimeMs);
   6369             }
   6370         }
   6371 
   6372         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
   6373             // Don't create a timer if one doesn't already exist
   6374             StopwatchTimer t = getSensorTimerLocked(sensor, false);
   6375             if (t != null) {
   6376                 t.stopRunningLocked(elapsedRealtimeMs);
   6377             }
   6378         }
   6379 
   6380         public void noteStartGps(long elapsedRealtimeMs) {
   6381             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
   6382             if (t != null) {
   6383                 t.startRunningLocked(elapsedRealtimeMs);
   6384             }
   6385         }
   6386 
   6387         public void noteStopGps(long elapsedRealtimeMs) {
   6388             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
   6389             if (t != null) {
   6390                 t.stopRunningLocked(elapsedRealtimeMs);
   6391             }
   6392         }
   6393 
   6394         public BatteryStatsImpl getBatteryStats() {
   6395             return BatteryStatsImpl.this;
   6396         }
   6397     }
   6398 
   6399     public BatteryStatsImpl(File systemDir, Handler handler) {
   6400         if (systemDir != null) {
   6401             mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
   6402                     new File(systemDir, "batterystats.bin.tmp"));
   6403         } else {
   6404             mFile = null;
   6405         }
   6406         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
   6407         mHandler = new MyHandler(handler.getLooper());
   6408         mStartCount++;
   6409         mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase);
   6410         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   6411             mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase);
   6412         }
   6413         mInteractiveTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase);
   6414         mLowPowerModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
   6415         mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase);
   6416         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   6417             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null,
   6418                     mOnBatteryTimeBase);
   6419         }
   6420         mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase);
   6421         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   6422             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null,
   6423                     mOnBatteryTimeBase);
   6424         }
   6425         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   6426             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
   6427             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
   6428         }
   6429         mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase);
   6430         mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase);
   6431         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
   6432         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
   6433         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
   6434         mWifiOnTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase);
   6435         mGlobalWifiRunningTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase);
   6436         for (int i=0; i<NUM_WIFI_STATES; i++) {
   6437             mWifiStateTimer[i] = new StopwatchTimer(null, -600-i, null, mOnBatteryTimeBase);
   6438         }
   6439         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   6440             mWifiSupplStateTimer[i] = new StopwatchTimer(null, -700-i, null, mOnBatteryTimeBase);
   6441         }
   6442         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   6443             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i, null,
   6444                     mOnBatteryTimeBase);
   6445         }
   6446         mBluetoothOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase);
   6447         for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
   6448             mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i, null, mOnBatteryTimeBase);
   6449         }
   6450         mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
   6451         mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
   6452         mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase);
   6453         mOnBattery = mOnBatteryInternal = false;
   6454         long uptime = SystemClock.uptimeMillis() * 1000;
   6455         long realtime = SystemClock.elapsedRealtime() * 1000;
   6456         initTimes(uptime, realtime);
   6457         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
   6458         mDischargeStartLevel = 0;
   6459         mDischargeUnplugLevel = 0;
   6460         mDischargePlugLevel = -1;
   6461         mDischargeCurrentLevel = 0;
   6462         mCurrentBatteryLevel = 0;
   6463         initDischarge();
   6464         clearHistoryLocked();
   6465     }
   6466 
   6467     public BatteryStatsImpl(Parcel p) {
   6468         mFile = null;
   6469         mCheckinFile = null;
   6470         mHandler = null;
   6471         clearHistoryLocked();
   6472         readFromParcel(p);
   6473     }
   6474 
   6475     public void setCallback(BatteryCallback cb) {
   6476         mCallback = cb;
   6477     }
   6478 
   6479     public void setNumSpeedSteps(int steps) {
   6480         if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
   6481     }
   6482 
   6483     public void setRadioScanningTimeout(long timeout) {
   6484         if (mPhoneSignalScanningTimer != null) {
   6485             mPhoneSignalScanningTimer.setTimeout(timeout);
   6486         }
   6487     }
   6488 
   6489     @Override
   6490     public boolean startIteratingOldHistoryLocked() {
   6491         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
   6492                 + " pos=" + mHistoryBuffer.dataPosition());
   6493         if ((mHistoryIterator = mHistory) == null) {
   6494             return false;
   6495         }
   6496         mHistoryBuffer.setDataPosition(0);
   6497         mHistoryReadTmp.clear();
   6498         mReadOverflow = false;
   6499         mIteratingHistory = true;
   6500         return true;
   6501     }
   6502 
   6503     @Override
   6504     public boolean getNextOldHistoryLocked(HistoryItem out) {
   6505         boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
   6506         if (!end) {
   6507             readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
   6508             mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
   6509         }
   6510         HistoryItem cur = mHistoryIterator;
   6511         if (cur == null) {
   6512             if (!mReadOverflow && !end) {
   6513                 Slog.w(TAG, "Old history ends before new history!");
   6514             }
   6515             return false;
   6516         }
   6517         out.setTo(cur);
   6518         mHistoryIterator = cur.next;
   6519         if (!mReadOverflow) {
   6520             if (end) {
   6521                 Slog.w(TAG, "New history ends before old history!");
   6522             } else if (!out.same(mHistoryReadTmp)) {
   6523                 PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
   6524                 pw.println("Histories differ!");
   6525                 pw.println("Old history:");
   6526                 (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
   6527                 pw.println("New history:");
   6528                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
   6529                         true);
   6530                 pw.flush();
   6531             }
   6532         }
   6533         return true;
   6534     }
   6535 
   6536     @Override
   6537     public void finishIteratingOldHistoryLocked() {
   6538         mIteratingHistory = false;
   6539         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
   6540         mHistoryIterator = null;
   6541     }
   6542 
   6543     public int getHistoryTotalSize() {
   6544         return MAX_HISTORY_BUFFER;
   6545     }
   6546 
   6547     public int getHistoryUsedSize() {
   6548         return mHistoryBuffer.dataSize();
   6549     }
   6550 
   6551     @Override
   6552     public boolean startIteratingHistoryLocked() {
   6553         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
   6554                 + " pos=" + mHistoryBuffer.dataPosition());
   6555         if (mHistoryBuffer.dataSize() <= 0) {
   6556             return false;
   6557         }
   6558         mHistoryBuffer.setDataPosition(0);
   6559         mReadOverflow = false;
   6560         mIteratingHistory = true;
   6561         mReadHistoryStrings = new String[mHistoryTagPool.size()];
   6562         mReadHistoryUids = new int[mHistoryTagPool.size()];
   6563         mReadHistoryChars = 0;
   6564         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
   6565             final HistoryTag tag = ent.getKey();
   6566             final int idx = ent.getValue();
   6567             mReadHistoryStrings[idx] = tag.string;
   6568             mReadHistoryUids[idx] = tag.uid;
   6569             mReadHistoryChars += tag.string.length() + 1;
   6570         }
   6571         return true;
   6572     }
   6573 
   6574     @Override
   6575     public int getHistoryStringPoolSize() {
   6576         return mReadHistoryStrings.length;
   6577     }
   6578 
   6579     @Override
   6580     public int getHistoryStringPoolBytes() {
   6581         // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
   6582         // Each string character is 2 bytes.
   6583         return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
   6584     }
   6585 
   6586     @Override
   6587     public String getHistoryTagPoolString(int index) {
   6588         return mReadHistoryStrings[index];
   6589     }
   6590 
   6591     @Override
   6592     public int getHistoryTagPoolUid(int index) {
   6593         return mReadHistoryUids[index];
   6594     }
   6595 
   6596     @Override
   6597     public boolean getNextHistoryLocked(HistoryItem out) {
   6598         final int pos = mHistoryBuffer.dataPosition();
   6599         if (pos == 0) {
   6600             out.clear();
   6601         }
   6602         boolean end = pos >= mHistoryBuffer.dataSize();
   6603         if (end) {
   6604             return false;
   6605         }
   6606 
   6607         final long lastRealtime = out.time;
   6608         final long lastWalltime = out.currentTime;
   6609         readHistoryDelta(mHistoryBuffer, out);
   6610         if (out.cmd != HistoryItem.CMD_CURRENT_TIME
   6611                 && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
   6612             out.currentTime = lastWalltime + (out.time - lastRealtime);
   6613         }
   6614         return true;
   6615     }
   6616 
   6617     @Override
   6618     public void finishIteratingHistoryLocked() {
   6619         mIteratingHistory = false;
   6620         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
   6621         mReadHistoryStrings = null;
   6622     }
   6623 
   6624     @Override
   6625     public long getHistoryBaseTime() {
   6626         return mHistoryBaseTime;
   6627     }
   6628 
   6629     @Override
   6630     public int getStartCount() {
   6631         return mStartCount;
   6632     }
   6633 
   6634     public boolean isOnBattery() {
   6635         return mOnBattery;
   6636     }
   6637 
   6638     public boolean isScreenOn() {
   6639         return mScreenState == Display.STATE_ON;
   6640     }
   6641 
   6642     void initTimes(long uptime, long realtime) {
   6643         mStartClockTime = System.currentTimeMillis();
   6644         mOnBatteryTimeBase.init(uptime, realtime);
   6645         mOnBatteryScreenOffTimeBase.init(uptime, realtime);
   6646         mRealtime = 0;
   6647         mUptime = 0;
   6648         mRealtimeStart = realtime;
   6649         mUptimeStart = uptime;
   6650     }
   6651 
   6652     void initDischarge() {
   6653         mLowDischargeAmountSinceCharge = 0;
   6654         mHighDischargeAmountSinceCharge = 0;
   6655         mDischargeAmountScreenOn = 0;
   6656         mDischargeAmountScreenOnSinceCharge = 0;
   6657         mDischargeAmountScreenOff = 0;
   6658         mDischargeAmountScreenOffSinceCharge = 0;
   6659         mLastDischargeStepTime = -1;
   6660         mNumDischargeStepDurations = 0;
   6661         mLastChargeStepTime = -1;
   6662         mNumChargeStepDurations = 0;
   6663     }
   6664 
   6665     public void resetAllStatsCmdLocked() {
   6666         resetAllStatsLocked();
   6667         final long mSecUptime = SystemClock.uptimeMillis();
   6668         long uptime = mSecUptime * 1000;
   6669         long mSecRealtime = SystemClock.elapsedRealtime();
   6670         long realtime = mSecRealtime * 1000;
   6671         mDischargeStartLevel = mHistoryCur.batteryLevel;
   6672         pullPendingStateUpdatesLocked();
   6673         addHistoryRecordLocked(mSecRealtime, mSecUptime);
   6674         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
   6675                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
   6676         mOnBatteryTimeBase.reset(uptime, realtime);
   6677         mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
   6678         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
   6679             if (mScreenState == Display.STATE_ON) {
   6680                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
   6681                 mDischargeScreenOffUnplugLevel = 0;
   6682             } else {
   6683                 mDischargeScreenOnUnplugLevel = 0;
   6684                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
   6685             }
   6686             mDischargeAmountScreenOn = 0;
   6687             mDischargeAmountScreenOff = 0;
   6688         }
   6689         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
   6690     }
   6691 
   6692     private void resetAllStatsLocked() {
   6693         mStartCount = 0;
   6694         initTimes(SystemClock.uptimeMillis() * 1000, SystemClock.elapsedRealtime() * 1000);
   6695         mScreenOnTimer.reset(false);
   6696         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   6697             mScreenBrightnessTimer[i].reset(false);
   6698         }
   6699         mInteractiveTimer.reset(false);
   6700         mLowPowerModeEnabledTimer.reset(false);
   6701         mPhoneOnTimer.reset(false);
   6702         mAudioOnTimer.reset(false);
   6703         mVideoOnTimer.reset(false);
   6704         mFlashlightOnTimer.reset(false);
   6705         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   6706             mPhoneSignalStrengthsTimer[i].reset(false);
   6707         }
   6708         mPhoneSignalScanningTimer.reset(false);
   6709         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   6710             mPhoneDataConnectionsTimer[i].reset(false);
   6711         }
   6712         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   6713             mNetworkByteActivityCounters[i].reset(false);
   6714             mNetworkPacketActivityCounters[i].reset(false);
   6715         }
   6716         mMobileRadioActiveTimer.reset(false);
   6717         mMobileRadioActivePerAppTimer.reset(false);
   6718         mMobileRadioActiveAdjustedTime.reset(false);
   6719         mMobileRadioActiveUnknownTime.reset(false);
   6720         mMobileRadioActiveUnknownCount.reset(false);
   6721         mWifiOnTimer.reset(false);
   6722         mGlobalWifiRunningTimer.reset(false);
   6723         for (int i=0; i<NUM_WIFI_STATES; i++) {
   6724             mWifiStateTimer[i].reset(false);
   6725         }
   6726         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   6727             mWifiSupplStateTimer[i].reset(false);
   6728         }
   6729         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   6730             mWifiSignalStrengthsTimer[i].reset(false);
   6731         }
   6732         mBluetoothOnTimer.reset(false);
   6733         for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
   6734             mBluetoothStateTimer[i].reset(false);
   6735         }
   6736         mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
   6737 
   6738         for (int i=0; i<mUidStats.size(); i++) {
   6739             if (mUidStats.valueAt(i).reset()) {
   6740                 mUidStats.remove(mUidStats.keyAt(i));
   6741                 i--;
   6742             }
   6743         }
   6744 
   6745         if (mKernelWakelockStats.size() > 0) {
   6746             for (SamplingTimer timer : mKernelWakelockStats.values()) {
   6747                 mOnBatteryScreenOffTimeBase.remove(timer);
   6748             }
   6749             mKernelWakelockStats.clear();
   6750         }
   6751 
   6752         if (mWakeupReasonStats.size() > 0) {
   6753             for (SamplingTimer timer : mWakeupReasonStats.values()) {
   6754                 mOnBatteryTimeBase.remove(timer);
   6755             }
   6756             mWakeupReasonStats.clear();
   6757         }
   6758 
   6759         initDischarge();
   6760 
   6761         clearHistoryLocked();
   6762     }
   6763 
   6764     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
   6765         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
   6766             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
   6767                 // Not recording process starts/stops.
   6768                 continue;
   6769             }
   6770             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
   6771             if (active == null) {
   6772                 continue;
   6773             }
   6774             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
   6775                 SparseIntArray uids = ent.getValue();
   6776                 for (int j=0; j<uids.size(); j++) {
   6777                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
   6778                             uids.keyAt(j));
   6779                 }
   6780             }
   6781         }
   6782     }
   6783 
   6784     void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) {
   6785         if (oldScreenOn) {
   6786             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
   6787             if (diff > 0) {
   6788                 mDischargeAmountScreenOn += diff;
   6789                 mDischargeAmountScreenOnSinceCharge += diff;
   6790             }
   6791         } else {
   6792             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
   6793             if (diff > 0) {
   6794                 mDischargeAmountScreenOff += diff;
   6795                 mDischargeAmountScreenOffSinceCharge += diff;
   6796             }
   6797         }
   6798         if (newScreenOn) {
   6799             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
   6800             mDischargeScreenOffUnplugLevel = 0;
   6801         } else {
   6802             mDischargeScreenOnUnplugLevel = 0;
   6803             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
   6804         }
   6805     }
   6806 
   6807     public void pullPendingStateUpdatesLocked() {
   6808         updateKernelWakelocksLocked();
   6809         updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
   6810         if (mOnBatteryInternal) {
   6811             final boolean screenOn = mScreenState == Display.STATE_ON;
   6812             updateDischargeScreenLevelsLocked(screenOn, screenOn);
   6813         }
   6814     }
   6815 
   6816     void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
   6817             final int oldStatus, final int level) {
   6818         boolean doWrite = false;
   6819         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
   6820         m.arg1 = onBattery ? 1 : 0;
   6821         mHandler.sendMessage(m);
   6822 
   6823         final long uptime = mSecUptime * 1000;
   6824         final long realtime = mSecRealtime * 1000;
   6825         final boolean screenOn = mScreenState == Display.STATE_ON;
   6826         if (onBattery) {
   6827             // We will reset our status if we are unplugging after the
   6828             // battery was last full, or the level is at 100, or
   6829             // we have gone through a significant charge (from a very low
   6830             // level to a now very high level).
   6831             boolean reset = false;
   6832             if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
   6833                     || level >= 90
   6834                     || (mDischargeCurrentLevel < 20 && level >= 80)
   6835                     || (getHighDischargeAmountSinceCharge() >= 200
   6836                             && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
   6837                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
   6838                         + " dischargeLevel=" + mDischargeCurrentLevel
   6839                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
   6840                         + " highAmount=" + getHighDischargeAmountSinceCharge());
   6841                 // Before we write, collect a snapshot of the final aggregated
   6842                 // stats to be reported in the next checkin.  Only do this if we have
   6843                 // a sufficient amount of data to make it interesting.
   6844                 if (getLowDischargeAmountSinceCharge() >= 20) {
   6845                     final Parcel parcel = Parcel.obtain();
   6846                     writeSummaryToParcel(parcel, true);
   6847                     BackgroundThread.getHandler().post(new Runnable() {
   6848                         @Override public void run() {
   6849                             synchronized (mCheckinFile) {
   6850                                 FileOutputStream stream = null;
   6851                                 try {
   6852                                     stream = mCheckinFile.startWrite();
   6853                                     stream.write(parcel.marshall());
   6854                                     stream.flush();
   6855                                     FileUtils.sync(stream);
   6856                                     stream.close();
   6857                                     mCheckinFile.finishWrite(stream);
   6858                                 } catch (IOException e) {
   6859                                     Slog.w("BatteryStats",
   6860                                             "Error writing checkin battery statistics", e);
   6861                                     mCheckinFile.failWrite(stream);
   6862                                 } finally {
   6863                                     parcel.recycle();
   6864                                 }
   6865                             }
   6866                         }
   6867                     });
   6868                 }
   6869                 doWrite = true;
   6870                 resetAllStatsLocked();
   6871                 mDischargeStartLevel = level;
   6872                 reset = true;
   6873                 mNumDischargeStepDurations = 0;
   6874             }
   6875             mOnBattery = mOnBatteryInternal = onBattery;
   6876             mLastDischargeStepLevel = level;
   6877             mMinDischargeStepLevel = level;
   6878             mLastDischargeStepTime = -1;
   6879             mInitStepMode = mCurStepMode;
   6880             mModStepMode = 0;
   6881             pullPendingStateUpdatesLocked();
   6882             mHistoryCur.batteryLevel = (byte)level;
   6883             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   6884             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
   6885                     + Integer.toHexString(mHistoryCur.states));
   6886             if (reset) {
   6887                 mRecordingHistory = true;
   6888                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
   6889             }
   6890             addHistoryRecordLocked(mSecRealtime, mSecUptime);
   6891             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
   6892             if (screenOn) {
   6893                 mDischargeScreenOnUnplugLevel = level;
   6894                 mDischargeScreenOffUnplugLevel = 0;
   6895             } else {
   6896                 mDischargeScreenOnUnplugLevel = 0;
   6897                 mDischargeScreenOffUnplugLevel = level;
   6898             }
   6899             mDischargeAmountScreenOn = 0;
   6900             mDischargeAmountScreenOff = 0;
   6901             updateTimeBasesLocked(true, !screenOn, uptime, realtime);
   6902         } else {
   6903             mOnBattery = mOnBatteryInternal = onBattery;
   6904             pullPendingStateUpdatesLocked();
   6905             mHistoryCur.batteryLevel = (byte)level;
   6906             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   6907             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
   6908                     + Integer.toHexString(mHistoryCur.states));
   6909             addHistoryRecordLocked(mSecRealtime, mSecUptime);
   6910             mDischargeCurrentLevel = mDischargePlugLevel = level;
   6911             if (level < mDischargeUnplugLevel) {
   6912                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
   6913                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
   6914             }
   6915             updateDischargeScreenLevelsLocked(screenOn, screenOn);
   6916             updateTimeBasesLocked(false, !screenOn, uptime, realtime);
   6917             mNumChargeStepDurations = 0;
   6918             mLastChargeStepLevel = level;
   6919             mMaxChargeStepLevel = level;
   6920             mLastChargeStepTime = -1;
   6921             mInitStepMode = mCurStepMode;
   6922             mModStepMode = 0;
   6923         }
   6924         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
   6925             if (mFile != null) {
   6926                 writeAsyncLocked();
   6927             }
   6928         }
   6929     }
   6930 
   6931     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
   6932             boolean reset) {
   6933         mRecordingHistory = true;
   6934         mHistoryCur.currentTime = System.currentTimeMillis();
   6935         mLastRecordedClockTime = mHistoryCur.currentTime;
   6936         mLastRecordedClockRealtime = elapsedRealtimeMs;
   6937         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
   6938                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
   6939                 mHistoryCur);
   6940         mHistoryCur.currentTime = 0;
   6941         if (reset) {
   6942             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
   6943         }
   6944     }
   6945 
   6946     private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
   6947             final long uptimeMs) {
   6948         if (mRecordingHistory) {
   6949             mHistoryCur.currentTime = currentTime;
   6950             mLastRecordedClockTime = currentTime;
   6951             mLastRecordedClockRealtime = elapsedRealtimeMs;
   6952             addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
   6953                     mHistoryCur);
   6954             mHistoryCur.currentTime = 0;
   6955         }
   6956     }
   6957 
   6958     private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
   6959         if (mRecordingHistory) {
   6960             mHistoryCur.currentTime = System.currentTimeMillis();
   6961             mLastRecordedClockTime = mHistoryCur.currentTime;
   6962             mLastRecordedClockRealtime = elapsedRealtimeMs;
   6963             addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_SHUTDOWN,
   6964                     mHistoryCur);
   6965             mHistoryCur.currentTime = 0;
   6966         }
   6967     }
   6968 
   6969     // This should probably be exposed in the API, though it's not critical
   6970     private static final int BATTERY_PLUGGED_NONE = 0;
   6971 
   6972     private static int addLevelSteps(long[] steps, int stepCount, long lastStepTime,
   6973             int numStepLevels, long modeBits, long elapsedRealtime) {
   6974         if (lastStepTime >= 0 && numStepLevels > 0) {
   6975             long duration = elapsedRealtime - lastStepTime;
   6976             for (int i=0; i<numStepLevels; i++) {
   6977                 System.arraycopy(steps, 0, steps, 1, steps.length-1);
   6978                 long thisDuration = duration / (numStepLevels-i);
   6979                 duration -= thisDuration;
   6980                 if (thisDuration > STEP_LEVEL_TIME_MASK) {
   6981                     thisDuration = STEP_LEVEL_TIME_MASK;
   6982                 }
   6983                 steps[0] = thisDuration | modeBits;
   6984             }
   6985             stepCount += numStepLevels;
   6986             if (stepCount > steps.length) {
   6987                 stepCount = steps.length;
   6988             }
   6989         }
   6990         return stepCount;
   6991     }
   6992 
   6993     public void setBatteryState(int status, int health, int plugType, int level,
   6994             int temp, int volt) {
   6995         synchronized(this) {
   6996             final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
   6997             final long uptime = SystemClock.uptimeMillis();
   6998             final long elapsedRealtime = SystemClock.elapsedRealtime();
   6999             int oldStatus = mHistoryCur.batteryStatus;
   7000             if (!mHaveBatteryLevel) {
   7001                 mHaveBatteryLevel = true;
   7002                 // We start out assuming that the device is plugged in (not
   7003                 // on battery).  If our first report is now that we are indeed
   7004                 // plugged in, then twiddle our state to correctly reflect that
   7005                 // since we won't be going through the full setOnBattery().
   7006                 if (onBattery == mOnBattery) {
   7007                     if (onBattery) {
   7008                         mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   7009                     } else {
   7010                         mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   7011                     }
   7012                 }
   7013                 oldStatus = status;
   7014             }
   7015             if (onBattery) {
   7016                 mDischargeCurrentLevel = level;
   7017                 if (!mRecordingHistory) {
   7018                     mRecordingHistory = true;
   7019                     startRecordingHistory(elapsedRealtime, uptime, true);
   7020                 }
   7021             } else if (level < 96) {
   7022                 if (!mRecordingHistory) {
   7023                     mRecordingHistory = true;
   7024                     startRecordingHistory(elapsedRealtime, uptime, true);
   7025                 }
   7026             }
   7027             mCurrentBatteryLevel = level;
   7028             if (mDischargePlugLevel < 0) {
   7029                 mDischargePlugLevel = level;
   7030             }
   7031             if (onBattery != mOnBattery) {
   7032                 mHistoryCur.batteryLevel = (byte)level;
   7033                 mHistoryCur.batteryStatus = (byte)status;
   7034                 mHistoryCur.batteryHealth = (byte)health;
   7035                 mHistoryCur.batteryPlugType = (byte)plugType;
   7036                 mHistoryCur.batteryTemperature = (short)temp;
   7037                 mHistoryCur.batteryVoltage = (char)volt;
   7038                 setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
   7039             } else {
   7040                 boolean changed = false;
   7041                 if (mHistoryCur.batteryLevel != level) {
   7042                     mHistoryCur.batteryLevel = (byte)level;
   7043                     changed = true;
   7044                 }
   7045                 if (mHistoryCur.batteryStatus != status) {
   7046                     mHistoryCur.batteryStatus = (byte)status;
   7047                     changed = true;
   7048                 }
   7049                 if (mHistoryCur.batteryHealth != health) {
   7050                     mHistoryCur.batteryHealth = (byte)health;
   7051                     changed = true;
   7052                 }
   7053                 if (mHistoryCur.batteryPlugType != plugType) {
   7054                     mHistoryCur.batteryPlugType = (byte)plugType;
   7055                     changed = true;
   7056                 }
   7057                 if (temp >= (mHistoryCur.batteryTemperature+10)
   7058                         || temp <= (mHistoryCur.batteryTemperature-10)) {
   7059                     mHistoryCur.batteryTemperature = (short)temp;
   7060                     changed = true;
   7061                 }
   7062                 if (volt > (mHistoryCur.batteryVoltage+20)
   7063                         || volt < (mHistoryCur.batteryVoltage-20)) {
   7064                     mHistoryCur.batteryVoltage = (char)volt;
   7065                     changed = true;
   7066                 }
   7067                 if (changed) {
   7068                     addHistoryRecordLocked(elapsedRealtime, uptime);
   7069                 }
   7070                 long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
   7071                         | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
   7072                         | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
   7073                 if (onBattery) {
   7074                     if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
   7075                         mNumDischargeStepDurations = addLevelSteps(mDischargeStepDurations,
   7076                                 mNumDischargeStepDurations, mLastDischargeStepTime,
   7077                                 mLastDischargeStepLevel - level, modeBits, elapsedRealtime);
   7078                         mLastDischargeStepLevel = level;
   7079                         mMinDischargeStepLevel = level;
   7080                         mLastDischargeStepTime = elapsedRealtime;
   7081                         mInitStepMode = mCurStepMode;
   7082                         mModStepMode = 0;
   7083                     }
   7084                 } else {
   7085                     if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
   7086                         mNumChargeStepDurations = addLevelSteps(mChargeStepDurations,
   7087                                 mNumChargeStepDurations, mLastChargeStepTime,
   7088                                 level - mLastChargeStepLevel, modeBits, elapsedRealtime);
   7089                         mLastChargeStepLevel = level;
   7090                         mMaxChargeStepLevel = level;
   7091                         mLastChargeStepTime = elapsedRealtime;
   7092                         mInitStepMode = mCurStepMode;
   7093                         mModStepMode = 0;
   7094                     }
   7095                 }
   7096             }
   7097             if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
   7098                 // We don't record history while we are plugged in and fully charged.
   7099                 // The next time we are unplugged, history will be cleared.
   7100                 mRecordingHistory = DEBUG;
   7101             }
   7102         }
   7103     }
   7104 
   7105     public void updateKernelWakelocksLocked() {
   7106         Map<String, KernelWakelockStats> m = readKernelWakelockStats();
   7107 
   7108         if (m == null) {
   7109             // Not crashing might make board bringup easier.
   7110             Slog.w(TAG, "Couldn't get kernel wake lock stats");
   7111             return;
   7112         }
   7113 
   7114         for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) {
   7115             String name = ent.getKey();
   7116             KernelWakelockStats kws = ent.getValue();
   7117 
   7118             SamplingTimer kwlt = mKernelWakelockStats.get(name);
   7119             if (kwlt == null) {
   7120                 kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase,
   7121                         true /* track reported val */);
   7122                 mKernelWakelockStats.put(name, kwlt);
   7123             }
   7124             kwlt.updateCurrentReportedCount(kws.mCount);
   7125             kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
   7126             kwlt.setUpdateVersion(sKernelWakelockUpdateVersion);
   7127         }
   7128 
   7129         if (m.size() != mKernelWakelockStats.size()) {
   7130             // Set timers to stale if they didn't appear in /proc/wakelocks this time.
   7131             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
   7132                 SamplingTimer st = ent.getValue();
   7133                 if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) {
   7134                     st.setStale();
   7135                 }
   7136             }
   7137         }
   7138     }
   7139 
   7140     static final int NET_UPDATE_MOBILE = 1<<0;
   7141     static final int NET_UPDATE_WIFI = 1<<1;
   7142     static final int NET_UPDATE_ALL = 0xffff;
   7143 
   7144     private void updateNetworkActivityLocked(int which, long elapsedRealtimeMs) {
   7145         if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return;
   7146 
   7147         if ((which&NET_UPDATE_MOBILE) != 0 && mMobileIfaces.length > 0) {
   7148             final NetworkStats snapshot;
   7149             final NetworkStats last = mCurMobileSnapshot;
   7150             try {
   7151                 snapshot = mNetworkStatsFactory.readNetworkStatsDetail(UID_ALL,
   7152                         mMobileIfaces, NetworkStats.TAG_NONE, mLastMobileSnapshot);
   7153             } catch (IOException e) {
   7154                 Log.wtf(TAG, "Failed to read mobile network stats", e);
   7155                 return;
   7156             }
   7157 
   7158             mCurMobileSnapshot = snapshot;
   7159             mLastMobileSnapshot = last;
   7160 
   7161             if (mOnBatteryInternal) {
   7162                 final NetworkStats delta = NetworkStats.subtract(snapshot, last,
   7163                         null, null, mTmpNetworkStats);
   7164                 mTmpNetworkStats = delta;
   7165 
   7166                 long radioTime = mMobileRadioActivePerAppTimer.checkpointRunningLocked(
   7167                         elapsedRealtimeMs);
   7168                 long totalPackets = delta.getTotalPackets();
   7169 
   7170                 final int size = delta.size();
   7171                 for (int i = 0; i < size; i++) {
   7172                     final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
   7173 
   7174                     if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
   7175 
   7176                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
   7177                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
   7178                             entry.rxPackets);
   7179                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
   7180                             entry.txPackets);
   7181 
   7182                     if (radioTime > 0) {
   7183                         // Distribute total radio active time in to this app.
   7184                         long appPackets = entry.rxPackets + entry.txPackets;
   7185                         long appRadioTime = (radioTime*appPackets)/totalPackets;
   7186                         u.noteMobileRadioActiveTimeLocked(appRadioTime);
   7187                         // Remove this app from the totals, so that we don't lose any time
   7188                         // due to rounding.
   7189                         radioTime -= appRadioTime;
   7190                         totalPackets -= appPackets;
   7191                     }
   7192 
   7193                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
   7194                             entry.rxBytes);
   7195                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
   7196                             entry.txBytes);
   7197                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
   7198                             entry.rxPackets);
   7199                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
   7200                             entry.txPackets);
   7201                 }
   7202 
   7203                 if (radioTime > 0) {
   7204                     // Whoops, there is some radio time we can't blame on an app!
   7205                     mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
   7206                     mMobileRadioActiveUnknownCount.addCountLocked(1);
   7207                 }
   7208             }
   7209         }
   7210 
   7211         if ((which&NET_UPDATE_WIFI) != 0 && mWifiIfaces.length > 0) {
   7212             final NetworkStats snapshot;
   7213             final NetworkStats last = mCurWifiSnapshot;
   7214             try {
   7215                 snapshot = mNetworkStatsFactory.readNetworkStatsDetail(UID_ALL,
   7216                         mWifiIfaces, NetworkStats.TAG_NONE, mLastWifiSnapshot);
   7217             } catch (IOException e) {
   7218                 Log.wtf(TAG, "Failed to read wifi network stats", e);
   7219                 return;
   7220             }
   7221 
   7222             mCurWifiSnapshot = snapshot;
   7223             mLastWifiSnapshot = last;
   7224 
   7225             if (mOnBatteryInternal) {
   7226                 final NetworkStats delta = NetworkStats.subtract(snapshot, last,
   7227                         null, null, mTmpNetworkStats);
   7228                 mTmpNetworkStats = delta;
   7229 
   7230                 final int size = delta.size();
   7231                 for (int i = 0; i < size; i++) {
   7232                     final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
   7233 
   7234                     if (DEBUG) {
   7235                         final NetworkStats.Entry cur = snapshot.getValues(i, null);
   7236                         Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
   7237                                 + " tx=" + entry.txBytes + ", cur rx=" + cur.rxBytes
   7238                                 + " tx=" + cur.txBytes);
   7239                     }
   7240 
   7241                     if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
   7242 
   7243                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
   7244                     u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
   7245                             entry.rxPackets);
   7246                     u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
   7247                             entry.txPackets);
   7248 
   7249                     mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
   7250                             entry.rxBytes);
   7251                     mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
   7252                             entry.txBytes);
   7253                     mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
   7254                             entry.rxPackets);
   7255                     mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
   7256                             entry.txPackets);
   7257                 }
   7258             }
   7259         }
   7260     }
   7261 
   7262     public long getAwakeTimeBattery() {
   7263         return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
   7264     }
   7265 
   7266     public long getAwakeTimePlugged() {
   7267         return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
   7268     }
   7269 
   7270     @Override
   7271     public long computeUptime(long curTime, int which) {
   7272         switch (which) {
   7273             case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
   7274             case STATS_CURRENT: return (curTime-mUptimeStart);
   7275             case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
   7276         }
   7277         return 0;
   7278     }
   7279 
   7280     @Override
   7281     public long computeRealtime(long curTime, int which) {
   7282         switch (which) {
   7283             case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
   7284             case STATS_CURRENT: return (curTime-mRealtimeStart);
   7285             case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
   7286         }
   7287         return 0;
   7288     }
   7289 
   7290     @Override
   7291     public long computeBatteryUptime(long curTime, int which) {
   7292         return mOnBatteryTimeBase.computeUptime(curTime, which);
   7293     }
   7294 
   7295     @Override
   7296     public long computeBatteryRealtime(long curTime, int which) {
   7297         return mOnBatteryTimeBase.computeRealtime(curTime, which);
   7298     }
   7299 
   7300     @Override
   7301     public long computeBatteryScreenOffUptime(long curTime, int which) {
   7302         return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
   7303     }
   7304 
   7305     @Override
   7306     public long computeBatteryScreenOffRealtime(long curTime, int which) {
   7307         return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
   7308     }
   7309 
   7310     private long computeTimePerLevel(long[] steps, int numSteps) {
   7311         // For now we'll do a simple average across all steps.
   7312         if (numSteps <= 0) {
   7313             return -1;
   7314         }
   7315         long total = 0;
   7316         for (int i=0; i<numSteps; i++) {
   7317             total += steps[i] & STEP_LEVEL_TIME_MASK;
   7318         }
   7319         return total / numSteps;
   7320         /*
   7321         long[] buckets = new long[numSteps];
   7322         int numBuckets = 0;
   7323         int numToAverage = 4;
   7324         int i = 0;
   7325         while (i < numSteps) {
   7326             long totalTime = 0;
   7327             int num = 0;
   7328             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
   7329                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
   7330                 num++;
   7331             }
   7332             buckets[numBuckets] = totalTime / num;
   7333             numBuckets++;
   7334             numToAverage *= 2;
   7335             i += num;
   7336         }
   7337         if (numBuckets < 1) {
   7338             return -1;
   7339         }
   7340         long averageTime = buckets[numBuckets-1];
   7341         for (i=numBuckets-2; i>=0; i--) {
   7342             averageTime = (averageTime + buckets[i]) / 2;
   7343         }
   7344         return averageTime;
   7345         */
   7346     }
   7347 
   7348     @Override
   7349     public long computeBatteryTimeRemaining(long curTime) {
   7350         if (!mOnBattery) {
   7351             return -1;
   7352         }
   7353         /* Simple implementation just looks at the average discharge per level across the
   7354            entire sample period.
   7355         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
   7356         if (discharge < 2) {
   7357             return -1;
   7358         }
   7359         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
   7360         if (duration < 1000*1000) {
   7361             return -1;
   7362         }
   7363         long usPerLevel = duration/discharge;
   7364         return usPerLevel * mCurrentBatteryLevel;
   7365         */
   7366         if (mNumDischargeStepDurations < 1) {
   7367             return -1;
   7368         }
   7369         long msPerLevel = computeTimePerLevel(mDischargeStepDurations, mNumDischargeStepDurations);
   7370         if (msPerLevel <= 0) {
   7371             return -1;
   7372         }
   7373         return (msPerLevel * mCurrentBatteryLevel) * 1000;
   7374     }
   7375 
   7376     public int getNumDischargeStepDurations() {
   7377         return mNumDischargeStepDurations;
   7378     }
   7379 
   7380     public long[] getDischargeStepDurationsArray() {
   7381         return mDischargeStepDurations;
   7382     }
   7383 
   7384     @Override
   7385     public long computeChargeTimeRemaining(long curTime) {
   7386         if (mOnBattery) {
   7387             // Not yet working.
   7388             return -1;
   7389         }
   7390         /* Broken
   7391         int curLevel = mCurrentBatteryLevel;
   7392         int plugLevel = mDischargePlugLevel;
   7393         if (plugLevel < 0 || curLevel < (plugLevel+1)) {
   7394             return -1;
   7395         }
   7396         long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
   7397         if (duration < 1000*1000) {
   7398             return -1;
   7399         }
   7400         long usPerLevel = duration/(curLevel-plugLevel);
   7401         return usPerLevel * (100-curLevel);
   7402         */
   7403         if (mNumChargeStepDurations < 1) {
   7404             return -1;
   7405         }
   7406         long msPerLevel = computeTimePerLevel(mChargeStepDurations, mNumChargeStepDurations);
   7407         if (msPerLevel <= 0) {
   7408             return -1;
   7409         }
   7410         return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
   7411     }
   7412 
   7413     public int getNumChargeStepDurations() {
   7414         return mNumChargeStepDurations;
   7415     }
   7416 
   7417     public long[] getChargeStepDurationsArray() {
   7418         return mChargeStepDurations;
   7419     }
   7420 
   7421     long getBatteryUptimeLocked() {
   7422         return mOnBatteryTimeBase.getUptime(SystemClock.uptimeMillis() * 1000);
   7423     }
   7424 
   7425     @Override
   7426     public long getBatteryUptime(long curTime) {
   7427         return mOnBatteryTimeBase.getUptime(curTime);
   7428     }
   7429 
   7430     @Override
   7431     public long getBatteryRealtime(long curTime) {
   7432         return mOnBatteryTimeBase.getRealtime(curTime);
   7433     }
   7434 
   7435     @Override
   7436     public int getDischargeStartLevel() {
   7437         synchronized(this) {
   7438             return getDischargeStartLevelLocked();
   7439         }
   7440     }
   7441 
   7442     public int getDischargeStartLevelLocked() {
   7443             return mDischargeUnplugLevel;
   7444     }
   7445 
   7446     @Override
   7447     public int getDischargeCurrentLevel() {
   7448         synchronized(this) {
   7449             return getDischargeCurrentLevelLocked();
   7450         }
   7451     }
   7452 
   7453     public int getDischargeCurrentLevelLocked() {
   7454         return mDischargeCurrentLevel;
   7455     }
   7456 
   7457     @Override
   7458     public int getLowDischargeAmountSinceCharge() {
   7459         synchronized(this) {
   7460             int val = mLowDischargeAmountSinceCharge;
   7461             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
   7462                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
   7463             }
   7464             return val;
   7465         }
   7466     }
   7467 
   7468     @Override
   7469     public int getHighDischargeAmountSinceCharge() {
   7470         synchronized(this) {
   7471             int val = mHighDischargeAmountSinceCharge;
   7472             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
   7473                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
   7474             }
   7475             return val;
   7476         }
   7477     }
   7478 
   7479     @Override
   7480     public int getDischargeAmount(int which) {
   7481         int dischargeAmount = which == STATS_SINCE_CHARGED
   7482                 ? getHighDischargeAmountSinceCharge()
   7483                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
   7484         if (dischargeAmount < 0) {
   7485             dischargeAmount = 0;
   7486         }
   7487         return dischargeAmount;
   7488     }
   7489 
   7490     public int getDischargeAmountScreenOn() {
   7491         synchronized(this) {
   7492             int val = mDischargeAmountScreenOn;
   7493             if (mOnBattery && mScreenState == Display.STATE_ON
   7494                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
   7495                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
   7496             }
   7497             return val;
   7498         }
   7499     }
   7500 
   7501     public int getDischargeAmountScreenOnSinceCharge() {
   7502         synchronized(this) {
   7503             int val = mDischargeAmountScreenOnSinceCharge;
   7504             if (mOnBattery && mScreenState == Display.STATE_ON
   7505                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
   7506                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
   7507             }
   7508             return val;
   7509         }
   7510     }
   7511 
   7512     public int getDischargeAmountScreenOff() {
   7513         synchronized(this) {
   7514             int val = mDischargeAmountScreenOff;
   7515             if (mOnBattery && mScreenState != Display.STATE_ON
   7516                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
   7517                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
   7518             }
   7519             return val;
   7520         }
   7521     }
   7522 
   7523     public int getDischargeAmountScreenOffSinceCharge() {
   7524         synchronized(this) {
   7525             int val = mDischargeAmountScreenOffSinceCharge;
   7526             if (mOnBattery && mScreenState != Display.STATE_ON
   7527                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
   7528                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
   7529             }
   7530             return val;
   7531         }
   7532     }
   7533 
   7534     @Override
   7535     public int getCpuSpeedSteps() {
   7536         return sNumSpeedSteps;
   7537     }
   7538 
   7539     /**
   7540      * Retrieve the statistics object for a particular uid, creating if needed.
   7541      */
   7542     public Uid getUidStatsLocked(int uid) {
   7543         Uid u = mUidStats.get(uid);
   7544         if (u == null) {
   7545             u = new Uid(uid);
   7546             mUidStats.put(uid, u);
   7547         }
   7548         return u;
   7549     }
   7550 
   7551     /**
   7552      * Remove the statistics object for a particular uid.
   7553      */
   7554     public void removeUidStatsLocked(int uid) {
   7555         mUidStats.remove(uid);
   7556     }
   7557 
   7558     /**
   7559      * Retrieve the statistics object for a particular process, creating
   7560      * if needed.
   7561      */
   7562     public Uid.Proc getProcessStatsLocked(int uid, String name) {
   7563         uid = mapUid(uid);
   7564         Uid u = getUidStatsLocked(uid);
   7565         return u.getProcessStatsLocked(name);
   7566     }
   7567 
   7568     /**
   7569      * Retrieve the statistics object for a particular process, creating
   7570      * if needed.
   7571      */
   7572     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
   7573         uid = mapUid(uid);
   7574         Uid u = getUidStatsLocked(uid);
   7575         return u.getPackageStatsLocked(pkg);
   7576     }
   7577 
   7578     /**
   7579      * Retrieve the statistics object for a particular service, creating
   7580      * if needed.
   7581      */
   7582     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
   7583         uid = mapUid(uid);
   7584         Uid u = getUidStatsLocked(uid);
   7585         return u.getServiceStatsLocked(pkg, name);
   7586     }
   7587 
   7588     /**
   7589      * Massage data to distribute any reasonable work down to more specific
   7590      * owners.  Must only be called on a dead BatteryStats object!
   7591      */
   7592     public void distributeWorkLocked(int which) {
   7593         // Aggregate all CPU time associated with WIFI.
   7594         Uid wifiUid = mUidStats.get(Process.WIFI_UID);
   7595         if (wifiUid != null) {
   7596             long uSecTime = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which);
   7597             for (int ip=wifiUid.mProcessStats.size()-1; ip>=0; ip--) {
   7598                 Uid.Proc proc = wifiUid.mProcessStats.valueAt(ip);
   7599                 long totalRunningTime = getGlobalWifiRunningTime(uSecTime, which);
   7600                 for (int i=0; i<mUidStats.size(); i++) {
   7601                     Uid uid = mUidStats.valueAt(i);
   7602                     if (uid.mUid != Process.WIFI_UID) {
   7603                         long uidRunningTime = uid.getWifiRunningTime(uSecTime, which);
   7604                         if (uidRunningTime > 0) {
   7605                             Uid.Proc uidProc = uid.getProcessStatsLocked("*wifi*");
   7606                             long time = proc.getUserTime(which);
   7607                             time = (time*uidRunningTime)/totalRunningTime;
   7608                             uidProc.mUserTime += time;
   7609                             proc.mUserTime -= time;
   7610                             time = proc.getSystemTime(which);
   7611                             time = (time*uidRunningTime)/totalRunningTime;
   7612                             uidProc.mSystemTime += time;
   7613                             proc.mSystemTime -= time;
   7614                             time = proc.getForegroundTime(which);
   7615                             time = (time*uidRunningTime)/totalRunningTime;
   7616                             uidProc.mForegroundTime += time;
   7617                             proc.mForegroundTime -= time;
   7618                             for (int sb=0; sb<proc.mSpeedBins.length; sb++) {
   7619                                 SamplingCounter sc = proc.mSpeedBins[sb];
   7620                                 if (sc != null) {
   7621                                     time = sc.getCountLocked(which);
   7622                                     time = (time*uidRunningTime)/totalRunningTime;
   7623                                     SamplingCounter uidSc = uidProc.mSpeedBins[sb];
   7624                                     if (uidSc == null) {
   7625                                         uidSc = new SamplingCounter(mOnBatteryTimeBase);
   7626                                         uidProc.mSpeedBins[sb] = uidSc;
   7627                                     }
   7628                                     uidSc.mCount.addAndGet((int)time);
   7629                                     sc.mCount.addAndGet((int)-time);
   7630                                 }
   7631                             }
   7632                             totalRunningTime -= uidRunningTime;
   7633                         }
   7634                     }
   7635                 }
   7636             }
   7637         }
   7638     }
   7639 
   7640     public void shutdownLocked() {
   7641         recordShutdownLocked(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
   7642         writeSyncLocked();
   7643         mShuttingDown = true;
   7644     }
   7645 
   7646     Parcel mPendingWrite = null;
   7647     final ReentrantLock mWriteLock = new ReentrantLock();
   7648 
   7649     public void writeAsyncLocked() {
   7650         writeLocked(false);
   7651     }
   7652 
   7653     public void writeSyncLocked() {
   7654         writeLocked(true);
   7655     }
   7656 
   7657     void writeLocked(boolean sync) {
   7658         if (mFile == null) {
   7659             Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
   7660             return;
   7661         }
   7662 
   7663         if (mShuttingDown) {
   7664             return;
   7665         }
   7666 
   7667         Parcel out = Parcel.obtain();
   7668         writeSummaryToParcel(out, true);
   7669         mLastWriteTime = SystemClock.elapsedRealtime();
   7670 
   7671         if (mPendingWrite != null) {
   7672             mPendingWrite.recycle();
   7673         }
   7674         mPendingWrite = out;
   7675 
   7676         if (sync) {
   7677             commitPendingDataToDisk();
   7678         } else {
   7679             BackgroundThread.getHandler().post(new Runnable() {
   7680                 @Override public void run() {
   7681                     commitPendingDataToDisk();
   7682                 }
   7683             });
   7684         }
   7685     }
   7686 
   7687     public void commitPendingDataToDisk() {
   7688         final Parcel next;
   7689         synchronized (this) {
   7690             next = mPendingWrite;
   7691             mPendingWrite = null;
   7692             if (next == null) {
   7693                 return;
   7694             }
   7695 
   7696             mWriteLock.lock();
   7697         }
   7698 
   7699         try {
   7700             FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
   7701             stream.write(next.marshall());
   7702             stream.flush();
   7703             FileUtils.sync(stream);
   7704             stream.close();
   7705             mFile.commit();
   7706         } catch (IOException e) {
   7707             Slog.w("BatteryStats", "Error writing battery statistics", e);
   7708             mFile.rollback();
   7709         } finally {
   7710             next.recycle();
   7711             mWriteLock.unlock();
   7712         }
   7713     }
   7714 
   7715     public void readLocked() {
   7716         if (mFile == null) {
   7717             Slog.w("BatteryStats", "readLocked: no file associated with this instance");
   7718             return;
   7719         }
   7720 
   7721         mUidStats.clear();
   7722 
   7723         try {
   7724             File file = mFile.chooseForRead();
   7725             if (!file.exists()) {
   7726                 return;
   7727             }
   7728             FileInputStream stream = new FileInputStream(file);
   7729 
   7730             byte[] raw = BatteryStatsHelper.readFully(stream);
   7731             Parcel in = Parcel.obtain();
   7732             in.unmarshall(raw, 0, raw.length);
   7733             in.setDataPosition(0);
   7734             stream.close();
   7735 
   7736             readSummaryFromParcel(in);
   7737         } catch(Exception e) {
   7738             Slog.e("BatteryStats", "Error reading battery statistics", e);
   7739         }
   7740 
   7741         mEndPlatformVersion = Build.ID;
   7742 
   7743         if (mHistoryBuffer.dataPosition() > 0) {
   7744             mRecordingHistory = true;
   7745             final long elapsedRealtime = SystemClock.elapsedRealtime();
   7746             final long uptime = SystemClock.uptimeMillis();
   7747             if (USE_OLD_HISTORY) {
   7748                 addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
   7749             }
   7750             addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
   7751             startRecordingHistory(elapsedRealtime, uptime, false);
   7752         }
   7753     }
   7754 
   7755     public int describeContents() {
   7756         return 0;
   7757     }
   7758 
   7759     void readHistory(Parcel in, boolean andOldHistory) {
   7760         final long historyBaseTime = in.readLong();
   7761 
   7762         mHistoryBuffer.setDataSize(0);
   7763         mHistoryBuffer.setDataPosition(0);
   7764         mHistoryTagPool.clear();
   7765         mNextHistoryTagIdx = 0;
   7766         mNumHistoryTagChars = 0;
   7767 
   7768         int numTags = in.readInt();
   7769         for (int i=0; i<numTags; i++) {
   7770             int idx = in.readInt();
   7771             String str = in.readString();
   7772             int uid = in.readInt();
   7773             HistoryTag tag = new HistoryTag();
   7774             tag.string = str;
   7775             tag.uid = uid;
   7776             tag.poolIdx = idx;
   7777             mHistoryTagPool.put(tag, idx);
   7778             if (idx >= mNextHistoryTagIdx) {
   7779                 mNextHistoryTagIdx = idx+1;
   7780             }
   7781             mNumHistoryTagChars += tag.string.length() + 1;
   7782         }
   7783 
   7784         int bufSize = in.readInt();
   7785         int curPos = in.dataPosition();
   7786         if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
   7787             Slog.w(TAG, "File corrupt: history data buffer too large " + bufSize);
   7788         } else if ((bufSize&~3) != bufSize) {
   7789             Slog.w(TAG, "File corrupt: history data buffer not aligned " + bufSize);
   7790         } else {
   7791             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
   7792                     + " bytes at " + curPos);
   7793             mHistoryBuffer.appendFrom(in, curPos, bufSize);
   7794             in.setDataPosition(curPos + bufSize);
   7795         }
   7796 
   7797         if (andOldHistory) {
   7798             readOldHistory(in);
   7799         }
   7800 
   7801         if (DEBUG_HISTORY) {
   7802             StringBuilder sb = new StringBuilder(128);
   7803             sb.append("****************** OLD mHistoryBaseTime: ");
   7804             TimeUtils.formatDuration(mHistoryBaseTime, sb);
   7805             Slog.i(TAG, sb.toString());
   7806         }
   7807         mHistoryBaseTime = historyBaseTime;
   7808         if (DEBUG_HISTORY) {
   7809             StringBuilder sb = new StringBuilder(128);
   7810             sb.append("****************** NEW mHistoryBaseTime: ");
   7811             TimeUtils.formatDuration(mHistoryBaseTime, sb);
   7812             Slog.i(TAG, sb.toString());
   7813         }
   7814 
   7815         // We are just arbitrarily going to insert 1 minute from the sample of
   7816         // the last run until samples in this run.
   7817         if (mHistoryBaseTime > 0) {
   7818             long oldnow = SystemClock.elapsedRealtime();
   7819             mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
   7820             if (DEBUG_HISTORY) {
   7821                 StringBuilder sb = new StringBuilder(128);
   7822                 sb.append("****************** ADJUSTED mHistoryBaseTime: ");
   7823                 TimeUtils.formatDuration(mHistoryBaseTime, sb);
   7824                 Slog.i(TAG, sb.toString());
   7825             }
   7826         }
   7827     }
   7828 
   7829     void readOldHistory(Parcel in) {
   7830         if (!USE_OLD_HISTORY) {
   7831             return;
   7832         }
   7833         mHistory = mHistoryEnd = mHistoryCache = null;
   7834         long time;
   7835         while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
   7836             HistoryItem rec = new HistoryItem(time, in);
   7837             addHistoryRecordLocked(rec);
   7838         }
   7839     }
   7840 
   7841     void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
   7842         if (DEBUG_HISTORY) {
   7843             StringBuilder sb = new StringBuilder(128);
   7844             sb.append("****************** WRITING mHistoryBaseTime: ");
   7845             TimeUtils.formatDuration(mHistoryBaseTime, sb);
   7846             sb.append(" mLastHistoryElapsedRealtime: ");
   7847             TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
   7848             Slog.i(TAG, sb.toString());
   7849         }
   7850         out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
   7851         if (!inclData) {
   7852             out.writeInt(0);
   7853             out.writeInt(0);
   7854             return;
   7855         }
   7856         out.writeInt(mHistoryTagPool.size());
   7857         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
   7858             HistoryTag tag = ent.getKey();
   7859             out.writeInt(ent.getValue());
   7860             out.writeString(tag.string);
   7861             out.writeInt(tag.uid);
   7862         }
   7863         out.writeInt(mHistoryBuffer.dataSize());
   7864         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
   7865                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
   7866         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
   7867 
   7868         if (andOldHistory) {
   7869             writeOldHistory(out);
   7870         }
   7871     }
   7872 
   7873     void writeOldHistory(Parcel out) {
   7874         if (!USE_OLD_HISTORY) {
   7875             return;
   7876         }
   7877         HistoryItem rec = mHistory;
   7878         while (rec != null) {
   7879             if (rec.time >= 0) rec.writeToParcel(out, 0);
   7880             rec = rec.next;
   7881         }
   7882         out.writeLong(-1);
   7883     }
   7884 
   7885     public void readSummaryFromParcel(Parcel in) {
   7886         final int version = in.readInt();
   7887         if (version != VERSION) {
   7888             Slog.w("BatteryStats", "readFromParcel: version got " + version
   7889                 + ", expected " + VERSION + "; erasing old stats");
   7890             return;
   7891         }
   7892 
   7893         readHistory(in, true);
   7894 
   7895         mStartCount = in.readInt();
   7896         mUptime = in.readLong();
   7897         mRealtime = in.readLong();
   7898         mStartClockTime = in.readLong();
   7899         mStartPlatformVersion = in.readString();
   7900         mEndPlatformVersion = in.readString();
   7901         mOnBatteryTimeBase.readSummaryFromParcel(in);
   7902         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
   7903         mDischargeUnplugLevel = in.readInt();
   7904         mDischargePlugLevel = in.readInt();
   7905         mDischargeCurrentLevel = in.readInt();
   7906         mCurrentBatteryLevel = in.readInt();
   7907         mLowDischargeAmountSinceCharge = in.readInt();
   7908         mHighDischargeAmountSinceCharge = in.readInt();
   7909         mDischargeAmountScreenOnSinceCharge = in.readInt();
   7910         mDischargeAmountScreenOffSinceCharge = in.readInt();
   7911         mNumDischargeStepDurations = in.readInt();
   7912         in.readLongArray(mDischargeStepDurations);
   7913         mNumChargeStepDurations = in.readInt();
   7914         in.readLongArray(mChargeStepDurations);
   7915 
   7916         mStartCount++;
   7917 
   7918         mScreenState = Display.STATE_UNKNOWN;
   7919         mScreenOnTimer.readSummaryFromParcelLocked(in);
   7920         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   7921             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
   7922         }
   7923         mInteractive = false;
   7924         mInteractiveTimer.readSummaryFromParcelLocked(in);
   7925         mPhoneOn = false;
   7926         mLowPowerModeEnabledTimer.readSummaryFromParcelLocked(in);
   7927         mPhoneOnTimer.readSummaryFromParcelLocked(in);
   7928         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   7929             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
   7930         }
   7931         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
   7932         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   7933             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
   7934         }
   7935         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   7936             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
   7937             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
   7938         }
   7939         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
   7940         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
   7941         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
   7942         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
   7943         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
   7944         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
   7945         mWifiOn = false;
   7946         mWifiOnTimer.readSummaryFromParcelLocked(in);
   7947         mGlobalWifiRunning = false;
   7948         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
   7949         for (int i=0; i<NUM_WIFI_STATES; i++) {
   7950             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
   7951         }
   7952         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   7953             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
   7954         }
   7955         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   7956             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
   7957         }
   7958         mBluetoothOn = false;
   7959         mBluetoothOnTimer.readSummaryFromParcelLocked(in);
   7960         for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
   7961             mBluetoothStateTimer[i].readSummaryFromParcelLocked(in);
   7962         }
   7963         mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
   7964         mFlashlightOn = false;
   7965         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
   7966 
   7967         int NKW = in.readInt();
   7968         if (NKW > 10000) {
   7969             Slog.w(TAG, "File corrupt: too many kernel wake locks " + NKW);
   7970             return;
   7971         }
   7972         for (int ikw = 0; ikw < NKW; ikw++) {
   7973             if (in.readInt() != 0) {
   7974                 String kwltName = in.readString();
   7975                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
   7976             }
   7977         }
   7978 
   7979         int NWR = in.readInt();
   7980         if (NWR > 10000) {
   7981             Slog.w(TAG, "File corrupt: too many wakeup reasons " + NWR);
   7982             return;
   7983         }
   7984         for (int iwr = 0; iwr < NWR; iwr++) {
   7985             if (in.readInt() != 0) {
   7986                 String reasonName = in.readString();
   7987                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
   7988             }
   7989         }
   7990 
   7991         sNumSpeedSteps = in.readInt();
   7992         if (sNumSpeedSteps < 0 || sNumSpeedSteps > 100) {
   7993             throw new BadParcelableException("Bad speed steps in data: " + sNumSpeedSteps);
   7994         }
   7995 
   7996         final int NU = in.readInt();
   7997         if (NU > 10000) {
   7998             Slog.w(TAG, "File corrupt: too many uids " + NU);
   7999             return;
   8000         }
   8001         for (int iu = 0; iu < NU; iu++) {
   8002             int uid = in.readInt();
   8003             Uid u = new Uid(uid);
   8004             mUidStats.put(uid, u);
   8005 
   8006             u.mWifiRunning = false;
   8007             if (in.readInt() != 0) {
   8008                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
   8009             }
   8010             u.mFullWifiLockOut = false;
   8011             if (in.readInt() != 0) {
   8012                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
   8013             }
   8014             u.mWifiScanStarted = false;
   8015             if (in.readInt() != 0) {
   8016                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
   8017             }
   8018             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
   8019             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   8020                 if (in.readInt() != 0) {
   8021                     u.makeWifiBatchedScanBin(i, null);
   8022                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
   8023                 }
   8024             }
   8025             u.mWifiMulticastEnabled = false;
   8026             if (in.readInt() != 0) {
   8027                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
   8028             }
   8029             if (in.readInt() != 0) {
   8030                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
   8031             }
   8032             if (in.readInt() != 0) {
   8033                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
   8034             }
   8035             if (in.readInt() != 0) {
   8036                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
   8037             }
   8038             u.mProcessState = Uid.PROCESS_STATE_NONE;
   8039             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
   8040                 if (in.readInt() != 0) {
   8041                     u.makeProcessState(i, null);
   8042                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
   8043                 }
   8044             }
   8045             if (in.readInt() != 0) {
   8046                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
   8047             }
   8048 
   8049             if (in.readInt() != 0) {
   8050                 if (u.mUserActivityCounters == null) {
   8051                     u.initUserActivityLocked();
   8052                 }
   8053                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
   8054                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
   8055                 }
   8056             }
   8057 
   8058             if (in.readInt() != 0) {
   8059                 if (u.mNetworkByteActivityCounters == null) {
   8060                     u.initNetworkActivityLocked();
   8061                 }
   8062                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   8063                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
   8064                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
   8065                 }
   8066                 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
   8067                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
   8068             }
   8069 
   8070             int NW = in.readInt();
   8071             if (NW > 100) {
   8072                 Slog.w(TAG, "File corrupt: too many wake locks " + NW);
   8073                 return;
   8074             }
   8075             for (int iw = 0; iw < NW; iw++) {
   8076                 String wlName = in.readString();
   8077                 u.readWakeSummaryFromParcelLocked(wlName, in);
   8078             }
   8079 
   8080             int NS = in.readInt();
   8081             if (NS > 100) {
   8082                 Slog.w(TAG, "File corrupt: too many syncs " + NS);
   8083                 return;
   8084             }
   8085             for (int is = 0; is < NS; is++) {
   8086                 String name = in.readString();
   8087                 u.readSyncSummaryFromParcelLocked(name, in);
   8088             }
   8089 
   8090             int NJ = in.readInt();
   8091             if (NJ > 100) {
   8092                 Slog.w(TAG, "File corrupt: too many job timers " + NJ);
   8093                 return;
   8094             }
   8095             for (int ij = 0; ij < NJ; ij++) {
   8096                 String name = in.readString();
   8097                 u.readJobSummaryFromParcelLocked(name, in);
   8098             }
   8099 
   8100             int NP = in.readInt();
   8101             if (NP > 1000) {
   8102                 Slog.w(TAG, "File corrupt: too many sensors " + NP);
   8103                 return;
   8104             }
   8105             for (int is = 0; is < NP; is++) {
   8106                 int seNumber = in.readInt();
   8107                 if (in.readInt() != 0) {
   8108                     u.getSensorTimerLocked(seNumber, true)
   8109                             .readSummaryFromParcelLocked(in);
   8110                 }
   8111             }
   8112 
   8113             NP = in.readInt();
   8114             if (NP > 1000) {
   8115                 Slog.w(TAG, "File corrupt: too many processes " + NP);
   8116                 return;
   8117             }
   8118             for (int ip = 0; ip < NP; ip++) {
   8119                 String procName = in.readString();
   8120                 Uid.Proc p = u.getProcessStatsLocked(procName);
   8121                 p.mUserTime = p.mLoadedUserTime = in.readLong();
   8122                 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
   8123                 p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
   8124                 p.mStarts = p.mLoadedStarts = in.readInt();
   8125                 p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
   8126                 p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
   8127                 int NSB = in.readInt();
   8128                 if (NSB > 100) {
   8129                     Slog.w(TAG, "File corrupt: too many speed bins " + NSB);
   8130                     return;
   8131                 }
   8132                 p.mSpeedBins = new SamplingCounter[NSB];
   8133                 for (int i=0; i<NSB; i++) {
   8134                     if (in.readInt() != 0) {
   8135                         p.mSpeedBins[i] = new SamplingCounter(mOnBatteryTimeBase);
   8136                         p.mSpeedBins[i].readSummaryFromParcelLocked(in);
   8137                     }
   8138                 }
   8139                 if (!p.readExcessivePowerFromParcelLocked(in)) {
   8140                     return;
   8141                 }
   8142             }
   8143 
   8144             NP = in.readInt();
   8145             if (NP > 10000) {
   8146                 Slog.w(TAG, "File corrupt: too many packages " + NP);
   8147                 return;
   8148             }
   8149             for (int ip = 0; ip < NP; ip++) {
   8150                 String pkgName = in.readString();
   8151                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
   8152                 p.mWakeups = p.mLoadedWakeups = in.readInt();
   8153                 NS = in.readInt();
   8154                 if (NS > 1000) {
   8155                     Slog.w(TAG, "File corrupt: too many services " + NS);
   8156                     return;
   8157                 }
   8158                 for (int is = 0; is < NS; is++) {
   8159                     String servName = in.readString();
   8160                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
   8161                     s.mStartTime = s.mLoadedStartTime = in.readLong();
   8162                     s.mStarts = s.mLoadedStarts = in.readInt();
   8163                     s.mLaunches = s.mLoadedLaunches = in.readInt();
   8164                 }
   8165             }
   8166         }
   8167     }
   8168 
   8169     /**
   8170      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
   8171      * disk.  This format does not allow a lossless round-trip.
   8172      *
   8173      * @param out the Parcel to be written to.
   8174      */
   8175     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
   8176         pullPendingStateUpdatesLocked();
   8177 
   8178         // Pull the clock time.  This may update the time and make a new history entry
   8179         // if we had originally pulled a time before the RTC was set.
   8180         long startClockTime = getStartClockTime();
   8181 
   8182         final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
   8183         final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
   8184 
   8185         out.writeInt(VERSION);
   8186 
   8187         writeHistory(out, inclHistory, true);
   8188 
   8189         out.writeInt(mStartCount);
   8190         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
   8191         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
   8192         out.writeLong(startClockTime);
   8193         out.writeString(mStartPlatformVersion);
   8194         out.writeString(mEndPlatformVersion);
   8195         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
   8196         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
   8197         out.writeInt(mDischargeUnplugLevel);
   8198         out.writeInt(mDischargePlugLevel);
   8199         out.writeInt(mDischargeCurrentLevel);
   8200         out.writeInt(mCurrentBatteryLevel);
   8201         out.writeInt(getLowDischargeAmountSinceCharge());
   8202         out.writeInt(getHighDischargeAmountSinceCharge());
   8203         out.writeInt(getDischargeAmountScreenOnSinceCharge());
   8204         out.writeInt(getDischargeAmountScreenOffSinceCharge());
   8205         out.writeInt(mNumDischargeStepDurations);
   8206         out.writeLongArray(mDischargeStepDurations);
   8207         out.writeInt(mNumChargeStepDurations);
   8208         out.writeLongArray(mChargeStepDurations);
   8209 
   8210         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8211         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   8212             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8213         }
   8214         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8215         mLowPowerModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8216         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8217         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   8218             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8219         }
   8220         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8221         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   8222             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8223         }
   8224         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   8225             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
   8226             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
   8227         }
   8228         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8229         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8230         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
   8231         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
   8232         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
   8233         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8234         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8235         for (int i=0; i<NUM_WIFI_STATES; i++) {
   8236             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8237         }
   8238         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   8239             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8240         }
   8241         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   8242             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8243         }
   8244         mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8245         for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
   8246             mBluetoothStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8247         }
   8248         out.writeInt(mNumConnectivityChange);
   8249         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8250 
   8251         out.writeInt(mKernelWakelockStats.size());
   8252         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
   8253             Timer kwlt = ent.getValue();
   8254             if (kwlt != null) {
   8255                 out.writeInt(1);
   8256                 out.writeString(ent.getKey());
   8257                 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8258             } else {
   8259                 out.writeInt(0);
   8260             }
   8261         }
   8262 
   8263         out.writeInt(mWakeupReasonStats.size());
   8264         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
   8265             SamplingTimer timer = ent.getValue();
   8266             if (timer != null) {
   8267                 out.writeInt(1);
   8268                 out.writeString(ent.getKey());
   8269                 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8270             } else {
   8271                 out.writeInt(0);
   8272             }
   8273         }
   8274 
   8275         out.writeInt(sNumSpeedSteps);
   8276         final int NU = mUidStats.size();
   8277         out.writeInt(NU);
   8278         for (int iu = 0; iu < NU; iu++) {
   8279             out.writeInt(mUidStats.keyAt(iu));
   8280             Uid u = mUidStats.valueAt(iu);
   8281 
   8282             if (u.mWifiRunningTimer != null) {
   8283                 out.writeInt(1);
   8284                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8285             } else {
   8286                 out.writeInt(0);
   8287             }
   8288             if (u.mFullWifiLockTimer != null) {
   8289                 out.writeInt(1);
   8290                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8291             } else {
   8292                 out.writeInt(0);
   8293             }
   8294             if (u.mWifiScanTimer != null) {
   8295                 out.writeInt(1);
   8296                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8297             } else {
   8298                 out.writeInt(0);
   8299             }
   8300             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   8301                 if (u.mWifiBatchedScanTimer[i] != null) {
   8302                     out.writeInt(1);
   8303                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8304                 } else {
   8305                     out.writeInt(0);
   8306                 }
   8307             }
   8308             if (u.mWifiMulticastTimer != null) {
   8309                 out.writeInt(1);
   8310                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8311             } else {
   8312                 out.writeInt(0);
   8313             }
   8314             if (u.mAudioTurnedOnTimer != null) {
   8315                 out.writeInt(1);
   8316                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8317             } else {
   8318                 out.writeInt(0);
   8319             }
   8320             if (u.mVideoTurnedOnTimer != null) {
   8321                 out.writeInt(1);
   8322                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8323             } else {
   8324                 out.writeInt(0);
   8325             }
   8326             if (u.mForegroundActivityTimer != null) {
   8327                 out.writeInt(1);
   8328                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8329             } else {
   8330                 out.writeInt(0);
   8331             }
   8332             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
   8333                 if (u.mProcessStateTimer[i] != null) {
   8334                     out.writeInt(1);
   8335                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8336                 } else {
   8337                     out.writeInt(0);
   8338                 }
   8339             }
   8340             if (u.mVibratorOnTimer != null) {
   8341                 out.writeInt(1);
   8342                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8343             } else {
   8344                 out.writeInt(0);
   8345             }
   8346 
   8347             if (u.mUserActivityCounters == null) {
   8348                 out.writeInt(0);
   8349             } else {
   8350                 out.writeInt(1);
   8351                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
   8352                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
   8353                 }
   8354             }
   8355 
   8356             if (u.mNetworkByteActivityCounters == null) {
   8357                 out.writeInt(0);
   8358             } else {
   8359                 out.writeInt(1);
   8360                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   8361                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
   8362                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
   8363                 }
   8364                 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
   8365                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
   8366             }
   8367 
   8368             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
   8369             int NW = wakeStats.size();
   8370             out.writeInt(NW);
   8371             for (int iw=0; iw<NW; iw++) {
   8372                 out.writeString(wakeStats.keyAt(iw));
   8373                 Uid.Wakelock wl = wakeStats.valueAt(iw);
   8374                 if (wl.mTimerFull != null) {
   8375                     out.writeInt(1);
   8376                     wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8377                 } else {
   8378                     out.writeInt(0);
   8379                 }
   8380                 if (wl.mTimerPartial != null) {
   8381                     out.writeInt(1);
   8382                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8383                 } else {
   8384                     out.writeInt(0);
   8385                 }
   8386                 if (wl.mTimerWindow != null) {
   8387                     out.writeInt(1);
   8388                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8389                 } else {
   8390                     out.writeInt(0);
   8391                 }
   8392             }
   8393 
   8394             final ArrayMap<String, StopwatchTimer> syncStats = u.mSyncStats.getMap();
   8395             int NS = syncStats.size();
   8396             out.writeInt(NS);
   8397             for (int is=0; is<NS; is++) {
   8398                 out.writeString(syncStats.keyAt(is));
   8399                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8400             }
   8401 
   8402             final ArrayMap<String, StopwatchTimer> jobStats = u.mJobStats.getMap();
   8403             int NJ = jobStats.size();
   8404             out.writeInt(NJ);
   8405             for (int ij=0; ij<NJ; ij++) {
   8406                 out.writeString(jobStats.keyAt(ij));
   8407                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8408             }
   8409 
   8410             int NSE = u.mSensorStats.size();
   8411             out.writeInt(NSE);
   8412             for (int ise=0; ise<NSE; ise++) {
   8413                 out.writeInt(u.mSensorStats.keyAt(ise));
   8414                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
   8415                 if (se.mTimer != null) {
   8416                     out.writeInt(1);
   8417                     se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   8418                 } else {
   8419                     out.writeInt(0);
   8420                 }
   8421             }
   8422 
   8423             int NP = u.mProcessStats.size();
   8424             out.writeInt(NP);
   8425             for (int ip=0; ip<NP; ip++) {
   8426                 out.writeString(u.mProcessStats.keyAt(ip));
   8427                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
   8428                 out.writeLong(ps.mUserTime);
   8429                 out.writeLong(ps.mSystemTime);
   8430                 out.writeLong(ps.mForegroundTime);
   8431                 out.writeInt(ps.mStarts);
   8432                 out.writeInt(ps.mNumCrashes);
   8433                 out.writeInt(ps.mNumAnrs);
   8434                 final int N = ps.mSpeedBins.length;
   8435                 out.writeInt(N);
   8436                 for (int i=0; i<N; i++) {
   8437                     if (ps.mSpeedBins[i] != null) {
   8438                         out.writeInt(1);
   8439                         ps.mSpeedBins[i].writeSummaryFromParcelLocked(out);
   8440                     } else {
   8441                         out.writeInt(0);
   8442                     }
   8443                 }
   8444                 ps.writeExcessivePowerToParcelLocked(out);
   8445             }
   8446 
   8447             NP = u.mPackageStats.size();
   8448             out.writeInt(NP);
   8449             if (NP > 0) {
   8450                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
   8451                     : u.mPackageStats.entrySet()) {
   8452                     out.writeString(ent.getKey());
   8453                     Uid.Pkg ps = ent.getValue();
   8454                     out.writeInt(ps.mWakeups);
   8455                     NS = ps.mServiceStats.size();
   8456                     out.writeInt(NS);
   8457                     if (NS > 0) {
   8458                         for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent
   8459                                 : ps.mServiceStats.entrySet()) {
   8460                             out.writeString(sent.getKey());
   8461                             BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue();
   8462                             long time = ss.getStartTimeToNowLocked(
   8463                                     mOnBatteryTimeBase.getUptime(NOW_SYS));
   8464                             out.writeLong(time);
   8465                             out.writeInt(ss.mStarts);
   8466                             out.writeInt(ss.mLaunches);
   8467                         }
   8468                     }
   8469                 }
   8470             }
   8471         }
   8472     }
   8473 
   8474     public void readFromParcel(Parcel in) {
   8475         readFromParcelLocked(in);
   8476     }
   8477 
   8478     void readFromParcelLocked(Parcel in) {
   8479         int magic = in.readInt();
   8480         if (magic != MAGIC) {
   8481             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
   8482         }
   8483 
   8484         readHistory(in, false);
   8485 
   8486         mStartCount = in.readInt();
   8487         mStartClockTime = in.readLong();
   8488         mStartPlatformVersion = in.readString();
   8489         mEndPlatformVersion = in.readString();
   8490         mUptime = in.readLong();
   8491         mUptimeStart = in.readLong();
   8492         mRealtime = in.readLong();
   8493         mRealtimeStart = in.readLong();
   8494         mOnBattery = in.readInt() != 0;
   8495         mOnBatteryInternal = false; // we are no longer really running.
   8496         mOnBatteryTimeBase.readFromParcel(in);
   8497         mOnBatteryScreenOffTimeBase.readFromParcel(in);
   8498 
   8499         mScreenState = Display.STATE_UNKNOWN;
   8500         mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase, in);
   8501         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   8502             mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase,
   8503                     in);
   8504         }
   8505         mInteractive = false;
   8506         mInteractiveTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase, in);
   8507         mPhoneOn = false;
   8508         mLowPowerModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
   8509         mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in);
   8510         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   8511             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
   8512                     null, mOnBatteryTimeBase, in);
   8513         }
   8514         mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase, in);
   8515         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   8516             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
   8517                     null, mOnBatteryTimeBase, in);
   8518         }
   8519         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   8520             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
   8521             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
   8522         }
   8523         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
   8524         mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase, in);
   8525         mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase,
   8526                 in);
   8527         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
   8528         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
   8529         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
   8530         mWifiOn = false;
   8531         mWifiOnTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase, in);
   8532         mGlobalWifiRunning = false;
   8533         mGlobalWifiRunningTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase, in);
   8534         for (int i=0; i<NUM_WIFI_STATES; i++) {
   8535             mWifiStateTimer[i] = new StopwatchTimer(null, -600-i,
   8536                     null, mOnBatteryTimeBase, in);
   8537         }
   8538         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   8539             mWifiSupplStateTimer[i] = new StopwatchTimer(null, -700-i,
   8540                     null, mOnBatteryTimeBase, in);
   8541         }
   8542         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   8543             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i,
   8544                     null, mOnBatteryTimeBase, in);
   8545         }
   8546         mBluetoothOn = false;
   8547         mBluetoothOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase, in);
   8548         for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
   8549             mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i,
   8550                     null, mOnBatteryTimeBase, in);
   8551         }
   8552         mNumConnectivityChange = in.readInt();
   8553         mLoadedNumConnectivityChange = in.readInt();
   8554         mUnpluggedNumConnectivityChange = in.readInt();
   8555         mAudioOnNesting = 0;
   8556         mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
   8557         mVideoOnNesting = 0;
   8558         mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
   8559         mFlashlightOn = false;
   8560         mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase, in);
   8561         mDischargeUnplugLevel = in.readInt();
   8562         mDischargePlugLevel = in.readInt();
   8563         mDischargeCurrentLevel = in.readInt();
   8564         mCurrentBatteryLevel = in.readInt();
   8565         mLowDischargeAmountSinceCharge = in.readInt();
   8566         mHighDischargeAmountSinceCharge = in.readInt();
   8567         mDischargeAmountScreenOn = in.readInt();
   8568         mDischargeAmountScreenOnSinceCharge = in.readInt();
   8569         mDischargeAmountScreenOff = in.readInt();
   8570         mDischargeAmountScreenOffSinceCharge = in.readInt();
   8571         mNumDischargeStepDurations = in.readInt();
   8572         in.readLongArray(mDischargeStepDurations);
   8573         mNumChargeStepDurations = in.readInt();
   8574         in.readLongArray(mChargeStepDurations);
   8575         mLastWriteTime = in.readLong();
   8576 
   8577         mBluetoothPingCount = in.readInt();
   8578         mBluetoothPingStart = -1;
   8579 
   8580         mKernelWakelockStats.clear();
   8581         int NKW = in.readInt();
   8582         for (int ikw = 0; ikw < NKW; ikw++) {
   8583             if (in.readInt() != 0) {
   8584                 String wakelockName = in.readString();
   8585                 SamplingTimer kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, in);
   8586                 mKernelWakelockStats.put(wakelockName, kwlt);
   8587             }
   8588         }
   8589 
   8590         mWakeupReasonStats.clear();
   8591         int NWR = in.readInt();
   8592         for (int iwr = 0; iwr < NWR; iwr++) {
   8593             if (in.readInt() != 0) {
   8594                 String reasonName = in.readString();
   8595                 SamplingTimer timer = new SamplingTimer(mOnBatteryTimeBase, in);
   8596                 mWakeupReasonStats.put(reasonName, timer);
   8597             }
   8598         }
   8599 
   8600         mPartialTimers.clear();
   8601         mFullTimers.clear();
   8602         mWindowTimers.clear();
   8603         mWifiRunningTimers.clear();
   8604         mFullWifiLockTimers.clear();
   8605         mWifiScanTimers.clear();
   8606         mWifiBatchedScanTimers.clear();
   8607         mWifiMulticastTimers.clear();
   8608         mAudioTurnedOnTimers.clear();
   8609         mVideoTurnedOnTimers.clear();
   8610 
   8611         sNumSpeedSteps = in.readInt();
   8612 
   8613         int numUids = in.readInt();
   8614         mUidStats.clear();
   8615         for (int i = 0; i < numUids; i++) {
   8616             int uid = in.readInt();
   8617             Uid u = new Uid(uid);
   8618             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
   8619             mUidStats.append(uid, u);
   8620         }
   8621     }
   8622 
   8623     public void writeToParcel(Parcel out, int flags) {
   8624         writeToParcelLocked(out, true, flags);
   8625     }
   8626 
   8627     public void writeToParcelWithoutUids(Parcel out, int flags) {
   8628         writeToParcelLocked(out, false, flags);
   8629     }
   8630 
   8631     @SuppressWarnings("unused")
   8632     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
   8633         // Need to update with current kernel wake lock counts.
   8634         pullPendingStateUpdatesLocked();
   8635 
   8636         // Pull the clock time.  This may update the time and make a new history entry
   8637         // if we had originally pulled a time before the RTC was set.
   8638         long startClockTime = getStartClockTime();
   8639 
   8640         final long uSecUptime = SystemClock.uptimeMillis() * 1000;
   8641         final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
   8642         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
   8643         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
   8644 
   8645         out.writeInt(MAGIC);
   8646 
   8647         writeHistory(out, true, false);
   8648 
   8649         out.writeInt(mStartCount);
   8650         out.writeLong(startClockTime);
   8651         out.writeString(mStartPlatformVersion);
   8652         out.writeString(mEndPlatformVersion);
   8653         out.writeLong(mUptime);
   8654         out.writeLong(mUptimeStart);
   8655         out.writeLong(mRealtime);
   8656         out.writeLong(mRealtimeStart);
   8657         out.writeInt(mOnBattery ? 1 : 0);
   8658         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
   8659         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
   8660 
   8661         mScreenOnTimer.writeToParcel(out, uSecRealtime);
   8662         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   8663             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
   8664         }
   8665         mInteractiveTimer.writeToParcel(out, uSecRealtime);
   8666         mLowPowerModeEnabledTimer.writeToParcel(out, uSecRealtime);
   8667         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
   8668         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   8669             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
   8670         }
   8671         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
   8672         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   8673             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
   8674         }
   8675         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   8676             mNetworkByteActivityCounters[i].writeToParcel(out);
   8677             mNetworkPacketActivityCounters[i].writeToParcel(out);
   8678         }
   8679         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
   8680         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
   8681         mMobileRadioActiveAdjustedTime.writeToParcel(out);
   8682         mMobileRadioActiveUnknownTime.writeToParcel(out);
   8683         mMobileRadioActiveUnknownCount.writeToParcel(out);
   8684         mWifiOnTimer.writeToParcel(out, uSecRealtime);
   8685         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
   8686         for (int i=0; i<NUM_WIFI_STATES; i++) {
   8687             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
   8688         }
   8689         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   8690             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
   8691         }
   8692         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   8693             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
   8694         }
   8695         mBluetoothOnTimer.writeToParcel(out, uSecRealtime);
   8696         for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
   8697             mBluetoothStateTimer[i].writeToParcel(out, uSecRealtime);
   8698         }
   8699         out.writeInt(mNumConnectivityChange);
   8700         out.writeInt(mLoadedNumConnectivityChange);
   8701         out.writeInt(mUnpluggedNumConnectivityChange);
   8702         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
   8703         out.writeInt(mDischargeUnplugLevel);
   8704         out.writeInt(mDischargePlugLevel);
   8705         out.writeInt(mDischargeCurrentLevel);
   8706         out.writeInt(mCurrentBatteryLevel);
   8707         out.writeInt(mLowDischargeAmountSinceCharge);
   8708         out.writeInt(mHighDischargeAmountSinceCharge);
   8709         out.writeInt(mDischargeAmountScreenOn);
   8710         out.writeInt(mDischargeAmountScreenOnSinceCharge);
   8711         out.writeInt(mDischargeAmountScreenOff);
   8712         out.writeInt(mDischargeAmountScreenOffSinceCharge);
   8713         out.writeInt(mNumDischargeStepDurations);
   8714         out.writeLongArray(mDischargeStepDurations);
   8715         out.writeInt(mNumChargeStepDurations);
   8716         out.writeLongArray(mChargeStepDurations);
   8717         out.writeLong(mLastWriteTime);
   8718 
   8719         out.writeInt(getBluetoothPingCount());
   8720 
   8721         if (inclUids) {
   8722             out.writeInt(mKernelWakelockStats.size());
   8723             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
   8724                 SamplingTimer kwlt = ent.getValue();
   8725                 if (kwlt != null) {
   8726                     out.writeInt(1);
   8727                     out.writeString(ent.getKey());
   8728                     kwlt.writeToParcel(out, uSecRealtime);
   8729                 } else {
   8730                     out.writeInt(0);
   8731                 }
   8732             }
   8733             out.writeInt(mWakeupReasonStats.size());
   8734             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
   8735                 SamplingTimer timer = ent.getValue();
   8736                 if (timer != null) {
   8737                     out.writeInt(1);
   8738                     out.writeString(ent.getKey());
   8739                     timer.writeToParcel(out, uSecRealtime);
   8740                 } else {
   8741                     out.writeInt(0);
   8742                 }
   8743             }
   8744         } else {
   8745             out.writeInt(0);
   8746         }
   8747 
   8748         out.writeInt(sNumSpeedSteps);
   8749 
   8750         if (inclUids) {
   8751             int size = mUidStats.size();
   8752             out.writeInt(size);
   8753             for (int i = 0; i < size; i++) {
   8754                 out.writeInt(mUidStats.keyAt(i));
   8755                 Uid uid = mUidStats.valueAt(i);
   8756 
   8757                 uid.writeToParcelLocked(out, uSecRealtime);
   8758             }
   8759         } else {
   8760             out.writeInt(0);
   8761         }
   8762     }
   8763 
   8764     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
   8765         new Parcelable.Creator<BatteryStatsImpl>() {
   8766         public BatteryStatsImpl createFromParcel(Parcel in) {
   8767             return new BatteryStatsImpl(in);
   8768         }
   8769 
   8770         public BatteryStatsImpl[] newArray(int size) {
   8771             return new BatteryStatsImpl[size];
   8772         }
   8773     };
   8774 
   8775     public void prepareForDumpLocked() {
   8776         // Need to retrieve current kernel wake lock stats before printing.
   8777         pullPendingStateUpdatesLocked();
   8778 
   8779         // Pull the clock time.  This may update the time and make a new history entry
   8780         // if we had originally pulled a time before the RTC was set.
   8781         getStartClockTime();
   8782     }
   8783 
   8784     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
   8785         if (DEBUG) {
   8786             pw.println("mOnBatteryTimeBase:");
   8787             mOnBatteryTimeBase.dump(pw, "  ");
   8788             pw.println("mOnBatteryScreenOffTimeBase:");
   8789             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
   8790             Printer pr = new PrintWriterPrinter(pw);
   8791             pr.println("*** Screen timer:");
   8792             mScreenOnTimer.logState(pr, "  ");
   8793             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   8794                 pr.println("*** Screen brightness #" + i + ":");
   8795                 mScreenBrightnessTimer[i].logState(pr, "  ");
   8796             }
   8797             pr.println("*** Interactive timer:");
   8798             mInteractiveTimer.logState(pr, "  ");
   8799             pr.println("*** Low power mode timer:");
   8800             mLowPowerModeEnabledTimer.logState(pr, "  ");
   8801             pr.println("*** Phone timer:");
   8802             mPhoneOnTimer.logState(pr, "  ");
   8803             for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   8804                 pr.println("*** Phone signal strength #" + i + ":");
   8805                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
   8806             }
   8807             pr.println("*** Signal scanning :");
   8808             mPhoneSignalScanningTimer.logState(pr, "  ");
   8809             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   8810                 pr.println("*** Data connection type #" + i + ":");
   8811                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
   8812             }
   8813             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
   8814             pr.println("*** Mobile network active timer:");
   8815             mMobileRadioActiveTimer.logState(pr, "  ");
   8816             pr.println("*** Mobile network active adjusted timer:");
   8817             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
   8818             pr.println("*** Wifi timer:");
   8819             mWifiOnTimer.logState(pr, "  ");
   8820             pr.println("*** WifiRunning timer:");
   8821             mGlobalWifiRunningTimer.logState(pr, "  ");
   8822             for (int i=0; i<NUM_WIFI_STATES; i++) {
   8823                 pr.println("*** Wifi state #" + i + ":");
   8824                 mWifiStateTimer[i].logState(pr, "  ");
   8825             }
   8826             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   8827                 pr.println("*** Wifi suppl state #" + i + ":");
   8828                 mWifiSupplStateTimer[i].logState(pr, "  ");
   8829             }
   8830             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   8831                 pr.println("*** Wifi signal strength #" + i + ":");
   8832                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
   8833             }
   8834             pr.println("*** Bluetooth timer:");
   8835             mBluetoothOnTimer.logState(pr, "  ");
   8836             for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
   8837                 pr.println("*** Bluetooth active type #" + i + ":");
   8838                 mBluetoothStateTimer[i].logState(pr, "  ");
   8839             }
   8840             pr.println("*** Flashlight timer:");
   8841             mFlashlightOnTimer.logState(pr, "  ");
   8842         }
   8843         super.dumpLocked(context, pw, flags, reqUid, histStart);
   8844     }
   8845 }
   8846