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