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 android.annotation.Nullable;
     20 import android.app.ActivityManager;
     21 import android.bluetooth.BluetoothActivityEnergyInfo;
     22 import android.bluetooth.UidTraffic;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.net.ConnectivityManager;
     26 import android.net.NetworkStats;
     27 import android.net.wifi.WifiActivityEnergyInfo;
     28 import android.net.wifi.WifiManager;
     29 import android.os.BatteryManager;
     30 import android.os.BatteryStats;
     31 import android.os.Build;
     32 import android.os.FileUtils;
     33 import android.os.Handler;
     34 import android.os.Looper;
     35 import android.os.Message;
     36 import android.os.Parcel;
     37 import android.os.ParcelFormatException;
     38 import android.os.Parcelable;
     39 import android.os.Process;
     40 import android.os.SystemClock;
     41 import android.os.SystemProperties;
     42 import android.os.WorkSource;
     43 import android.telephony.DataConnectionRealTimeInfo;
     44 import android.telephony.ModemActivityInfo;
     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.SparseLongArray;
     59 import android.util.TimeUtils;
     60 import android.util.Xml;
     61 import android.view.Display;
     62 
     63 import com.android.internal.annotations.VisibleForTesting;
     64 import com.android.internal.net.NetworkStatsFactory;
     65 import com.android.internal.util.ArrayUtils;
     66 import com.android.internal.util.FastPrintWriter;
     67 import com.android.internal.util.FastXmlSerializer;
     68 import com.android.internal.util.JournaledFile;
     69 import com.android.internal.util.XmlUtils;
     70 import com.android.server.NetworkManagementSocketTagger;
     71 import libcore.util.EmptyArray;
     72 import org.xmlpull.v1.XmlPullParser;
     73 import org.xmlpull.v1.XmlPullParserException;
     74 import org.xmlpull.v1.XmlSerializer;
     75 
     76 import java.io.ByteArrayOutputStream;
     77 import java.io.File;
     78 import java.io.FileInputStream;
     79 import java.io.FileNotFoundException;
     80 import java.io.FileOutputStream;
     81 import java.io.IOException;
     82 import java.io.PrintWriter;
     83 import java.nio.charset.StandardCharsets;
     84 import java.util.ArrayList;
     85 import java.util.Calendar;
     86 import java.util.HashMap;
     87 import java.util.Iterator;
     88 import java.util.Map;
     89 import java.util.concurrent.atomic.AtomicInteger;
     90 import java.util.concurrent.locks.ReentrantLock;
     91 
     92 /**
     93  * All information we are collecting about things that can happen that impact
     94  * battery life.  All times are represented in microseconds except where indicated
     95  * otherwise.
     96  */
     97 public class BatteryStatsImpl extends BatteryStats {
     98     private static final String TAG = "BatteryStatsImpl";
     99     private static final boolean DEBUG = false;
    100     public static final boolean DEBUG_ENERGY = false;
    101     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
    102     private static final boolean DEBUG_HISTORY = false;
    103     private static final boolean USE_OLD_HISTORY = false;   // for debugging.
    104 
    105     // TODO: remove "tcp" from network methods, since we measure total stats.
    106 
    107     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
    108     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
    109 
    110     // Current on-disk Parcel version
    111     private static final int VERSION = 150 + (USE_OLD_HISTORY ? 1000 : 0);
    112 
    113     // Maximum number of items we will record in the history.
    114     private static final int MAX_HISTORY_ITEMS = 2000;
    115 
    116     // No, really, THIS is the maximum number of items we will record in the history.
    117     private static final int MAX_MAX_HISTORY_ITEMS = 3000;
    118 
    119     // The maximum number of names wakelocks we will keep track of
    120     // per uid; once the limit is reached, we batch the remaining wakelocks
    121     // in to one common name.
    122     private static final int MAX_WAKELOCKS_PER_UID = 100;
    123 
    124     // Number of transmit power states the Wifi controller can be in.
    125     private static final int NUM_WIFI_TX_LEVELS = 1;
    126 
    127     // Number of transmit power states the Bluetooth controller can be in.
    128     private static final int NUM_BT_TX_LEVELS = 1;
    129 
    130     protected Clocks mClocks;
    131 
    132     private final JournaledFile mFile;
    133     public final AtomicFile mCheckinFile;
    134     public final AtomicFile mDailyFile;
    135 
    136     static final int MSG_UPDATE_WAKELOCKS = 1;
    137     static final int MSG_REPORT_POWER_CHANGE = 2;
    138     static final int MSG_REPORT_CHARGING = 3;
    139     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
    140 
    141     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
    142     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
    143 
    144     private final KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
    145     private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
    146 
    147     public interface BatteryCallback {
    148         public void batteryNeedsCpuUpdate();
    149         public void batteryPowerChanged(boolean onBattery);
    150         public void batterySendBroadcast(Intent intent);
    151     }
    152 
    153     public interface PlatformIdleStateCallback {
    154         public String getPlatformLowPowerStats();
    155     }
    156 
    157     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
    158 
    159 
    160     final class MyHandler extends Handler {
    161         public MyHandler(Looper looper) {
    162             super(looper, null, true);
    163         }
    164 
    165         @Override
    166         public void handleMessage(Message msg) {
    167             BatteryCallback cb = mCallback;
    168             switch (msg.what) {
    169                 case MSG_UPDATE_WAKELOCKS:
    170                     synchronized (BatteryStatsImpl.this) {
    171                         updateCpuTimeLocked();
    172                     }
    173                     if (cb != null) {
    174                         cb.batteryNeedsCpuUpdate();
    175                     }
    176                     break;
    177                 case MSG_REPORT_POWER_CHANGE:
    178                     if (cb != null) {
    179                         cb.batteryPowerChanged(msg.arg1 != 0);
    180                     }
    181                     break;
    182                 case MSG_REPORT_CHARGING:
    183                     if (cb != null) {
    184                         final String action;
    185                         synchronized (BatteryStatsImpl.this) {
    186                             action = mCharging ? BatteryManager.ACTION_CHARGING
    187                                     : BatteryManager.ACTION_DISCHARGING;
    188                         }
    189                         Intent intent = new Intent(action);
    190                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
    191                         cb.batterySendBroadcast(intent);
    192                     }
    193                     break;
    194             }
    195         }
    196     }
    197 
    198     public interface Clocks {
    199         public long elapsedRealtime();
    200         public long uptimeMillis();
    201     }
    202 
    203     public static class SystemClocks implements Clocks {
    204         public long elapsedRealtime() {
    205             return SystemClock.elapsedRealtime();
    206         }
    207 
    208         public long uptimeMillis() {
    209             return SystemClock.uptimeMillis();
    210         }
    211     }
    212 
    213     public interface ExternalStatsSync {
    214         public static final int UPDATE_CPU = 0x01;
    215         public static final int UPDATE_WIFI = 0x02;
    216         public static final int UPDATE_RADIO = 0x04;
    217         public static final int UPDATE_BT = 0x08;
    218         public static final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
    219 
    220         void scheduleSync(String reason, int flags);
    221         void scheduleCpuSyncDueToRemovedUid(int uid);
    222     }
    223 
    224     public final MyHandler mHandler;
    225     private final ExternalStatsSync mExternalSync;
    226 
    227     private BatteryCallback mCallback;
    228 
    229     /**
    230      * Mapping isolated uids to the actual owning app uid.
    231      */
    232     final SparseIntArray mIsolatedUids = new SparseIntArray();
    233 
    234     /**
    235      * The statistics we have collected organized by uids.
    236      */
    237     final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
    238 
    239     // A set of pools of currently active timers.  When a timer is queried, we will divide the
    240     // elapsed time by the number of active timers to arrive at that timer's share of the time.
    241     // In order to do this, we must refresh each timer whenever the number of active timers
    242     // changes.
    243     final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
    244     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
    245     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
    246     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
    247     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
    248     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
    249     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
    250     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
    251     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
    252     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
    253     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
    254     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
    255     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
    256     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
    257     final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
    258 
    259     // Last partial timers we use for distributing CPU usage.
    260     final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
    261 
    262     // These are the objects that will want to do something when the device
    263     // is unplugged from power.
    264     protected final TimeBase mOnBatteryTimeBase = new TimeBase();
    265 
    266     // These are the objects that will want to do something when the device
    267     // is unplugged from power *and* the screen is off.
    268     final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase();
    269 
    270     // Set to true when we want to distribute CPU across wakelocks for the next
    271     // CPU update, even if we aren't currently running wake locks.
    272     boolean mDistributeWakelockCpu;
    273 
    274     boolean mShuttingDown;
    275 
    276     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
    277 
    278     long mHistoryBaseTime;
    279     boolean mHaveBatteryLevel = false;
    280     boolean mRecordingHistory = false;
    281     int mNumHistoryItems;
    282 
    283     static final int MAX_HISTORY_BUFFER = 256*1024; // 256KB
    284     static final int MAX_MAX_HISTORY_BUFFER = 320*1024; // 320KB
    285     final Parcel mHistoryBuffer = Parcel.obtain();
    286     final HistoryItem mHistoryLastWritten = new HistoryItem();
    287     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
    288     final HistoryItem mHistoryReadTmp = new HistoryItem();
    289     final HistoryItem mHistoryAddTmp = new HistoryItem();
    290     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
    291     String[] mReadHistoryStrings;
    292     int[] mReadHistoryUids;
    293     int mReadHistoryChars;
    294     int mNextHistoryTagIdx = 0;
    295     int mNumHistoryTagChars = 0;
    296     int mHistoryBufferLastPos = -1;
    297     boolean mHistoryOverflow = false;
    298     int mActiveHistoryStates = 0xffffffff;
    299     int mActiveHistoryStates2 = 0xffffffff;
    300     long mLastHistoryElapsedRealtime = 0;
    301     long mTrackRunningHistoryElapsedRealtime = 0;
    302     long mTrackRunningHistoryUptime = 0;
    303 
    304     final HistoryItem mHistoryCur = new HistoryItem();
    305 
    306     HistoryItem mHistory;
    307     HistoryItem mHistoryEnd;
    308     HistoryItem mHistoryLastEnd;
    309     HistoryItem mHistoryCache;
    310 
    311     // Used by computeHistoryStepDetails
    312     HistoryStepDetails mLastHistoryStepDetails = null;
    313     byte mLastHistoryStepLevel = 0;
    314     final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
    315     final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
    316     final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
    317 
    318     /**
    319      * Total time (in milliseconds) spent executing in user code.
    320      */
    321     long mLastStepCpuUserTime;
    322     long mCurStepCpuUserTime;
    323     /**
    324      * Total time (in milliseconds) spent executing in kernel code.
    325      */
    326     long mLastStepCpuSystemTime;
    327     long mCurStepCpuSystemTime;
    328     /**
    329      * Times from /proc/stat (but measured in milliseconds).
    330      */
    331     long mLastStepStatUserTime;
    332     long mLastStepStatSystemTime;
    333     long mLastStepStatIOWaitTime;
    334     long mLastStepStatIrqTime;
    335     long mLastStepStatSoftIrqTime;
    336     long mLastStepStatIdleTime;
    337     long mCurStepStatUserTime;
    338     long mCurStepStatSystemTime;
    339     long mCurStepStatIOWaitTime;
    340     long mCurStepStatIrqTime;
    341     long mCurStepStatSoftIrqTime;
    342     long mCurStepStatIdleTime;
    343 
    344     private HistoryItem mHistoryIterator;
    345     private boolean mReadOverflow;
    346     private boolean mIteratingHistory;
    347 
    348     int mStartCount;
    349 
    350     long mStartClockTime;
    351     String mStartPlatformVersion;
    352     String mEndPlatformVersion;
    353 
    354     long mUptime;
    355     long mUptimeStart;
    356     long mRealtime;
    357     long mRealtimeStart;
    358 
    359     int mWakeLockNesting;
    360     boolean mWakeLockImportant;
    361     public boolean mRecordAllHistory;
    362     boolean mNoAutoReset;
    363 
    364     int mScreenState = Display.STATE_UNKNOWN;
    365     StopwatchTimer mScreenOnTimer;
    366 
    367     int mScreenBrightnessBin = -1;
    368     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
    369 
    370     boolean mInteractive;
    371     StopwatchTimer mInteractiveTimer;
    372 
    373     boolean mPowerSaveModeEnabled;
    374     StopwatchTimer mPowerSaveModeEnabledTimer;
    375 
    376     boolean mDeviceIdling;
    377     StopwatchTimer mDeviceIdlingTimer;
    378 
    379     boolean mDeviceLightIdling;
    380     StopwatchTimer mDeviceLightIdlingTimer;
    381 
    382     int mDeviceIdleMode;
    383     long mLastIdleTimeStart;
    384     long mLongestLightIdleTime;
    385     long mLongestFullIdleTime;
    386     StopwatchTimer mDeviceIdleModeLightTimer;
    387     StopwatchTimer mDeviceIdleModeFullTimer;
    388 
    389     boolean mPhoneOn;
    390     StopwatchTimer mPhoneOnTimer;
    391 
    392     int mAudioOnNesting;
    393     StopwatchTimer mAudioOnTimer;
    394 
    395     int mVideoOnNesting;
    396     StopwatchTimer mVideoOnTimer;
    397 
    398     int mFlashlightOnNesting;
    399     StopwatchTimer mFlashlightOnTimer;
    400 
    401     int mCameraOnNesting;
    402     StopwatchTimer mCameraOnTimer;
    403 
    404     int mPhoneSignalStrengthBin = -1;
    405     int mPhoneSignalStrengthBinRaw = -1;
    406     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
    407             new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
    408 
    409     StopwatchTimer mPhoneSignalScanningTimer;
    410 
    411     int mPhoneDataConnectionType = -1;
    412     final StopwatchTimer[] mPhoneDataConnectionsTimer =
    413             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
    414 
    415     final LongSamplingCounter[] mNetworkByteActivityCounters =
    416             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
    417     final LongSamplingCounter[] mNetworkPacketActivityCounters =
    418             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
    419 
    420     /**
    421      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
    422      */
    423     ControllerActivityCounterImpl mWifiActivity;
    424 
    425     /**
    426      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
    427      */
    428     ControllerActivityCounterImpl mBluetoothActivity;
    429 
    430     /**
    431      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
    432      */
    433     ControllerActivityCounterImpl mModemActivity;
    434 
    435     /**
    436      * Whether the device supports WiFi controller energy reporting. This is set to true on
    437      * the first WiFi energy report. See {@link #mWifiActivity}.
    438      */
    439     boolean mHasWifiReporting = false;
    440 
    441     /**
    442      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
    443      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
    444      */
    445     boolean mHasBluetoothReporting = false;
    446 
    447     /**
    448      * Whether the device supports Modem controller energy reporting. This is set to true on
    449      * the first Modem energy report. See {@link #mModemActivity}.
    450      */
    451     boolean mHasModemReporting = false;
    452 
    453     boolean mWifiOn;
    454     StopwatchTimer mWifiOnTimer;
    455 
    456     boolean mGlobalWifiRunning;
    457     StopwatchTimer mGlobalWifiRunningTimer;
    458 
    459     int mWifiState = -1;
    460     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
    461 
    462     int mWifiSupplState = -1;
    463     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
    464 
    465     int mWifiSignalStrengthBin = -1;
    466     final StopwatchTimer[] mWifiSignalStrengthsTimer =
    467             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
    468 
    469     int mBluetoothScanNesting;
    470     StopwatchTimer mBluetoothScanTimer;
    471 
    472     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
    473     long mMobileRadioActiveStartTime;
    474     StopwatchTimer mMobileRadioActiveTimer;
    475     StopwatchTimer mMobileRadioActivePerAppTimer;
    476     LongSamplingCounter mMobileRadioActiveAdjustedTime;
    477     LongSamplingCounter mMobileRadioActiveUnknownTime;
    478     LongSamplingCounter mMobileRadioActiveUnknownCount;
    479 
    480     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
    481 
    482     /**
    483      * These provide time bases that discount the time the device is plugged
    484      * in to power.
    485      */
    486     boolean mOnBattery;
    487     boolean mOnBatteryInternal;
    488 
    489     /**
    490      * External reporting of whether the device is actually charging.
    491      */
    492     boolean mCharging = true;
    493     int mLastChargingStateLevel;
    494 
    495     /*
    496      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
    497      */
    498     int mDischargeStartLevel;
    499     int mDischargeUnplugLevel;
    500     int mDischargePlugLevel;
    501     int mDischargeCurrentLevel;
    502     int mCurrentBatteryLevel;
    503     int mLowDischargeAmountSinceCharge;
    504     int mHighDischargeAmountSinceCharge;
    505     int mDischargeScreenOnUnplugLevel;
    506     int mDischargeScreenOffUnplugLevel;
    507     int mDischargeAmountScreenOn;
    508     int mDischargeAmountScreenOnSinceCharge;
    509     int mDischargeAmountScreenOff;
    510     int mDischargeAmountScreenOffSinceCharge;
    511 
    512     private LongSamplingCounter mDischargeScreenOffCounter;
    513     private LongSamplingCounter mDischargeCounter;
    514 
    515     static final int MAX_LEVEL_STEPS = 200;
    516 
    517     int mInitStepMode = 0;
    518     int mCurStepMode = 0;
    519     int mModStepMode = 0;
    520 
    521     int mLastDischargeStepLevel;
    522     int mMinDischargeStepLevel;
    523     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
    524     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
    525     ArrayList<PackageChange> mDailyPackageChanges;
    526 
    527     int mLastChargeStepLevel;
    528     int mMaxChargeStepLevel;
    529     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
    530     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
    531 
    532     static final int MAX_DAILY_ITEMS = 10;
    533 
    534     long mDailyStartTime = 0;
    535     long mNextMinDailyDeadline = 0;
    536     long mNextMaxDailyDeadline = 0;
    537 
    538     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
    539 
    540     long mLastWriteTime = 0; // Milliseconds
    541 
    542     private int mPhoneServiceState = -1;
    543     private int mPhoneServiceStateRaw = -1;
    544     private int mPhoneSimStateRaw = -1;
    545 
    546     private int mNumConnectivityChange;
    547     private int mLoadedNumConnectivityChange;
    548     private int mUnpluggedNumConnectivityChange;
    549 
    550     private int mEstimatedBatteryCapacity = -1;
    551 
    552     private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
    553 
    554     private PowerProfile mPowerProfile;
    555 
    556     /*
    557      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
    558      */
    559     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
    560 
    561     public Map<String, ? extends Timer> getKernelWakelockStats() {
    562         return mKernelWakelockStats;
    563     }
    564 
    565     String mLastWakeupReason = null;
    566     long mLastWakeupUptimeMs = 0;
    567     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
    568 
    569     public Map<String, ? extends Timer> getWakeupReasonStats() {
    570         return mWakeupReasonStats;
    571     }
    572 
    573     @Override
    574     public LongCounter getDischargeScreenOffCoulombCounter() {
    575         return mDischargeScreenOffCounter;
    576     }
    577 
    578     @Override
    579     public LongCounter getDischargeCoulombCounter() {
    580         return mDischargeCounter;
    581     }
    582 
    583     @Override
    584     public int getEstimatedBatteryCapacity() {
    585         return mEstimatedBatteryCapacity;
    586     }
    587 
    588     public BatteryStatsImpl() {
    589         this(new SystemClocks());
    590     }
    591 
    592     public BatteryStatsImpl(Clocks clocks) {
    593         init(clocks);
    594         mFile = null;
    595         mCheckinFile = null;
    596         mDailyFile = null;
    597         mHandler = null;
    598         mExternalSync = null;
    599         mPlatformIdleStateCallback = null;
    600         clearHistoryLocked();
    601     }
    602 
    603     private void init(Clocks clocks) {
    604         mClocks = clocks;
    605         mMobileNetworkStats = new NetworkStats[] {
    606                 new NetworkStats(mClocks.elapsedRealtime(), 50),
    607                 new NetworkStats(mClocks.elapsedRealtime(), 50),
    608                 new NetworkStats(mClocks.elapsedRealtime(), 50)
    609         };
    610         mWifiNetworkStats = new NetworkStats[] {
    611                 new NetworkStats(mClocks.elapsedRealtime(), 50),
    612                 new NetworkStats(mClocks.elapsedRealtime(), 50),
    613                 new NetworkStats(mClocks.elapsedRealtime(), 50)
    614             };
    615     }
    616 
    617     public static interface TimeBaseObs {
    618         void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
    619         void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
    620     }
    621 
    622     // methods are protected not private to be VisibleForTesting
    623     public static class TimeBase {
    624         protected final ArrayList<TimeBaseObs> mObservers = new ArrayList<>();
    625 
    626         protected long mUptime;
    627         protected long mRealtime;
    628 
    629         protected boolean mRunning;
    630 
    631         protected long mPastUptime;
    632         protected long mUptimeStart;
    633         protected long mPastRealtime;
    634         protected long mRealtimeStart;
    635         protected long mUnpluggedUptime;
    636         protected long mUnpluggedRealtime;
    637 
    638         public void dump(PrintWriter pw, String prefix) {
    639             StringBuilder sb = new StringBuilder(128);
    640             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
    641             sb.setLength(0);
    642             sb.append(prefix);
    643                     sb.append("mUptime=");
    644                     formatTimeMs(sb, mUptime / 1000);
    645             pw.println(sb.toString());
    646             sb.setLength(0);
    647             sb.append(prefix);
    648                     sb.append("mRealtime=");
    649                     formatTimeMs(sb, mRealtime / 1000);
    650             pw.println(sb.toString());
    651             sb.setLength(0);
    652             sb.append(prefix);
    653                     sb.append("mPastUptime=");
    654                     formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
    655                     formatTimeMs(sb, mUptimeStart / 1000);
    656                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
    657             pw.println(sb.toString());
    658             sb.setLength(0);
    659             sb.append(prefix);
    660                     sb.append("mPastRealtime=");
    661                     formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
    662                     formatTimeMs(sb, mRealtimeStart / 1000);
    663                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
    664             pw.println(sb.toString());
    665         }
    666 
    667         public void add(TimeBaseObs observer) {
    668             mObservers.add(observer);
    669         }
    670 
    671         public void remove(TimeBaseObs observer) {
    672             if (!mObservers.remove(observer)) {
    673                 Slog.wtf(TAG, "Removed unknown observer: " + observer);
    674             }
    675         }
    676 
    677         public boolean hasObserver(TimeBaseObs observer) {
    678             return mObservers.contains(observer);
    679         }
    680 
    681         public void init(long uptime, long realtime) {
    682             mRealtime = 0;
    683             mUptime = 0;
    684             mPastUptime = 0;
    685             mPastRealtime = 0;
    686             mUptimeStart = uptime;
    687             mRealtimeStart = realtime;
    688             mUnpluggedUptime = getUptime(mUptimeStart);
    689             mUnpluggedRealtime = getRealtime(mRealtimeStart);
    690         }
    691 
    692         public void reset(long uptime, long realtime) {
    693             if (!mRunning) {
    694                 mPastUptime = 0;
    695                 mPastRealtime = 0;
    696             } else {
    697                 mUptimeStart = uptime;
    698                 mRealtimeStart = realtime;
    699                 // TODO: Since mUptimeStart was just reset and we are running, getUptime will
    700                 // just return mPastUptime. Also, are we sure we don't want to reset that?
    701                 mUnpluggedUptime = getUptime(uptime);
    702                 // TODO: likewise.
    703                 mUnpluggedRealtime = getRealtime(realtime);
    704             }
    705         }
    706 
    707         public long computeUptime(long curTime, int which) {
    708             switch (which) {
    709                 case STATS_SINCE_CHARGED:
    710                     return mUptime + getUptime(curTime);
    711                 case STATS_CURRENT:
    712                     return getUptime(curTime);
    713                 case STATS_SINCE_UNPLUGGED:
    714                     return getUptime(curTime) - mUnpluggedUptime;
    715             }
    716             return 0;
    717         }
    718 
    719         public long computeRealtime(long curTime, int which) {
    720             switch (which) {
    721                 case STATS_SINCE_CHARGED:
    722                     return mRealtime + getRealtime(curTime);
    723                 case STATS_CURRENT:
    724                     return getRealtime(curTime);
    725                 case STATS_SINCE_UNPLUGGED:
    726                     return getRealtime(curTime) - mUnpluggedRealtime;
    727             }
    728             return 0;
    729         }
    730 
    731         public long getUptime(long curTime) {
    732             long time = mPastUptime;
    733             if (mRunning) {
    734                 time += curTime - mUptimeStart;
    735             }
    736             return time;
    737         }
    738 
    739         public long getRealtime(long curTime) {
    740             long time = mPastRealtime;
    741             if (mRunning) {
    742                 time += curTime - mRealtimeStart;
    743             }
    744             return time;
    745         }
    746 
    747         public long getUptimeStart() {
    748             return mUptimeStart;
    749         }
    750 
    751         public long getRealtimeStart() {
    752             return mRealtimeStart;
    753         }
    754 
    755         public boolean isRunning() {
    756             return mRunning;
    757         }
    758 
    759         public boolean setRunning(boolean running, long uptime, long realtime) {
    760             if (mRunning != running) {
    761                 mRunning = running;
    762                 if (running) {
    763                     mUptimeStart = uptime;
    764                     mRealtimeStart = realtime;
    765                     long batteryUptime = mUnpluggedUptime = getUptime(uptime);
    766                     long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
    767 
    768                     for (int i = mObservers.size() - 1; i >= 0; i--) {
    769                         mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime);
    770                     }
    771                 } else {
    772                     mPastUptime += uptime - mUptimeStart;
    773                     mPastRealtime += realtime - mRealtimeStart;
    774 
    775                     long batteryUptime = getUptime(uptime);
    776                     long batteryRealtime = getRealtime(realtime);
    777 
    778                     for (int i = mObservers.size() - 1; i >= 0; i--) {
    779                         mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime);
    780                     }
    781                 }
    782                 return true;
    783             }
    784             return false;
    785         }
    786 
    787         public void readSummaryFromParcel(Parcel in) {
    788             mUptime = in.readLong();
    789             mRealtime = in.readLong();
    790         }
    791 
    792         public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
    793             out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
    794             out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
    795         }
    796 
    797         public void readFromParcel(Parcel in) {
    798             mRunning = false;
    799             mUptime = in.readLong();
    800             mPastUptime = in.readLong();
    801             mUptimeStart = in.readLong();
    802             mRealtime = in.readLong();
    803             mPastRealtime = in.readLong();
    804             mRealtimeStart = in.readLong();
    805             mUnpluggedUptime = in.readLong();
    806             mUnpluggedRealtime = in.readLong();
    807         }
    808 
    809         public void writeToParcel(Parcel out, long uptime, long realtime) {
    810             final long runningUptime = getUptime(uptime);
    811             final long runningRealtime = getRealtime(realtime);
    812             out.writeLong(mUptime);
    813             out.writeLong(runningUptime);
    814             out.writeLong(mUptimeStart);
    815             out.writeLong(mRealtime);
    816             out.writeLong(runningRealtime);
    817             out.writeLong(mRealtimeStart);
    818             out.writeLong(mUnpluggedUptime);
    819             out.writeLong(mUnpluggedRealtime);
    820         }
    821     }
    822 
    823     /**
    824      * State for keeping track of counting information.
    825      */
    826     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
    827         final AtomicInteger mCount = new AtomicInteger();
    828         final TimeBase mTimeBase;
    829         int mLoadedCount;
    830         int mLastCount;
    831         int mUnpluggedCount;
    832         int mPluggedCount;
    833 
    834         Counter(TimeBase timeBase, Parcel in) {
    835             mTimeBase = timeBase;
    836             mPluggedCount = in.readInt();
    837             mCount.set(mPluggedCount);
    838             mLoadedCount = in.readInt();
    839             mLastCount = 0;
    840             mUnpluggedCount = in.readInt();
    841             timeBase.add(this);
    842         }
    843 
    844         Counter(TimeBase timeBase) {
    845             mTimeBase = timeBase;
    846             timeBase.add(this);
    847         }
    848 
    849         public void writeToParcel(Parcel out) {
    850             out.writeInt(mCount.get());
    851             out.writeInt(mLoadedCount);
    852             out.writeInt(mUnpluggedCount);
    853         }
    854 
    855         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
    856             mUnpluggedCount = mPluggedCount;
    857             mCount.set(mPluggedCount);
    858         }
    859 
    860         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
    861             mPluggedCount = mCount.get();
    862         }
    863 
    864         /**
    865          * Writes a possibly null Counter to a Parcel.
    866          *
    867          * @param out the Parcel to be written to.
    868          * @param counter a Counter, or null.
    869          */
    870         public static void writeCounterToParcel(Parcel out, Counter counter) {
    871             if (counter == null) {
    872                 out.writeInt(0); // indicates null
    873                 return;
    874             }
    875             out.writeInt(1); // indicates non-null
    876 
    877             counter.writeToParcel(out);
    878         }
    879 
    880         @Override
    881         public int getCountLocked(int which) {
    882             int val = mCount.get();
    883             if (which == STATS_SINCE_UNPLUGGED) {
    884                 val -= mUnpluggedCount;
    885             } else if (which != STATS_SINCE_CHARGED) {
    886                 val -= mLoadedCount;
    887             }
    888 
    889             return val;
    890         }
    891 
    892         public void logState(Printer pw, String prefix) {
    893             pw.println(prefix + "mCount=" + mCount.get()
    894                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
    895                     + " mUnpluggedCount=" + mUnpluggedCount
    896                     + " mPluggedCount=" + mPluggedCount);
    897         }
    898 
    899         void stepAtomic() {
    900             mCount.incrementAndGet();
    901         }
    902 
    903         /**
    904          * Clear state of this counter.
    905          */
    906         void reset(boolean detachIfReset) {
    907             mCount.set(0);
    908             mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
    909             if (detachIfReset) {
    910                 detach();
    911             }
    912         }
    913 
    914         void detach() {
    915             mTimeBase.remove(this);
    916         }
    917 
    918         void writeSummaryFromParcelLocked(Parcel out) {
    919             int count = mCount.get();
    920             out.writeInt(count);
    921         }
    922 
    923         void readSummaryFromParcelLocked(Parcel in) {
    924             mLoadedCount = in.readInt();
    925             mCount.set(mLoadedCount);
    926             mLastCount = 0;
    927             mUnpluggedCount = mPluggedCount = mLoadedCount;
    928         }
    929     }
    930 
    931     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
    932         final TimeBase mTimeBase;
    933         long mCount;
    934         long mLoadedCount;
    935         long mUnpluggedCount;
    936         long mPluggedCount;
    937 
    938         LongSamplingCounter(TimeBase timeBase, Parcel in) {
    939             mTimeBase = timeBase;
    940             mPluggedCount = in.readLong();
    941             mCount = mPluggedCount;
    942             mLoadedCount = in.readLong();
    943             mUnpluggedCount = in.readLong();
    944             timeBase.add(this);
    945         }
    946 
    947         LongSamplingCounter(TimeBase timeBase) {
    948             mTimeBase = timeBase;
    949             timeBase.add(this);
    950         }
    951 
    952         public void writeToParcel(Parcel out) {
    953             out.writeLong(mCount);
    954             out.writeLong(mLoadedCount);
    955             out.writeLong(mUnpluggedCount);
    956         }
    957 
    958         @Override
    959         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
    960             mUnpluggedCount = mPluggedCount;
    961             mCount = mPluggedCount;
    962         }
    963 
    964         @Override
    965         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
    966             mPluggedCount = mCount;
    967         }
    968 
    969         public long getCountLocked(int which) {
    970             long val = mTimeBase.isRunning() ? mCount : mPluggedCount;
    971             if (which == STATS_SINCE_UNPLUGGED) {
    972                 val -= mUnpluggedCount;
    973             } else if (which != STATS_SINCE_CHARGED) {
    974                 val -= mLoadedCount;
    975             }
    976             return val;
    977         }
    978 
    979         @Override
    980         public void logState(Printer pw, String prefix) {
    981             pw.println(prefix + "mCount=" + mCount
    982                     + " mLoadedCount=" + mLoadedCount
    983                     + " mUnpluggedCount=" + mUnpluggedCount
    984                     + " mPluggedCount=" + mPluggedCount);
    985         }
    986 
    987         void addCountLocked(long count) {
    988             mCount += count;
    989         }
    990 
    991         /**
    992          * Clear state of this counter.
    993          */
    994         void reset(boolean detachIfReset) {
    995             mCount = 0;
    996             mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
    997             if (detachIfReset) {
    998                 detach();
    999             }
   1000         }
   1001 
   1002         void detach() {
   1003             mTimeBase.remove(this);
   1004         }
   1005 
   1006         void writeSummaryFromParcelLocked(Parcel out) {
   1007             out.writeLong(mCount);
   1008         }
   1009 
   1010         void readSummaryFromParcelLocked(Parcel in) {
   1011             mLoadedCount = in.readLong();
   1012             mCount = mLoadedCount;
   1013             mUnpluggedCount = mPluggedCount = mLoadedCount;
   1014         }
   1015     }
   1016 
   1017     /**
   1018      * State for keeping track of timing information.
   1019      */
   1020     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
   1021         protected final Clocks mClocks;
   1022         protected final int mType;
   1023         protected final TimeBase mTimeBase;
   1024 
   1025         protected int mCount;
   1026         protected int mLoadedCount;
   1027         protected int mLastCount;
   1028         protected int mUnpluggedCount;
   1029 
   1030         // Times are in microseconds for better accuracy when dividing by the
   1031         // lock count, and are in "battery realtime" units.
   1032 
   1033         /**
   1034          * The total time we have accumulated since the start of the original
   1035          * boot, to the last time something interesting happened in the
   1036          * current run.
   1037          */
   1038         protected long mTotalTime;
   1039 
   1040         /**
   1041          * The total time we loaded for the previous runs.  Subtract this from
   1042          * mTotalTime to find the time for the current run of the system.
   1043          */
   1044         protected long mLoadedTime;
   1045 
   1046         /**
   1047          * The run time of the last run of the system, as loaded from the
   1048          * saved data.
   1049          */
   1050         protected long mLastTime;
   1051 
   1052         /**
   1053          * The value of mTotalTime when unplug() was last called.  Subtract
   1054          * this from mTotalTime to find the time since the last unplug from
   1055          * power.
   1056          */
   1057         protected long mUnpluggedTime;
   1058 
   1059         /**
   1060          * The total time this timer has been running until the latest mark has been set.
   1061          * Subtract this from mTotalTime to get the time spent running since the mark was set.
   1062          */
   1063         protected long mTimeBeforeMark;
   1064 
   1065         /**
   1066          * Constructs from a parcel.
   1067          * @param type
   1068          * @param timeBase
   1069          * @param in
   1070          */
   1071         public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
   1072             mClocks = clocks;
   1073             mType = type;
   1074             mTimeBase = timeBase;
   1075 
   1076             mCount = in.readInt();
   1077             mLoadedCount = in.readInt();
   1078             mLastCount = 0;
   1079             mUnpluggedCount = in.readInt();
   1080             mTotalTime = in.readLong();
   1081             mLoadedTime = in.readLong();
   1082             mLastTime = 0;
   1083             mUnpluggedTime = in.readLong();
   1084             mTimeBeforeMark = in.readLong();
   1085             timeBase.add(this);
   1086             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
   1087         }
   1088 
   1089         public Timer(Clocks clocks, int type, TimeBase timeBase) {
   1090             mClocks = clocks;
   1091             mType = type;
   1092             mTimeBase = timeBase;
   1093             timeBase.add(this);
   1094         }
   1095 
   1096         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
   1097 
   1098         protected abstract int computeCurrentCountLocked();
   1099 
   1100         /**
   1101          * Clear state of this timer.  Returns true if the timer is inactive
   1102          * so can be completely dropped.
   1103          */
   1104         public boolean reset(boolean detachIfReset) {
   1105             mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0;
   1106             mCount = mLoadedCount = mLastCount = 0;
   1107             if (detachIfReset) {
   1108                 detach();
   1109             }
   1110             return true;
   1111         }
   1112 
   1113         public void detach() {
   1114             mTimeBase.remove(this);
   1115         }
   1116 
   1117         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   1118             if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
   1119                     + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
   1120             out.writeInt(computeCurrentCountLocked());
   1121             out.writeInt(mLoadedCount);
   1122             out.writeInt(mUnpluggedCount);
   1123             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
   1124             out.writeLong(mLoadedTime);
   1125             out.writeLong(mUnpluggedTime);
   1126             out.writeLong(mTimeBeforeMark);
   1127         }
   1128 
   1129         @Override
   1130         public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
   1131             if (DEBUG && mType < 0) {
   1132                 Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime
   1133                         + " old mUnpluggedTime=" + mUnpluggedTime
   1134                         + " old mUnpluggedCount=" + mUnpluggedCount);
   1135             }
   1136             mUnpluggedTime = computeRunTimeLocked(baseRealtime);
   1137             mUnpluggedCount = computeCurrentCountLocked();
   1138             if (DEBUG && mType < 0) {
   1139                 Log.v(TAG, "unplug #" + mType
   1140                         + ": new mUnpluggedTime=" + mUnpluggedTime
   1141                         + " new mUnpluggedCount=" + mUnpluggedCount);
   1142             }
   1143         }
   1144 
   1145         @Override
   1146         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1147             if (DEBUG && mType < 0) {
   1148                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
   1149                         + " old mTotalTime=" + mTotalTime);
   1150             }
   1151             mTotalTime = computeRunTimeLocked(baseRealtime);
   1152             mCount = computeCurrentCountLocked();
   1153             if (DEBUG && mType < 0) {
   1154                 Log.v(TAG, "plug #" + mType
   1155                         + ": new mTotalTime=" + mTotalTime);
   1156             }
   1157         }
   1158 
   1159         /**
   1160          * Writes a possibly null Timer to a Parcel.
   1161          *
   1162          * @param out the Parcel to be written to.
   1163          * @param timer a Timer, or null.
   1164          */
   1165         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
   1166             if (timer == null) {
   1167                 out.writeInt(0); // indicates null
   1168                 return;
   1169             }
   1170             out.writeInt(1); // indicates non-null
   1171 
   1172             timer.writeToParcel(out, elapsedRealtimeUs);
   1173         }
   1174 
   1175         @Override
   1176         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
   1177             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
   1178             if (which == STATS_SINCE_UNPLUGGED) {
   1179                 val -= mUnpluggedTime;
   1180             } else if (which != STATS_SINCE_CHARGED) {
   1181                 val -= mLoadedTime;
   1182             }
   1183 
   1184             return val;
   1185         }
   1186 
   1187         @Override
   1188         public int getCountLocked(int which) {
   1189             int val = computeCurrentCountLocked();
   1190             if (which == STATS_SINCE_UNPLUGGED) {
   1191                 val -= mUnpluggedCount;
   1192             } else if (which != STATS_SINCE_CHARGED) {
   1193                 val -= mLoadedCount;
   1194             }
   1195 
   1196             return val;
   1197         }
   1198 
   1199         @Override
   1200         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
   1201             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
   1202             return val - mTimeBeforeMark;
   1203         }
   1204 
   1205         @Override
   1206         public void logState(Printer pw, String prefix) {
   1207             pw.println(prefix + "mCount=" + mCount
   1208                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
   1209                     + " mUnpluggedCount=" + mUnpluggedCount);
   1210             pw.println(prefix + "mTotalTime=" + mTotalTime
   1211                     + " mLoadedTime=" + mLoadedTime);
   1212             pw.println(prefix + "mLastTime=" + mLastTime
   1213                     + " mUnpluggedTime=" + mUnpluggedTime);
   1214         }
   1215 
   1216 
   1217         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
   1218             long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
   1219             out.writeLong(runTime);
   1220             out.writeInt(computeCurrentCountLocked());
   1221         }
   1222 
   1223         public void readSummaryFromParcelLocked(Parcel in) {
   1224             // Multiply by 1000 for backwards compatibility
   1225             mTotalTime = mLoadedTime = in.readLong();
   1226             mLastTime = 0;
   1227             mUnpluggedTime = mTotalTime;
   1228             mCount = mLoadedCount = in.readInt();
   1229             mLastCount = 0;
   1230             mUnpluggedCount = mCount;
   1231 
   1232             // When reading the summary, we set the mark to be the latest information.
   1233             mTimeBeforeMark = mTotalTime;
   1234         }
   1235     }
   1236 
   1237     /**
   1238      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
   1239      * method. The state of the timer according to its {@link TimeBase} will determine how much
   1240      * of the value is recorded.
   1241      *
   1242      * If the value being recorded resets, {@link #endSample()} can be called in order to
   1243      * account for the change. If the value passed in to {@link #update(long, int)} decreased
   1244      * between calls, the {@link #endSample()} is automatically called and the new value is
   1245      * expected to increase monotonically from that point on.
   1246      */
   1247     public static class SamplingTimer extends Timer {
   1248 
   1249         /**
   1250          * The most recent reported count from /proc/wakelocks.
   1251          */
   1252         int mCurrentReportedCount;
   1253 
   1254         /**
   1255          * The reported count from /proc/wakelocks when unplug() was last
   1256          * called.
   1257          */
   1258         int mUnpluggedReportedCount;
   1259 
   1260         /**
   1261          * The most recent reported total_time from /proc/wakelocks.
   1262          */
   1263         long mCurrentReportedTotalTime;
   1264 
   1265 
   1266         /**
   1267          * The reported total_time from /proc/wakelocks when unplug() was last
   1268          * called.
   1269          */
   1270         long mUnpluggedReportedTotalTime;
   1271 
   1272         /**
   1273          * Whether we are currently in a discharge cycle.
   1274          */
   1275         boolean mTimeBaseRunning;
   1276 
   1277         /**
   1278          * Whether we are currently recording reported values.
   1279          */
   1280         boolean mTrackingReportedValues;
   1281 
   1282         /*
   1283          * A sequence counter, incremented once for each update of the stats.
   1284          */
   1285         int mUpdateVersion;
   1286 
   1287         @VisibleForTesting
   1288         public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
   1289             super(clocks, 0, timeBase, in);
   1290             mCurrentReportedCount = in.readInt();
   1291             mUnpluggedReportedCount = in.readInt();
   1292             mCurrentReportedTotalTime = in.readLong();
   1293             mUnpluggedReportedTotalTime = in.readLong();
   1294             mTrackingReportedValues = in.readInt() == 1;
   1295             mTimeBaseRunning = timeBase.isRunning();
   1296         }
   1297 
   1298         @VisibleForTesting
   1299         public SamplingTimer(Clocks clocks, TimeBase timeBase) {
   1300             super(clocks, 0, timeBase);
   1301             mTrackingReportedValues = false;
   1302             mTimeBaseRunning = timeBase.isRunning();
   1303         }
   1304 
   1305         /**
   1306          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
   1307          * be less than the values used for a previous invocation.
   1308          */
   1309         public void endSample() {
   1310             mTotalTime = computeRunTimeLocked(0 /* unused by us */);
   1311             mCount = computeCurrentCountLocked();
   1312             mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
   1313             mUnpluggedReportedCount = mCurrentReportedCount = 0;
   1314         }
   1315 
   1316         public void setUpdateVersion(int version) {
   1317             mUpdateVersion = version;
   1318         }
   1319 
   1320         public int getUpdateVersion() {
   1321             return mUpdateVersion;
   1322         }
   1323 
   1324         /**
   1325          * Updates the current recorded values. These are meant to be monotonically increasing
   1326          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
   1327          *
   1328          * If the values being recorded have been reset, the monotonically increasing requirement
   1329          * will be broken. In this case, {@link #endSample()} is automatically called and
   1330          * the total value of totalTime and count are recorded, starting a new monotonically
   1331          * increasing sample.
   1332          *
   1333          * @param totalTime total time of sample in microseconds.
   1334          * @param count total number of times the event being sampled occurred.
   1335          */
   1336         public void update(long totalTime, int count) {
   1337             if (mTimeBaseRunning && !mTrackingReportedValues) {
   1338                 // Updating the reported value for the first time.
   1339                 mUnpluggedReportedTotalTime = totalTime;
   1340                 mUnpluggedReportedCount = count;
   1341             }
   1342 
   1343             mTrackingReportedValues = true;
   1344 
   1345             if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) {
   1346                 endSample();
   1347             }
   1348 
   1349             mCurrentReportedTotalTime = totalTime;
   1350             mCurrentReportedCount = count;
   1351         }
   1352 
   1353         /**
   1354          * Adds deltaTime and deltaCount to the current sample.
   1355          *
   1356          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
   1357          * @param deltaCount additional number of times the event being sampled occurred.
   1358          */
   1359         public void add(long deltaTime, int deltaCount) {
   1360             update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount);
   1361         }
   1362 
   1363         @Override
   1364         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1365             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
   1366             if (mTrackingReportedValues) {
   1367                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
   1368                 mUnpluggedReportedCount = mCurrentReportedCount;
   1369             }
   1370             mTimeBaseRunning = true;
   1371         }
   1372 
   1373         @Override
   1374         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1375             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
   1376             mTimeBaseRunning = false;
   1377         }
   1378 
   1379         @Override
   1380         public void logState(Printer pw, String prefix) {
   1381             super.logState(pw, prefix);
   1382             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
   1383                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
   1384                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
   1385                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
   1386         }
   1387 
   1388         @Override
   1389         protected long computeRunTimeLocked(long curBatteryRealtime) {
   1390             return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
   1391                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
   1392         }
   1393 
   1394         @Override
   1395         protected int computeCurrentCountLocked() {
   1396             return mCount + (mTimeBaseRunning && mTrackingReportedValues
   1397                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
   1398         }
   1399 
   1400         @Override
   1401         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   1402             super.writeToParcel(out, elapsedRealtimeUs);
   1403             out.writeInt(mCurrentReportedCount);
   1404             out.writeInt(mUnpluggedReportedCount);
   1405             out.writeLong(mCurrentReportedTotalTime);
   1406             out.writeLong(mUnpluggedReportedTotalTime);
   1407             out.writeInt(mTrackingReportedValues ? 1 : 0);
   1408         }
   1409 
   1410         @Override
   1411         public boolean reset(boolean detachIfReset) {
   1412             super.reset(detachIfReset);
   1413             mTrackingReportedValues = false;
   1414             mUnpluggedReportedTotalTime = 0;
   1415             mUnpluggedReportedCount = 0;
   1416             return true;
   1417         }
   1418     }
   1419 
   1420     /**
   1421      * A timer that increments in batches.  It does not run for durations, but just jumps
   1422      * for a pre-determined amount.
   1423      */
   1424     public static class BatchTimer extends Timer {
   1425         final Uid mUid;
   1426 
   1427         /**
   1428          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
   1429          */
   1430         long mLastAddedTime;
   1431 
   1432         /**
   1433          * The last duration that we added to the timer.  This is in microseconds.
   1434          */
   1435         long mLastAddedDuration;
   1436 
   1437         /**
   1438          * Whether we are currently in a discharge cycle.
   1439          */
   1440         boolean mInDischarge;
   1441 
   1442         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
   1443             super(clocks, type, timeBase, in);
   1444             mUid = uid;
   1445             mLastAddedTime = in.readLong();
   1446             mLastAddedDuration = in.readLong();
   1447             mInDischarge = timeBase.isRunning();
   1448         }
   1449 
   1450         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
   1451             super(clocks, type, timeBase);
   1452             mUid = uid;
   1453             mInDischarge = timeBase.isRunning();
   1454         }
   1455 
   1456         @Override
   1457         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   1458             super.writeToParcel(out, elapsedRealtimeUs);
   1459             out.writeLong(mLastAddedTime);
   1460             out.writeLong(mLastAddedDuration);
   1461         }
   1462 
   1463         @Override
   1464         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1465             recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
   1466             mInDischarge = false;
   1467             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
   1468         }
   1469 
   1470         @Override
   1471         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1472             recomputeLastDuration(elapsedRealtime, false);
   1473             mInDischarge = true;
   1474             // If we are still within the last added duration, then re-added whatever remains.
   1475             if (mLastAddedTime == elapsedRealtime) {
   1476                 mTotalTime += mLastAddedDuration;
   1477             }
   1478             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
   1479         }
   1480 
   1481         @Override
   1482         public void logState(Printer pw, String prefix) {
   1483             super.logState(pw, prefix);
   1484             pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
   1485                     + " mLastAddedDuration=" + mLastAddedDuration);
   1486         }
   1487 
   1488         private long computeOverage(long curTime) {
   1489             if (mLastAddedTime > 0) {
   1490                 return mLastTime + mLastAddedDuration - curTime;
   1491             }
   1492             return 0;
   1493         }
   1494 
   1495         private void recomputeLastDuration(long curTime, boolean abort) {
   1496             final long overage = computeOverage(curTime);
   1497             if (overage > 0) {
   1498                 // Aborting before the duration ran out -- roll back the remaining
   1499                 // duration.  Only do this if currently discharging; otherwise we didn't
   1500                 // actually add the time.
   1501                 if (mInDischarge) {
   1502                     mTotalTime -= overage;
   1503                 }
   1504                 if (abort) {
   1505                     mLastAddedTime = 0;
   1506                 } else {
   1507                     mLastAddedTime = curTime;
   1508                     mLastAddedDuration -= overage;
   1509                 }
   1510             }
   1511         }
   1512 
   1513         public void addDuration(BatteryStatsImpl stats, long durationMillis) {
   1514             final long now = mClocks.elapsedRealtime() * 1000;
   1515             recomputeLastDuration(now, true);
   1516             mLastAddedTime = now;
   1517             mLastAddedDuration = durationMillis * 1000;
   1518             if (mInDischarge) {
   1519                 mTotalTime += mLastAddedDuration;
   1520                 mCount++;
   1521             }
   1522         }
   1523 
   1524         public void abortLastDuration(BatteryStatsImpl stats) {
   1525             final long now = mClocks.elapsedRealtime() * 1000;
   1526             recomputeLastDuration(now, true);
   1527         }
   1528 
   1529         @Override
   1530         protected int computeCurrentCountLocked() {
   1531             return mCount;
   1532         }
   1533 
   1534         @Override
   1535         protected long computeRunTimeLocked(long curBatteryRealtime) {
   1536             final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
   1537             if (overage > 0) {
   1538                 return mTotalTime = overage;
   1539             }
   1540             return mTotalTime;
   1541         }
   1542 
   1543         @Override
   1544         public boolean reset(boolean detachIfReset) {
   1545             final long now = mClocks.elapsedRealtime() * 1000;
   1546             recomputeLastDuration(now, true);
   1547             boolean stillActive = mLastAddedTime == now;
   1548             super.reset(!stillActive && detachIfReset);
   1549             return !stillActive;
   1550         }
   1551     }
   1552 
   1553 
   1554     /**
   1555      * A StopwatchTimer that also tracks the total and max individual
   1556      * time spent active according to the given timebase.  Whereas
   1557      * StopwatchTimer apportions the time amongst all in the pool,
   1558      * the total and max durations are not apportioned.
   1559      */
   1560     public static class DurationTimer extends StopwatchTimer {
   1561         /**
   1562          * The time (in ms) that the timer was last acquired or the time base
   1563          * last (re-)started. Increasing the nesting depth does not reset this time.
   1564          *
   1565          * -1 if the timer is currently not running or the time base is not running.
   1566          *
   1567          * If written to a parcel, the start time is reset, as is mNesting in the base class
   1568          * StopwatchTimer.
   1569          */
   1570         long mStartTimeMs = -1;
   1571 
   1572         /**
   1573          * The longest time period (in ms) that the timer has been active.
   1574          */
   1575         long mMaxDurationMs;
   1576 
   1577         /**
   1578          * The total time (in ms) that that the timer has been active since reset().
   1579          */
   1580         long mCurrentDurationMs;
   1581 
   1582         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   1583                 TimeBase timeBase, Parcel in) {
   1584             super(clocks, uid, type, timerPool, timeBase, in);
   1585             mMaxDurationMs = in.readLong();
   1586         }
   1587 
   1588         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   1589                 TimeBase timeBase) {
   1590             super(clocks, uid, type, timerPool, timeBase);
   1591         }
   1592 
   1593         @Override
   1594         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   1595             super.writeToParcel(out, elapsedRealtimeUs);
   1596             out.writeLong(mMaxDurationMs);
   1597         }
   1598 
   1599         /**
   1600          * Write the summary to the parcel.
   1601          *
   1602          * Since the time base is probably meaningless after we come back, reading
   1603          * from this will have the effect of stopping the timer. So here all we write
   1604          * is the max duration.
   1605          */
   1606         @Override
   1607         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
   1608             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
   1609             out.writeLong(mMaxDurationMs);
   1610         }
   1611 
   1612         /**
   1613          * Read the summary parcel.
   1614          *
   1615          * Has the side effect of stopping the timer.
   1616          */
   1617         @Override
   1618         public void readSummaryFromParcelLocked(Parcel in) {
   1619             super.readSummaryFromParcelLocked(in);
   1620             mMaxDurationMs = in.readLong();
   1621             mStartTimeMs = -1;
   1622             mCurrentDurationMs = 0;
   1623         }
   1624 
   1625         /**
   1626          * The TimeBase time started (again).
   1627          *
   1628          * If the timer is also running, store the start time.
   1629          */
   1630         public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
   1631             super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
   1632             if (mNesting > 0) {
   1633                 mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
   1634             }
   1635         }
   1636 
   1637         /**
   1638          * The TimeBase stopped running.
   1639          *
   1640          * If the timer is running, add the duration into mCurrentDurationMs.
   1641          */
   1642         @Override
   1643         public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
   1644             super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtime);
   1645             if (mNesting > 0) {
   1646                 mCurrentDurationMs += (elapsedRealtimeUs / 1000) - mStartTimeMs;
   1647             }
   1648             mStartTimeMs = -1;
   1649         }
   1650 
   1651         @Override
   1652         public void logState(Printer pw, String prefix) {
   1653             super.logState(pw, prefix);
   1654         }
   1655 
   1656         @Override
   1657         public void startRunningLocked(long elapsedRealtimeMs) {
   1658             super.startRunningLocked(elapsedRealtimeMs);
   1659             if (mNesting == 1 && mTimeBase.isRunning()) {
   1660                 // Just started
   1661                 mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
   1662             }
   1663         }
   1664 
   1665         /**
   1666          * Decrements the mNesting ref-count on this timer.
   1667          *
   1668          * If it actually stopped (mNesting went to 0), then possibly update
   1669          * mMaxDuration if the current duration was the longest ever.
   1670          */
   1671         @Override
   1672         public void stopRunningLocked(long elapsedRealtimeMs) {
   1673             super.stopRunningLocked(elapsedRealtimeMs);
   1674             if (mNesting == 0) {
   1675                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
   1676                 if (durationMs > mMaxDurationMs) {
   1677                     mMaxDurationMs = durationMs;
   1678                 }
   1679                 mStartTimeMs = -1;
   1680                 mCurrentDurationMs = 0;
   1681             }
   1682         }
   1683 
   1684         @Override
   1685         public boolean reset(boolean detachIfReset) {
   1686             boolean result = super.reset(detachIfReset);
   1687             mMaxDurationMs = 0;
   1688             mCurrentDurationMs = 0;
   1689             if (mNesting > 0) {
   1690                 mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
   1691             } else {
   1692                 mStartTimeMs = -1;
   1693             }
   1694             return result;
   1695         }
   1696 
   1697         /**
   1698          * Returns the max duration that this timer has ever seen.
   1699          *
   1700          * Note that this time is NOT split between the timers in the timer group that
   1701          * this timer is attached to.  It is the TOTAL time.
   1702          */
   1703         @Override
   1704         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
   1705             if (mNesting > 0) {
   1706                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
   1707                 if (durationMs > mMaxDurationMs) {
   1708                     return durationMs;
   1709                 }
   1710             }
   1711             return mMaxDurationMs;
   1712         }
   1713 
   1714         /**
   1715          * Returns the time since the timer was started.
   1716          *
   1717          * Note that this time is NOT split between the timers in the timer group that
   1718          * this timer is attached to.  It is the TOTAL time.
   1719          */
   1720         @Override
   1721         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
   1722             long durationMs = mCurrentDurationMs;
   1723             if (mNesting > 0) {
   1724                 if (mTimeBase.isRunning()) {
   1725                     durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000)
   1726                             - mStartTimeMs;
   1727                 }
   1728             }
   1729             return durationMs;
   1730         }
   1731     }
   1732 
   1733     /**
   1734      * State for keeping track of timing information.
   1735      */
   1736     public static class StopwatchTimer extends Timer {
   1737         final Uid mUid;
   1738         final ArrayList<StopwatchTimer> mTimerPool;
   1739 
   1740         int mNesting;
   1741 
   1742         /**
   1743          * The last time at which we updated the timer.  If mNesting is > 0,
   1744          * subtract this from the current battery time to find the amount of
   1745          * time we have been running since we last computed an update.
   1746          */
   1747         long mUpdateTime;
   1748 
   1749         /**
   1750          * The total time at which the timer was acquired, to determine if it
   1751          * was actually held for an interesting duration.
   1752          */
   1753         long mAcquireTime;
   1754 
   1755         long mTimeout;
   1756 
   1757         /**
   1758          * For partial wake locks, keep track of whether we are in the list
   1759          * to consume CPU cycles.
   1760          */
   1761         boolean mInList;
   1762 
   1763         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   1764                 TimeBase timeBase, Parcel in) {
   1765             super(clocks, type, timeBase, in);
   1766             mUid = uid;
   1767             mTimerPool = timerPool;
   1768             mUpdateTime = in.readLong();
   1769         }
   1770 
   1771         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   1772                 TimeBase timeBase) {
   1773             super(clocks, type, timeBase);
   1774             mUid = uid;
   1775             mTimerPool = timerPool;
   1776         }
   1777 
   1778         public void setTimeout(long timeout) {
   1779             mTimeout = timeout;
   1780         }
   1781 
   1782         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   1783             super.writeToParcel(out, elapsedRealtimeUs);
   1784             out.writeLong(mUpdateTime);
   1785         }
   1786 
   1787         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1788             if (mNesting > 0) {
   1789                 if (DEBUG && mType < 0) {
   1790                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
   1791                 }
   1792                 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
   1793                 mUpdateTime = baseRealtime;
   1794                 if (DEBUG && mType < 0) {
   1795                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
   1796                 }
   1797             }
   1798         }
   1799 
   1800         public void logState(Printer pw, String prefix) {
   1801             super.logState(pw, prefix);
   1802             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
   1803                     + " mAcquireTime=" + mAcquireTime);
   1804         }
   1805 
   1806         public void startRunningLocked(long elapsedRealtimeMs) {
   1807             if (mNesting++ == 0) {
   1808                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
   1809                 mUpdateTime = batteryRealtime;
   1810                 if (mTimerPool != null) {
   1811                     // Accumulate time to all currently active timers before adding
   1812                     // this new one to the pool.
   1813                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
   1814                     // Add this timer to the active pool
   1815                     mTimerPool.add(this);
   1816                 }
   1817                 // Increment the count
   1818                 mCount++;
   1819                 mAcquireTime = mTotalTime;
   1820                 if (DEBUG && mType < 0) {
   1821                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
   1822                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
   1823                             + " mAcquireTime=" + mAcquireTime);
   1824                 }
   1825             }
   1826         }
   1827 
   1828         public boolean isRunningLocked() {
   1829             return mNesting > 0;
   1830         }
   1831 
   1832         public void stopRunningLocked(long elapsedRealtimeMs) {
   1833             // Ignore attempt to stop a timer that isn't running
   1834             if (mNesting == 0) {
   1835                 return;
   1836             }
   1837             if (--mNesting == 0) {
   1838                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
   1839                 if (mTimerPool != null) {
   1840                     // Accumulate time to all active counters, scaled by the total
   1841                     // active in the pool, before taking this one out of the pool.
   1842                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
   1843                     // Remove this timer from the active pool
   1844                     mTimerPool.remove(this);
   1845                 } else {
   1846                     mNesting = 1;
   1847                     mTotalTime = computeRunTimeLocked(batteryRealtime);
   1848                     mNesting = 0;
   1849                 }
   1850 
   1851                 if (DEBUG && mType < 0) {
   1852                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
   1853                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
   1854                             + " mAcquireTime=" + mAcquireTime);
   1855                 }
   1856 
   1857                 if (mTotalTime == mAcquireTime) {
   1858                     // If there was no change in the time, then discard this
   1859                     // count.  A somewhat cheezy strategy, but hey.
   1860                     mCount--;
   1861                 }
   1862             }
   1863         }
   1864 
   1865         public void stopAllRunningLocked(long elapsedRealtimeMs) {
   1866             if (mNesting > 0) {
   1867                 mNesting = 1;
   1868                 stopRunningLocked(elapsedRealtimeMs);
   1869             }
   1870         }
   1871 
   1872         // Update the total time for all other running Timers with the same type as this Timer
   1873         // due to a change in timer count
   1874         private static long refreshTimersLocked(long batteryRealtime,
   1875                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
   1876             long selfTime = 0;
   1877             final int N = pool.size();
   1878             for (int i=N-1; i>= 0; i--) {
   1879                 final StopwatchTimer t = pool.get(i);
   1880                 long heldTime = batteryRealtime - t.mUpdateTime;
   1881                 if (heldTime > 0) {
   1882                     final long myTime = heldTime / N;
   1883                     if (t == self) {
   1884                         selfTime = myTime;
   1885                     }
   1886                     t.mTotalTime += myTime;
   1887                 }
   1888                 t.mUpdateTime = batteryRealtime;
   1889             }
   1890             return selfTime;
   1891         }
   1892 
   1893         @Override
   1894         protected long computeRunTimeLocked(long curBatteryRealtime) {
   1895             if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
   1896                 curBatteryRealtime = mUpdateTime + mTimeout;
   1897             }
   1898             return mTotalTime + (mNesting > 0
   1899                     ? (curBatteryRealtime - mUpdateTime)
   1900                             / (mTimerPool != null ? mTimerPool.size() : 1)
   1901                     : 0);
   1902         }
   1903 
   1904         @Override
   1905         protected int computeCurrentCountLocked() {
   1906             return mCount;
   1907         }
   1908 
   1909         @Override
   1910         public boolean reset(boolean detachIfReset) {
   1911             boolean canDetach = mNesting <= 0;
   1912             super.reset(canDetach && detachIfReset);
   1913             if (mNesting > 0) {
   1914                 mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
   1915             }
   1916             mAcquireTime = mTotalTime;
   1917             return canDetach;
   1918         }
   1919 
   1920         @Override
   1921         public void detach() {
   1922             super.detach();
   1923             if (mTimerPool != null) {
   1924                 mTimerPool.remove(this);
   1925             }
   1926         }
   1927 
   1928         @Override
   1929         public void readSummaryFromParcelLocked(Parcel in) {
   1930             super.readSummaryFromParcelLocked(in);
   1931             mNesting = 0;
   1932         }
   1933 
   1934         /**
   1935          * Set the mark so that we can query later for the total time the timer has
   1936          * accumulated since this point. The timer can be running or not.
   1937          *
   1938          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
   1939          */
   1940         public void setMark(long elapsedRealtimeMs) {
   1941             final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
   1942             if (mNesting > 0) {
   1943                 // We are running.
   1944                 if (mTimerPool != null) {
   1945                     refreshTimersLocked(batteryRealtime, mTimerPool, this);
   1946                 } else {
   1947                     mTotalTime += batteryRealtime - mUpdateTime;
   1948                     mUpdateTime = batteryRealtime;
   1949                 }
   1950             }
   1951             mTimeBeforeMark = mTotalTime;
   1952         }
   1953     }
   1954 
   1955     public abstract class OverflowArrayMap<T> {
   1956         private static final String OVERFLOW_NAME = "*overflow*";
   1957 
   1958         final int mUid;
   1959         final ArrayMap<String, T> mMap = new ArrayMap<>();
   1960         T mCurOverflow;
   1961         ArrayMap<String, MutableInt> mActiveOverflow;
   1962         long mLastOverflowTime;
   1963         long mLastOverflowFinishTime;
   1964         long mLastClearTime;
   1965         long mLastCleanupTime;
   1966 
   1967         public OverflowArrayMap(int uid) {
   1968             mUid = uid;
   1969         }
   1970 
   1971         public ArrayMap<String, T> getMap() {
   1972             return mMap;
   1973         }
   1974 
   1975         public void clear() {
   1976             mLastClearTime = SystemClock.elapsedRealtime();
   1977             mMap.clear();
   1978             mCurOverflow = null;
   1979             mActiveOverflow = null;
   1980         }
   1981 
   1982         public void add(String name, T obj) {
   1983             if (name == null) {
   1984                 name = "";
   1985             }
   1986             mMap.put(name, obj);
   1987             if (OVERFLOW_NAME.equals(name)) {
   1988                 mCurOverflow = obj;
   1989             }
   1990         }
   1991 
   1992         public void cleanup() {
   1993             mLastCleanupTime = SystemClock.elapsedRealtime();
   1994             if (mActiveOverflow != null) {
   1995                 if (mActiveOverflow.size() == 0) {
   1996                     mActiveOverflow = null;
   1997                 }
   1998             }
   1999             if (mActiveOverflow == null) {
   2000                 // There is no currently active overflow, so we should no longer have
   2001                 // an overflow entry.
   2002                 if (mMap.containsKey(OVERFLOW_NAME)) {
   2003                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
   2004                             + mMap.get(OVERFLOW_NAME));
   2005                     mMap.remove(OVERFLOW_NAME);
   2006                 }
   2007                 mCurOverflow = null;
   2008             } else {
   2009                 // There is currently active overflow, so we should still have an overflow entry.
   2010                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
   2011                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
   2012                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
   2013                 }
   2014             }
   2015         }
   2016 
   2017         public T startObject(String name) {
   2018             if (name == null) {
   2019                 name = "";
   2020             }
   2021             T obj = mMap.get(name);
   2022             if (obj != null) {
   2023                 return obj;
   2024             }
   2025 
   2026             // No object exists for the given name, but do we currently have it
   2027             // running as part of the overflow?
   2028             if (mActiveOverflow != null) {
   2029                 MutableInt over = mActiveOverflow.get(name);
   2030                 if (over != null) {
   2031                     // We are already actively counting this name in the overflow object.
   2032                     obj = mCurOverflow;
   2033                     if (obj == null) {
   2034                         // Shouldn't be here, but we'll try to recover.
   2035                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
   2036                         obj = mCurOverflow = instantiateObject();
   2037                         mMap.put(OVERFLOW_NAME, obj);
   2038                     }
   2039                     over.value++;
   2040                     return obj;
   2041                 }
   2042             }
   2043 
   2044             // No object exists for given name nor in the overflow; we need to make
   2045             // a new one.
   2046             final int N = mMap.size();
   2047             if (N >= MAX_WAKELOCKS_PER_UID) {
   2048                 // Went over the limit on number of objects to track; this one goes
   2049                 // in to the overflow.
   2050                 obj = mCurOverflow;
   2051                 if (obj == null) {
   2052                     // Need to start overflow now...
   2053                     obj = mCurOverflow = instantiateObject();
   2054                     mMap.put(OVERFLOW_NAME, obj);
   2055                 }
   2056                 if (mActiveOverflow == null) {
   2057                     mActiveOverflow = new ArrayMap<>();
   2058                 }
   2059                 mActiveOverflow.put(name, new MutableInt(1));
   2060                 mLastOverflowTime = SystemClock.elapsedRealtime();
   2061                 return obj;
   2062             }
   2063 
   2064             // Normal case where we just need to make a new object.
   2065             obj = instantiateObject();
   2066             mMap.put(name, obj);
   2067             return obj;
   2068         }
   2069 
   2070         public T stopObject(String name) {
   2071             if (name == null) {
   2072                 name = "";
   2073             }
   2074             T obj = mMap.get(name);
   2075             if (obj != null) {
   2076                 return obj;
   2077             }
   2078 
   2079             // No object exists for the given name, but do we currently have it
   2080             // running as part of the overflow?
   2081             if (mActiveOverflow != null) {
   2082                 MutableInt over = mActiveOverflow.get(name);
   2083                 if (over != null) {
   2084                     // We are already actively counting this name in the overflow object.
   2085                     obj = mCurOverflow;
   2086                     if (obj != null) {
   2087                         over.value--;
   2088                         if (over.value <= 0) {
   2089                             mActiveOverflow.remove(name);
   2090                             mLastOverflowFinishTime = SystemClock.elapsedRealtime();
   2091                         }
   2092                         return obj;
   2093                     }
   2094                 }
   2095             }
   2096 
   2097             // Huh, they are stopping an active operation but we can't find one!
   2098             // That's not good.
   2099             StringBuilder sb = new StringBuilder();
   2100             sb.append("Unable to find object for ");
   2101             sb.append(name);
   2102             sb.append(" in uid ");
   2103             sb.append(mUid);
   2104             sb.append(" mapsize=");
   2105             sb.append(mMap.size());
   2106             sb.append(" activeoverflow=");
   2107             sb.append(mActiveOverflow);
   2108             sb.append(" curoverflow=");
   2109             sb.append(mCurOverflow);
   2110             long now = SystemClock.elapsedRealtime();
   2111             if (mLastOverflowTime != 0) {
   2112                 sb.append(" lastOverflowTime=");
   2113                 TimeUtils.formatDuration(mLastOverflowTime-now, sb);
   2114             }
   2115             if (mLastOverflowFinishTime != 0) {
   2116                 sb.append(" lastOverflowFinishTime=");
   2117                 TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb);
   2118             }
   2119             if (mLastClearTime != 0) {
   2120                 sb.append(" lastClearTime=");
   2121                 TimeUtils.formatDuration(mLastClearTime-now, sb);
   2122             }
   2123             if (mLastCleanupTime != 0) {
   2124                 sb.append(" lastCleanupTime=");
   2125                 TimeUtils.formatDuration(mLastCleanupTime-now, sb);
   2126             }
   2127             Slog.wtf(TAG, sb.toString());
   2128             return null;
   2129         }
   2130 
   2131         public abstract T instantiateObject();
   2132     }
   2133 
   2134     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
   2135             implements Parcelable {
   2136         private final LongSamplingCounter mIdleTimeMillis;
   2137         private final LongSamplingCounter mRxTimeMillis;
   2138         private final LongSamplingCounter[] mTxTimeMillis;
   2139         private final LongSamplingCounter mPowerDrainMaMs;
   2140 
   2141         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
   2142             mIdleTimeMillis = new LongSamplingCounter(timeBase);
   2143             mRxTimeMillis = new LongSamplingCounter(timeBase);
   2144             mTxTimeMillis = new LongSamplingCounter[numTxStates];
   2145             for (int i = 0; i < numTxStates; i++) {
   2146                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
   2147             }
   2148             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
   2149         }
   2150 
   2151         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
   2152             mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
   2153             mRxTimeMillis = new LongSamplingCounter(timeBase, in);
   2154             final int recordedTxStates = in.readInt();
   2155             if (recordedTxStates != numTxStates) {
   2156                 throw new ParcelFormatException("inconsistent tx state lengths");
   2157             }
   2158 
   2159             mTxTimeMillis = new LongSamplingCounter[numTxStates];
   2160             for (int i = 0; i < numTxStates; i++) {
   2161                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
   2162             }
   2163             mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
   2164         }
   2165 
   2166         public void readSummaryFromParcel(Parcel in) {
   2167             mIdleTimeMillis.readSummaryFromParcelLocked(in);
   2168             mRxTimeMillis.readSummaryFromParcelLocked(in);
   2169             final int recordedTxStates = in.readInt();
   2170             if (recordedTxStates != mTxTimeMillis.length) {
   2171                 throw new ParcelFormatException("inconsistent tx state lengths");
   2172             }
   2173             for (LongSamplingCounter counter : mTxTimeMillis) {
   2174                 counter.readSummaryFromParcelLocked(in);
   2175             }
   2176             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
   2177         }
   2178 
   2179         @Override
   2180         public int describeContents() {
   2181             return 0;
   2182         }
   2183 
   2184         public void writeSummaryToParcel(Parcel dest) {
   2185             mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
   2186             mRxTimeMillis.writeSummaryFromParcelLocked(dest);
   2187             dest.writeInt(mTxTimeMillis.length);
   2188             for (LongSamplingCounter counter : mTxTimeMillis) {
   2189                 counter.writeSummaryFromParcelLocked(dest);
   2190             }
   2191             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
   2192         }
   2193 
   2194         @Override
   2195         public void writeToParcel(Parcel dest, int flags) {
   2196             mIdleTimeMillis.writeToParcel(dest);
   2197             mRxTimeMillis.writeToParcel(dest);
   2198             dest.writeInt(mTxTimeMillis.length);
   2199             for (LongSamplingCounter counter : mTxTimeMillis) {
   2200                 counter.writeToParcel(dest);
   2201             }
   2202             mPowerDrainMaMs.writeToParcel(dest);
   2203         }
   2204 
   2205         public void reset(boolean detachIfReset) {
   2206             mIdleTimeMillis.reset(detachIfReset);
   2207             mRxTimeMillis.reset(detachIfReset);
   2208             for (LongSamplingCounter counter : mTxTimeMillis) {
   2209                 counter.reset(detachIfReset);
   2210             }
   2211             mPowerDrainMaMs.reset(detachIfReset);
   2212         }
   2213 
   2214         public void detach() {
   2215             mIdleTimeMillis.detach();
   2216             mRxTimeMillis.detach();
   2217             for (LongSamplingCounter counter : mTxTimeMillis) {
   2218                 counter.detach();
   2219             }
   2220             mPowerDrainMaMs.detach();
   2221         }
   2222 
   2223         /**
   2224          * @return a LongSamplingCounter, measuring time spent in the idle state in
   2225          * milliseconds.
   2226          */
   2227         @Override
   2228         public LongSamplingCounter getIdleTimeCounter() {
   2229             return mIdleTimeMillis;
   2230         }
   2231 
   2232         /**
   2233          * @return a LongSamplingCounter, measuring time spent in the receive state in
   2234          * milliseconds.
   2235          */
   2236         @Override
   2237         public LongSamplingCounter getRxTimeCounter() {
   2238             return mRxTimeMillis;
   2239         }
   2240 
   2241         /**
   2242          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
   2243          * milliseconds.
   2244          */
   2245         @Override
   2246         public LongSamplingCounter[] getTxTimeCounters() {
   2247             return mTxTimeMillis;
   2248         }
   2249 
   2250         /**
   2251          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
   2252          */
   2253         @Override
   2254         public LongSamplingCounter getPowerCounter() {
   2255             return mPowerDrainMaMs;
   2256         }
   2257     }
   2258 
   2259     /*
   2260      * Get the wakeup reason counter, and create a new one if one
   2261      * doesn't already exist.
   2262      */
   2263     public SamplingTimer getWakeupReasonTimerLocked(String name) {
   2264         SamplingTimer timer = mWakeupReasonStats.get(name);
   2265         if (timer == null) {
   2266             timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
   2267             mWakeupReasonStats.put(name, timer);
   2268         }
   2269         return timer;
   2270     }
   2271 
   2272     /*
   2273      * Get the KernelWakelockTimer associated with name, and create a new one if one
   2274      * doesn't already exist.
   2275      */
   2276     public SamplingTimer getKernelWakelockTimerLocked(String name) {
   2277         SamplingTimer kwlt = mKernelWakelockStats.get(name);
   2278         if (kwlt == null) {
   2279             kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
   2280             mKernelWakelockStats.put(name, kwlt);
   2281         }
   2282         return kwlt;
   2283     }
   2284 
   2285     private int writeHistoryTag(HistoryTag tag) {
   2286         Integer idxObj = mHistoryTagPool.get(tag);
   2287         int idx;
   2288         if (idxObj != null) {
   2289             idx = idxObj;
   2290         } else {
   2291             idx = mNextHistoryTagIdx;
   2292             HistoryTag key = new HistoryTag();
   2293             key.setTo(tag);
   2294             tag.poolIdx = idx;
   2295             mHistoryTagPool.put(key, idx);
   2296             mNextHistoryTagIdx++;
   2297             mNumHistoryTagChars += key.string.length() + 1;
   2298         }
   2299         return idx;
   2300     }
   2301 
   2302     private void readHistoryTag(int index, HistoryTag tag) {
   2303         tag.string = mReadHistoryStrings[index];
   2304         tag.uid = mReadHistoryUids[index];
   2305         tag.poolIdx = index;
   2306     }
   2307 
   2308     /*
   2309         The history delta format uses flags to denote further data in subsequent ints in the parcel.
   2310 
   2311         There is always the first token, which may contain the delta time, or an indicator of
   2312         the length of the time (int or long) following this token.
   2313 
   2314         First token: always present,
   2315         31              23              15               7             0
   2316         M|L|K|J|I|H|G|FE|D|C|B|A|T|T|TT|T|T|T|T|T|T|TT|T|T|T|T|T|T|T
   2317 
   2318         T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
   2319            follows containing the time, and 0x7ffff indicates a long immediately follows with the
   2320            delta time.
   2321         A: battery level changed and an int follows with battery data.
   2322         B: state changed and an int follows with state change data.
   2323         C: state2 has changed and an int follows with state2 change data.
   2324         D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
   2325         E: event data has changed and an event struct follows.
   2326         F: battery charge in coulombs has changed and an int with the charge follows.
   2327         G: state flag denoting that the mobile radio was active.
   2328         H: state flag denoting that the wifi radio was active.
   2329         I: state flag denoting that a wifi scan occurred.
   2330         J: state flag denoting that a wifi full lock was held.
   2331         K: state flag denoting that the gps was on.
   2332         L: state flag denoting that a wakelock was held.
   2333         M: state flag denoting that the cpu was running.
   2334 
   2335         Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
   2336         with the time delta.
   2337 
   2338         Battery level int: if A in the first token is set,
   2339         31              23              15               7             0
   2340         L|L|L|L|L|L|L|TT|T|T|T|T|T|T|TT|V|V|V|V|V|V|VV|V|V|V|V|V|V|D
   2341 
   2342         D: indicates that extra history details follow.
   2343         V: the battery voltage.
   2344         T: the battery temperature.
   2345         L: the battery level (out of 100).
   2346 
   2347         State change int: if B in the first token is set,
   2348         31              23              15               7             0
   2349         S|S|S|H|H|H|P|PF|E|D|C|B| | |A | | | | | | |  | | | | | | | 
   2350 
   2351         A: wifi multicast was on.
   2352         B: battery was plugged in.
   2353         C: screen was on.
   2354         D: phone was scanning for signal.
   2355         E: audio was on.
   2356         F: a sensor was active.
   2357 
   2358         State2 change int: if C in the first token is set,
   2359         31              23              15               7             0
   2360         M|L|K|J|I|H|H|GF|E|D|C| | | |  | | | | | | |  |B|B|B|A|A|A|A
   2361 
   2362         A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
   2363         B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
   2364         C: a bluetooth scan was active.
   2365         D: the camera was active.
   2366         E: bluetooth was on.
   2367         F: a phone call was active.
   2368         G: the device was charging.
   2369         H: 2 bits indicating the device-idle (doze) state: off, light, full
   2370         I: the flashlight was on.
   2371         J: wifi was on.
   2372         K: wifi was running.
   2373         L: video was playing.
   2374         M: power save mode was on.
   2375 
   2376         Wakelock/wakereason struct: if D in the first token is set,
   2377         TODO(adamlesinski): describe wakelock/wakereason struct.
   2378 
   2379         Event struct: if E in the first token is set,
   2380         TODO(adamlesinski): describe the event struct.
   2381 
   2382         History step details struct: if D in the battery level int is set,
   2383         TODO(adamlesinski): describe the history step details struct.
   2384 
   2385         Battery charge int: if F in the first token is set, an int representing the battery charge
   2386         in coulombs follows.
   2387      */
   2388 
   2389     // Part of initial delta int that specifies the time delta.
   2390     static final int DELTA_TIME_MASK = 0x7ffff;
   2391     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
   2392     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
   2393     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
   2394     // Flag in delta int: a new battery level int follows.
   2395     static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
   2396     // Flag in delta int: a new full state and battery status int follows.
   2397     static final int DELTA_STATE_FLAG                       = 0x00100000;
   2398     // Flag in delta int: a new full state2 int follows.
   2399     static final int DELTA_STATE2_FLAG                      = 0x00200000;
   2400     // Flag in delta int: contains a wakelock or wakeReason tag.
   2401     static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
   2402     // Flag in delta int: contains an event description.
   2403     static final int DELTA_EVENT_FLAG                       = 0x00800000;
   2404     // Flag in delta int: contains the battery charge count in uAh.
   2405     static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
   2406     // These upper bits are the frequently changing state bits.
   2407     static final int DELTA_STATE_MASK                       = 0xfe000000;
   2408 
   2409     // These are the pieces of battery state that are packed in to the upper bits of
   2410     // the state int that have been packed in to the first delta int.  They must fit
   2411     // in STATE_BATTERY_MASK.
   2412     static final int STATE_BATTERY_MASK         = 0xff000000;
   2413     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
   2414     static final int STATE_BATTERY_STATUS_SHIFT = 29;
   2415     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
   2416     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
   2417     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
   2418     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
   2419 
   2420     // We use the low bit of the battery state int to indicate that we have full details
   2421     // from a battery level change.
   2422     static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
   2423 
   2424     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
   2425         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
   2426             dest.writeInt(DELTA_TIME_ABS);
   2427             cur.writeToParcel(dest, 0);
   2428             return;
   2429         }
   2430 
   2431         final long deltaTime = cur.time - last.time;
   2432         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
   2433         final int lastStateInt = buildStateInt(last);
   2434 
   2435         int deltaTimeToken;
   2436         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
   2437             deltaTimeToken = DELTA_TIME_LONG;
   2438         } else if (deltaTime >= DELTA_TIME_ABS) {
   2439             deltaTimeToken = DELTA_TIME_INT;
   2440         } else {
   2441             deltaTimeToken = (int)deltaTime;
   2442         }
   2443         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
   2444         final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
   2445                 ? BATTERY_DELTA_LEVEL_FLAG : 0;
   2446         final boolean computeStepDetails = includeStepDetails != 0
   2447                 || mLastHistoryStepDetails == null;
   2448         final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
   2449         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
   2450         if (batteryLevelIntChanged) {
   2451             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
   2452         }
   2453         final int stateInt = buildStateInt(cur);
   2454         final boolean stateIntChanged = stateInt != lastStateInt;
   2455         if (stateIntChanged) {
   2456             firstToken |= DELTA_STATE_FLAG;
   2457         }
   2458         final boolean state2IntChanged = cur.states2 != last.states2;
   2459         if (state2IntChanged) {
   2460             firstToken |= DELTA_STATE2_FLAG;
   2461         }
   2462         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
   2463             firstToken |= DELTA_WAKELOCK_FLAG;
   2464         }
   2465         if (cur.eventCode != HistoryItem.EVENT_NONE) {
   2466             firstToken |= DELTA_EVENT_FLAG;
   2467         }
   2468 
   2469         final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
   2470         if (batteryChargeChanged) {
   2471             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
   2472         }
   2473         dest.writeInt(firstToken);
   2474         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
   2475                 + " deltaTime=" + deltaTime);
   2476 
   2477         if (deltaTimeToken >= DELTA_TIME_INT) {
   2478             if (deltaTimeToken == DELTA_TIME_INT) {
   2479                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
   2480                 dest.writeInt((int)deltaTime);
   2481             } else {
   2482                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
   2483                 dest.writeLong(deltaTime);
   2484             }
   2485         }
   2486         if (batteryLevelIntChanged) {
   2487             dest.writeInt(batteryLevelInt);
   2488             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
   2489                     + Integer.toHexString(batteryLevelInt)
   2490                     + " batteryLevel=" + cur.batteryLevel
   2491                     + " batteryTemp=" + cur.batteryTemperature
   2492                     + " batteryVolt=" + (int)cur.batteryVoltage);
   2493         }
   2494         if (stateIntChanged) {
   2495             dest.writeInt(stateInt);
   2496             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
   2497                     + Integer.toHexString(stateInt)
   2498                     + " batteryStatus=" + cur.batteryStatus
   2499                     + " batteryHealth=" + cur.batteryHealth
   2500                     + " batteryPlugType=" + cur.batteryPlugType
   2501                     + " states=0x" + Integer.toHexString(cur.states));
   2502         }
   2503         if (state2IntChanged) {
   2504             dest.writeInt(cur.states2);
   2505             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
   2506                     + Integer.toHexString(cur.states2));
   2507         }
   2508         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
   2509             int wakeLockIndex;
   2510             int wakeReasonIndex;
   2511             if (cur.wakelockTag != null) {
   2512                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
   2513                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
   2514                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
   2515             } else {
   2516                 wakeLockIndex = 0xffff;
   2517             }
   2518             if (cur.wakeReasonTag != null) {
   2519                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
   2520                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
   2521                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
   2522             } else {
   2523                 wakeReasonIndex = 0xffff;
   2524             }
   2525             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
   2526         }
   2527         if (cur.eventCode != HistoryItem.EVENT_NONE) {
   2528             int index = writeHistoryTag(cur.eventTag);
   2529             int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
   2530             dest.writeInt(codeAndIndex);
   2531             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
   2532                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
   2533                     + cur.eventTag.string);
   2534         }
   2535         if (computeStepDetails) {
   2536             if (mPlatformIdleStateCallback != null) {
   2537                 mCurHistoryStepDetails.statPlatformIdleState =
   2538                         mPlatformIdleStateCallback.getPlatformLowPowerStats();
   2539                 if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
   2540                         mCurHistoryStepDetails.statPlatformIdleState);
   2541             }
   2542             computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
   2543             if (includeStepDetails != 0) {
   2544                 mCurHistoryStepDetails.writeToParcel(dest);
   2545             }
   2546             cur.stepDetails = mCurHistoryStepDetails;
   2547             mLastHistoryStepDetails = mCurHistoryStepDetails;
   2548         } else {
   2549             cur.stepDetails = null;
   2550         }
   2551         if (mLastHistoryStepLevel < cur.batteryLevel) {
   2552             mLastHistoryStepDetails = null;
   2553         }
   2554         mLastHistoryStepLevel = cur.batteryLevel;
   2555 
   2556         if (batteryChargeChanged) {
   2557             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
   2558             dest.writeInt(cur.batteryChargeUAh);
   2559         }
   2560     }
   2561 
   2562     private int buildBatteryLevelInt(HistoryItem h) {
   2563         return ((((int)h.batteryLevel)<<25)&0xfe000000)
   2564                 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
   2565                 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
   2566     }
   2567 
   2568     private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
   2569         out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
   2570         out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
   2571         out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
   2572     }
   2573 
   2574     private int buildStateInt(HistoryItem h) {
   2575         int plugType = 0;
   2576         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
   2577             plugType = 1;
   2578         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
   2579             plugType = 2;
   2580         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
   2581             plugType = 3;
   2582         }
   2583         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
   2584                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
   2585                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
   2586                 | (h.states&(~STATE_BATTERY_MASK));
   2587     }
   2588 
   2589     private void computeHistoryStepDetails(final HistoryStepDetails out,
   2590             final HistoryStepDetails last) {
   2591         final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
   2592 
   2593         // Perform a CPU update right after we do this collection, so we have started
   2594         // collecting good data for the next step.
   2595         requestImmediateCpuUpdate();
   2596 
   2597         if (last == null) {
   2598             // We are not generating a delta, so all we need to do is reset the stats
   2599             // we will later be doing a delta from.
   2600             final int NU = mUidStats.size();
   2601             for (int i=0; i<NU; i++) {
   2602                 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   2603                 uid.mLastStepUserTime = uid.mCurStepUserTime;
   2604                 uid.mLastStepSystemTime = uid.mCurStepSystemTime;
   2605             }
   2606             mLastStepCpuUserTime = mCurStepCpuUserTime;
   2607             mLastStepCpuSystemTime = mCurStepCpuSystemTime;
   2608             mLastStepStatUserTime = mCurStepStatUserTime;
   2609             mLastStepStatSystemTime = mCurStepStatSystemTime;
   2610             mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
   2611             mLastStepStatIrqTime = mCurStepStatIrqTime;
   2612             mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
   2613             mLastStepStatIdleTime = mCurStepStatIdleTime;
   2614             tmp.clear();
   2615             return;
   2616         }
   2617         if (DEBUG) {
   2618             Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
   2619                     + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
   2620                     + " irq=" + mLastStepStatIrqTime + " sirq="
   2621                     + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
   2622             Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
   2623                     + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
   2624                     + " irq=" + mCurStepStatIrqTime + " sirq="
   2625                     + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
   2626         }
   2627         out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
   2628         out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
   2629         out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
   2630         out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
   2631         out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
   2632         out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
   2633         out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
   2634         out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
   2635         out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
   2636         out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
   2637         out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
   2638         final int NU = mUidStats.size();
   2639         for (int i=0; i<NU; i++) {
   2640             final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   2641             final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
   2642             final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
   2643             final int totalTime = totalUTime + totalSTime;
   2644             uid.mLastStepUserTime = uid.mCurStepUserTime;
   2645             uid.mLastStepSystemTime = uid.mCurStepSystemTime;
   2646             if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
   2647                 continue;
   2648             }
   2649             if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
   2650                 out.appCpuUid3 = uid.mUid;
   2651                 out.appCpuUTime3 = totalUTime;
   2652                 out.appCpuSTime3 = totalSTime;
   2653             } else {
   2654                 out.appCpuUid3 = out.appCpuUid2;
   2655                 out.appCpuUTime3 = out.appCpuUTime2;
   2656                 out.appCpuSTime3 = out.appCpuSTime2;
   2657                 if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
   2658                     out.appCpuUid2 = uid.mUid;
   2659                     out.appCpuUTime2 = totalUTime;
   2660                     out.appCpuSTime2 = totalSTime;
   2661                 } else {
   2662                     out.appCpuUid2 = out.appCpuUid1;
   2663                     out.appCpuUTime2 = out.appCpuUTime1;
   2664                     out.appCpuSTime2 = out.appCpuSTime1;
   2665                     out.appCpuUid1 = uid.mUid;
   2666                     out.appCpuUTime1 = totalUTime;
   2667                     out.appCpuSTime1 = totalSTime;
   2668                 }
   2669             }
   2670         }
   2671         mLastStepCpuUserTime = mCurStepCpuUserTime;
   2672         mLastStepCpuSystemTime = mCurStepCpuSystemTime;
   2673         mLastStepStatUserTime = mCurStepStatUserTime;
   2674         mLastStepStatSystemTime = mCurStepStatSystemTime;
   2675         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
   2676         mLastStepStatIrqTime = mCurStepStatIrqTime;
   2677         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
   2678         mLastStepStatIdleTime = mCurStepStatIdleTime;
   2679     }
   2680 
   2681     public void readHistoryDelta(Parcel src, HistoryItem cur) {
   2682         int firstToken = src.readInt();
   2683         int deltaTimeToken = firstToken&DELTA_TIME_MASK;
   2684         cur.cmd = HistoryItem.CMD_UPDATE;
   2685         cur.numReadInts = 1;
   2686         if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
   2687                 + " deltaTimeToken=" + deltaTimeToken);
   2688 
   2689         if (deltaTimeToken < DELTA_TIME_ABS) {
   2690             cur.time += deltaTimeToken;
   2691         } else if (deltaTimeToken == DELTA_TIME_ABS) {
   2692             cur.time = src.readLong();
   2693             cur.numReadInts += 2;
   2694             if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
   2695             cur.readFromParcel(src);
   2696             return;
   2697         } else if (deltaTimeToken == DELTA_TIME_INT) {
   2698             int delta = src.readInt();
   2699             cur.time += delta;
   2700             cur.numReadInts += 1;
   2701             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
   2702         } else {
   2703             long delta = src.readLong();
   2704             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
   2705             cur.time += delta;
   2706             cur.numReadInts += 2;
   2707         }
   2708 
   2709         final int batteryLevelInt;
   2710         if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
   2711             batteryLevelInt = src.readInt();
   2712             readBatteryLevelInt(batteryLevelInt, cur);
   2713             cur.numReadInts += 1;
   2714             if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
   2715                     + Integer.toHexString(batteryLevelInt)
   2716                     + " batteryLevel=" + cur.batteryLevel
   2717                     + " batteryTemp=" + cur.batteryTemperature
   2718                     + " batteryVolt=" + (int)cur.batteryVoltage);
   2719         } else {
   2720             batteryLevelInt = 0;
   2721         }
   2722 
   2723         if ((firstToken&DELTA_STATE_FLAG) != 0) {
   2724             int stateInt = src.readInt();
   2725             cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
   2726             cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
   2727                     & STATE_BATTERY_STATUS_MASK);
   2728             cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
   2729                     & STATE_BATTERY_HEALTH_MASK);
   2730             cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
   2731                     & STATE_BATTERY_PLUG_MASK);
   2732             switch (cur.batteryPlugType) {
   2733                 case 1:
   2734                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
   2735                     break;
   2736                 case 2:
   2737                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
   2738                     break;
   2739                 case 3:
   2740                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
   2741                     break;
   2742             }
   2743             cur.numReadInts += 1;
   2744             if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
   2745                     + Integer.toHexString(stateInt)
   2746                     + " batteryStatus=" + cur.batteryStatus
   2747                     + " batteryHealth=" + cur.batteryHealth
   2748                     + " batteryPlugType=" + cur.batteryPlugType
   2749                     + " states=0x" + Integer.toHexString(cur.states));
   2750         } else {
   2751             cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
   2752         }
   2753 
   2754         if ((firstToken&DELTA_STATE2_FLAG) != 0) {
   2755             cur.states2 = src.readInt();
   2756             if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
   2757                     + Integer.toHexString(cur.states2));
   2758         }
   2759 
   2760         if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
   2761             int indexes = src.readInt();
   2762             int wakeLockIndex = indexes&0xffff;
   2763             int wakeReasonIndex = (indexes>>16)&0xffff;
   2764             if (wakeLockIndex != 0xffff) {
   2765                 cur.wakelockTag = cur.localWakelockTag;
   2766                 readHistoryTag(wakeLockIndex, cur.wakelockTag);
   2767                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
   2768                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
   2769             } else {
   2770                 cur.wakelockTag = null;
   2771             }
   2772             if (wakeReasonIndex != 0xffff) {
   2773                 cur.wakeReasonTag = cur.localWakeReasonTag;
   2774                 readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
   2775                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
   2776                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
   2777             } else {
   2778                 cur.wakeReasonTag = null;
   2779             }
   2780             cur.numReadInts += 1;
   2781         } else {
   2782             cur.wakelockTag = null;
   2783             cur.wakeReasonTag = null;
   2784         }
   2785 
   2786         if ((firstToken&DELTA_EVENT_FLAG) != 0) {
   2787             cur.eventTag = cur.localEventTag;
   2788             final int codeAndIndex = src.readInt();
   2789             cur.eventCode = (codeAndIndex&0xffff);
   2790             final int index = ((codeAndIndex>>16)&0xffff);
   2791             readHistoryTag(index, cur.eventTag);
   2792             cur.numReadInts += 1;
   2793             if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
   2794                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
   2795                     + cur.eventTag.string);
   2796         } else {
   2797             cur.eventCode = HistoryItem.EVENT_NONE;
   2798         }
   2799 
   2800         if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
   2801             cur.stepDetails = mReadHistoryStepDetails;
   2802             cur.stepDetails.readFromParcel(src);
   2803         } else {
   2804             cur.stepDetails = null;
   2805         }
   2806 
   2807         if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
   2808             cur.batteryChargeUAh = src.readInt();
   2809         }
   2810     }
   2811 
   2812     @Override
   2813     public void commitCurrentHistoryBatchLocked() {
   2814         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
   2815     }
   2816 
   2817     void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
   2818         if (!mHaveBatteryLevel || !mRecordingHistory) {
   2819             return;
   2820         }
   2821 
   2822         final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
   2823         final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
   2824         final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
   2825         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
   2826         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
   2827         if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
   2828                 + Integer.toHexString(diffStates) + " lastDiff="
   2829                 + Integer.toHexString(lastDiffStates) + " diff2="
   2830                 + Integer.toHexString(diffStates2) + " lastDiff2="
   2831                 + Integer.toHexString(lastDiffStates2));
   2832         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
   2833                 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
   2834                 && (diffStates2&lastDiffStates2) == 0
   2835                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
   2836                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
   2837                 && mHistoryLastWritten.stepDetails == null
   2838                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
   2839                         || cur.eventCode == HistoryItem.EVENT_NONE)
   2840                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
   2841                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
   2842                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
   2843                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
   2844                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
   2845                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
   2846             // We can merge this new change in with the last one.  Merging is
   2847             // allowed as long as only the states have changed, and within those states
   2848             // as long as no bit has changed both between now and the last entry, as
   2849             // well as the last entry and the one before it (so we capture any toggles).
   2850             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
   2851             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
   2852             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
   2853             mHistoryBufferLastPos = -1;
   2854             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
   2855             // If the last written history had a wakelock tag, we need to retain it.
   2856             // Note that the condition above made sure that we aren't in a case where
   2857             // both it and the current history item have a wakelock tag.
   2858             if (mHistoryLastWritten.wakelockTag != null) {
   2859                 cur.wakelockTag = cur.localWakelockTag;
   2860                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
   2861             }
   2862             // If the last written history had a wake reason tag, we need to retain it.
   2863             // Note that the condition above made sure that we aren't in a case where
   2864             // both it and the current history item have a wakelock tag.
   2865             if (mHistoryLastWritten.wakeReasonTag != null) {
   2866                 cur.wakeReasonTag = cur.localWakeReasonTag;
   2867                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
   2868             }
   2869             // If the last written history had an event, we need to retain it.
   2870             // Note that the condition above made sure that we aren't in a case where
   2871             // both it and the current history item have an event.
   2872             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
   2873                 cur.eventCode = mHistoryLastWritten.eventCode;
   2874                 cur.eventTag = cur.localEventTag;
   2875                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
   2876             }
   2877             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
   2878         }
   2879 
   2880         final int dataSize = mHistoryBuffer.dataSize();
   2881         if (dataSize >= MAX_HISTORY_BUFFER) {
   2882             if (!mHistoryOverflow) {
   2883                 mHistoryOverflow = true;
   2884                 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
   2885                 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_OVERFLOW, cur);
   2886                 return;
   2887             }
   2888 
   2889             // After overflow, we allow various bit-wise states to settle to 0.
   2890             boolean writeAnyway = false;
   2891             final int curStates = cur.states & HistoryItem.SETTLE_TO_ZERO_STATES
   2892                     & mActiveHistoryStates;
   2893             if (mHistoryLastWritten.states != curStates) {
   2894                 // mActiveHistoryStates keeps track of which bits in .states are now being
   2895                 // forced to 0.
   2896                 int old = mActiveHistoryStates;
   2897                 mActiveHistoryStates &= curStates | ~HistoryItem.SETTLE_TO_ZERO_STATES;
   2898                 writeAnyway |= old != mActiveHistoryStates;
   2899             }
   2900             final int curStates2 = cur.states2 & HistoryItem.SETTLE_TO_ZERO_STATES2
   2901                     & mActiveHistoryStates2;
   2902             if (mHistoryLastWritten.states2 != curStates2) {
   2903                 // mActiveHistoryStates2 keeps track of which bits in .states2 are now being
   2904                 // forced to 0.
   2905                 int old = mActiveHistoryStates2;
   2906                 mActiveHistoryStates2 &= curStates2 | ~HistoryItem.SETTLE_TO_ZERO_STATES2;
   2907                 writeAnyway |= old != mActiveHistoryStates2;
   2908             }
   2909 
   2910             // Once we've reached the maximum number of items, we only
   2911             // record changes to the battery level and the most interesting states.
   2912             // Once we've reached the maximum maximum number of items, we only
   2913             // record changes to the battery level.
   2914             if (!writeAnyway && mHistoryLastWritten.batteryLevel == cur.batteryLevel &&
   2915                     (dataSize >= MAX_MAX_HISTORY_BUFFER
   2916                             || ((mHistoryLastWritten.states^cur.states)
   2917                                     & HistoryItem.MOST_INTERESTING_STATES) == 0
   2918                             || ((mHistoryLastWritten.states2^cur.states2)
   2919                                     & HistoryItem.MOST_INTERESTING_STATES2) == 0)) {
   2920                 return;
   2921             }
   2922 
   2923             addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
   2924             return;
   2925         }
   2926 
   2927         if (dataSize == 0) {
   2928             // The history is currently empty; we need it to start with a time stamp.
   2929             cur.currentTime = System.currentTimeMillis();
   2930             addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_RESET, cur);
   2931         }
   2932         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
   2933     }
   2934 
   2935     private void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd,
   2936             HistoryItem cur) {
   2937         if (mIteratingHistory) {
   2938             throw new IllegalStateException("Can't do this while iterating history!");
   2939         }
   2940         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
   2941         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
   2942         mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
   2943         mHistoryLastWritten.states &= mActiveHistoryStates;
   2944         mHistoryLastWritten.states2 &= mActiveHistoryStates2;
   2945         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
   2946         mLastHistoryElapsedRealtime = elapsedRealtimeMs;
   2947         cur.wakelockTag = null;
   2948         cur.wakeReasonTag = null;
   2949         cur.eventCode = HistoryItem.EVENT_NONE;
   2950         cur.eventTag = null;
   2951         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
   2952                 + " now " + mHistoryBuffer.dataPosition()
   2953                 + " size is now " + mHistoryBuffer.dataSize());
   2954     }
   2955 
   2956     int mChangedStates = 0;
   2957     int mChangedStates2 = 0;
   2958 
   2959     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
   2960         if (mTrackRunningHistoryElapsedRealtime != 0) {
   2961             final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
   2962             final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
   2963             if (diffUptime < (diffElapsed-20)) {
   2964                 final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
   2965                 mHistoryAddTmp.setTo(mHistoryLastWritten);
   2966                 mHistoryAddTmp.wakelockTag = null;
   2967                 mHistoryAddTmp.wakeReasonTag = null;
   2968                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
   2969                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
   2970                 addHistoryRecordInnerLocked(wakeElapsedTime, uptimeMs, mHistoryAddTmp);
   2971             }
   2972         }
   2973         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
   2974         mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
   2975         mTrackRunningHistoryUptime = uptimeMs;
   2976         addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
   2977     }
   2978 
   2979     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
   2980         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
   2981 
   2982         if (!USE_OLD_HISTORY) {
   2983             return;
   2984         }
   2985 
   2986         if (!mHaveBatteryLevel || !mRecordingHistory) {
   2987             return;
   2988         }
   2989 
   2990         // If the current time is basically the same as the last time,
   2991         // and no states have since the last recorded entry changed and
   2992         // are now resetting back to their original value, then just collapse
   2993         // into one record.
   2994         if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
   2995                 && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
   2996                 && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
   2997                 && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
   2998             // If the current is the same as the one before, then we no
   2999             // longer need the entry.
   3000             if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
   3001                     && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
   3002                     && mHistoryLastEnd.sameNonEvent(cur)) {
   3003                 mHistoryLastEnd.next = null;
   3004                 mHistoryEnd.next = mHistoryCache;
   3005                 mHistoryCache = mHistoryEnd;
   3006                 mHistoryEnd = mHistoryLastEnd;
   3007                 mHistoryLastEnd = null;
   3008             } else {
   3009                 mChangedStates |= mHistoryEnd.states^(cur.states&mActiveHistoryStates);
   3010                 mChangedStates2 |= mHistoryEnd.states^(cur.states2&mActiveHistoryStates2);
   3011                 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
   3012             }
   3013             return;
   3014         }
   3015 
   3016         mChangedStates = 0;
   3017         mChangedStates2 = 0;
   3018 
   3019         if (mNumHistoryItems == MAX_HISTORY_ITEMS
   3020                 || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
   3021             addHistoryRecordLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW);
   3022         }
   3023 
   3024         if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
   3025             // Once we've reached the maximum number of items, we only
   3026             // record changes to the battery level and the most interesting states.
   3027             // Once we've reached the maximum maximum number of items, we only
   3028             // record changes to the battery level.
   3029             if (mHistoryEnd != null && mHistoryEnd.batteryLevel
   3030                     == cur.batteryLevel &&
   3031                     (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
   3032                             || ((mHistoryEnd.states^(cur.states&mActiveHistoryStates))
   3033                                     & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
   3034                 return;
   3035             }
   3036         }
   3037 
   3038         addHistoryRecordLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE);
   3039     }
   3040 
   3041     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
   3042             String name, int uid) {
   3043         mHistoryCur.eventCode = code;
   3044         mHistoryCur.eventTag = mHistoryCur.localEventTag;
   3045         mHistoryCur.eventTag.string = name;
   3046         mHistoryCur.eventTag.uid = uid;
   3047         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
   3048     }
   3049 
   3050     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
   3051         HistoryItem rec = mHistoryCache;
   3052         if (rec != null) {
   3053             mHistoryCache = rec.next;
   3054         } else {
   3055             rec = new HistoryItem();
   3056         }
   3057         rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
   3058 
   3059         addHistoryRecordLocked(rec);
   3060     }
   3061 
   3062     void addHistoryRecordLocked(HistoryItem rec) {
   3063         mNumHistoryItems++;
   3064         rec.next = null;
   3065         mHistoryLastEnd = mHistoryEnd;
   3066         if (mHistoryEnd != null) {
   3067             mHistoryEnd.next = rec;
   3068             mHistoryEnd = rec;
   3069         } else {
   3070             mHistory = mHistoryEnd = rec;
   3071         }
   3072     }
   3073 
   3074     void clearHistoryLocked() {
   3075         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
   3076         if (USE_OLD_HISTORY) {
   3077             if (mHistory != null) {
   3078                 mHistoryEnd.next = mHistoryCache;
   3079                 mHistoryCache = mHistory;
   3080                 mHistory = mHistoryLastEnd = mHistoryEnd = null;
   3081             }
   3082             mNumHistoryItems = 0;
   3083         }
   3084 
   3085         mHistoryBaseTime = 0;
   3086         mLastHistoryElapsedRealtime = 0;
   3087         mTrackRunningHistoryElapsedRealtime = 0;
   3088         mTrackRunningHistoryUptime = 0;
   3089 
   3090         mHistoryBuffer.setDataSize(0);
   3091         mHistoryBuffer.setDataPosition(0);
   3092         mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER / 2);
   3093         mHistoryLastLastWritten.clear();
   3094         mHistoryLastWritten.clear();
   3095         mHistoryTagPool.clear();
   3096         mNextHistoryTagIdx = 0;
   3097         mNumHistoryTagChars = 0;
   3098         mHistoryBufferLastPos = -1;
   3099         mHistoryOverflow = false;
   3100         mActiveHistoryStates = 0xffffffff;
   3101         mActiveHistoryStates2 = 0xffffffff;
   3102     }
   3103 
   3104     public void updateTimeBasesLocked(boolean unplugged, boolean screenOff, long uptime,
   3105             long realtime) {
   3106         mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
   3107 
   3108         boolean unpluggedScreenOff = unplugged && screenOff;
   3109         if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) {
   3110             updateKernelWakelocksLocked();
   3111             if (DEBUG_ENERGY_CPU) {
   3112                 Slog.d(TAG, "Updating cpu time because screen is now " +
   3113                         (unpluggedScreenOff ? "off" : "on"));
   3114             }
   3115             updateCpuTimeLocked();
   3116             mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime);
   3117         }
   3118     }
   3119 
   3120     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
   3121         mIsolatedUids.put(isolatedUid, appUid);
   3122     }
   3123 
   3124     /**
   3125      * Schedules a read of the latest cpu times before removing the isolated UID.
   3126      * @see #removeIsolatedUidLocked(int)
   3127      */
   3128     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
   3129         int curUid = mIsolatedUids.get(isolatedUid, -1);
   3130         if (curUid == appUid) {
   3131             if (mExternalSync != null) {
   3132                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
   3133             }
   3134         }
   3135     }
   3136 
   3137     /**
   3138      * This should only be called after the cpu times have been read.
   3139      * @see #scheduleRemoveIsolatedUidLocked(int, int)
   3140      */
   3141     public void removeIsolatedUidLocked(int isolatedUid) {
   3142         mIsolatedUids.delete(isolatedUid);
   3143         mKernelUidCpuTimeReader.removeUid(isolatedUid);
   3144     }
   3145 
   3146     public int mapUid(int uid) {
   3147         int isolated = mIsolatedUids.get(uid, -1);
   3148         return isolated > 0 ? isolated : uid;
   3149     }
   3150 
   3151     public void noteEventLocked(int code, String name, int uid) {
   3152         uid = mapUid(uid);
   3153         if (!mActiveEvents.updateState(code, name, uid, 0)) {
   3154             return;
   3155         }
   3156         final long elapsedRealtime = mClocks.elapsedRealtime();
   3157         final long uptime = mClocks.uptimeMillis();
   3158         addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
   3159     }
   3160 
   3161     boolean ensureStartClockTime(final long currentTime) {
   3162         final long ABOUT_ONE_YEAR = 365*24*60*60*1000L;
   3163         if (currentTime > ABOUT_ONE_YEAR && mStartClockTime < (currentTime-ABOUT_ONE_YEAR)) {
   3164             // If the start clock time has changed by more than a year, then presumably
   3165             // the previous time was completely bogus.  So we are going to figure out a
   3166             // new time based on how much time has elapsed since we started counting.
   3167             mStartClockTime = currentTime - (mClocks.elapsedRealtime()-(mRealtimeStart/1000));
   3168             return true;
   3169         }
   3170         return false;
   3171     }
   3172 
   3173     public void noteCurrentTimeChangedLocked() {
   3174         final long currentTime = System.currentTimeMillis();
   3175         final long elapsedRealtime = mClocks.elapsedRealtime();
   3176         final long uptime = mClocks.uptimeMillis();
   3177         recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
   3178         ensureStartClockTime(currentTime);
   3179     }
   3180 
   3181     public void noteProcessStartLocked(String name, int uid) {
   3182         uid = mapUid(uid);
   3183         if (isOnBattery()) {
   3184             Uid u = getUidStatsLocked(uid);
   3185             u.getProcessStatsLocked(name).incStartsLocked();
   3186         }
   3187         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
   3188             return;
   3189         }
   3190         if (!mRecordAllHistory) {
   3191             return;
   3192         }
   3193         final long elapsedRealtime = mClocks.elapsedRealtime();
   3194         final long uptime = mClocks.uptimeMillis();
   3195         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
   3196     }
   3197 
   3198     public void noteProcessCrashLocked(String name, int uid) {
   3199         uid = mapUid(uid);
   3200         if (isOnBattery()) {
   3201             Uid u = getUidStatsLocked(uid);
   3202             u.getProcessStatsLocked(name).incNumCrashesLocked();
   3203         }
   3204     }
   3205 
   3206     public void noteProcessAnrLocked(String name, int uid) {
   3207         uid = mapUid(uid);
   3208         if (isOnBattery()) {
   3209             Uid u = getUidStatsLocked(uid);
   3210             u.getProcessStatsLocked(name).incNumAnrsLocked();
   3211         }
   3212     }
   3213 
   3214     public void noteUidProcessStateLocked(int uid, int state) {
   3215         uid = mapUid(uid);
   3216         getUidStatsLocked(uid).updateUidProcessStateLocked(state);
   3217     }
   3218 
   3219     public void noteProcessFinishLocked(String name, int uid) {
   3220         uid = mapUid(uid);
   3221         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
   3222             return;
   3223         }
   3224         if (!mRecordAllHistory) {
   3225             return;
   3226         }
   3227         final long elapsedRealtime = mClocks.elapsedRealtime();
   3228         final long uptime = mClocks.uptimeMillis();
   3229         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
   3230     }
   3231 
   3232     public void noteSyncStartLocked(String name, int uid) {
   3233         uid = mapUid(uid);
   3234         final long elapsedRealtime = mClocks.elapsedRealtime();
   3235         final long uptime = mClocks.uptimeMillis();
   3236         getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
   3237         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
   3238             return;
   3239         }
   3240         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
   3241     }
   3242 
   3243     public void noteSyncFinishLocked(String name, int uid) {
   3244         uid = mapUid(uid);
   3245         final long elapsedRealtime = mClocks.elapsedRealtime();
   3246         final long uptime = mClocks.uptimeMillis();
   3247         getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
   3248         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
   3249             return;
   3250         }
   3251         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
   3252     }
   3253 
   3254     public void noteJobStartLocked(String name, int uid) {
   3255         uid = mapUid(uid);
   3256         final long elapsedRealtime = mClocks.elapsedRealtime();
   3257         final long uptime = mClocks.uptimeMillis();
   3258         getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
   3259         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
   3260             return;
   3261         }
   3262         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
   3263     }
   3264 
   3265     public void noteJobFinishLocked(String name, int uid) {
   3266         uid = mapUid(uid);
   3267         final long elapsedRealtime = mClocks.elapsedRealtime();
   3268         final long uptime = mClocks.uptimeMillis();
   3269         getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime);
   3270         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
   3271             return;
   3272         }
   3273         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
   3274     }
   3275 
   3276     public void noteAlarmStartLocked(String name, int uid) {
   3277         if (!mRecordAllHistory) {
   3278             return;
   3279         }
   3280         uid = mapUid(uid);
   3281         final long elapsedRealtime = mClocks.elapsedRealtime();
   3282         final long uptime = mClocks.uptimeMillis();
   3283         if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_START, name, uid, 0)) {
   3284             return;
   3285         }
   3286         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_START, name, uid);
   3287     }
   3288 
   3289     public void noteAlarmFinishLocked(String name, int uid) {
   3290         if (!mRecordAllHistory) {
   3291             return;
   3292         }
   3293         uid = mapUid(uid);
   3294         final long elapsedRealtime = mClocks.elapsedRealtime();
   3295         final long uptime = mClocks.uptimeMillis();
   3296         if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_FINISH, name, uid, 0)) {
   3297             return;
   3298         }
   3299         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_FINISH, name, uid);
   3300     }
   3301 
   3302     private void requestWakelockCpuUpdate() {
   3303         if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
   3304             Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
   3305             mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
   3306         }
   3307     }
   3308 
   3309     private void requestImmediateCpuUpdate() {
   3310         mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
   3311         mHandler.sendEmptyMessage(MSG_UPDATE_WAKELOCKS);
   3312     }
   3313 
   3314     public void setRecordAllHistoryLocked(boolean enabled) {
   3315         mRecordAllHistory = enabled;
   3316         if (!enabled) {
   3317             // Clear out any existing state.
   3318             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
   3319             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
   3320             // Record the currently running processes as stopping, now that we are no
   3321             // longer tracking them.
   3322             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
   3323                     HistoryItem.EVENT_PROC);
   3324             if (active != null) {
   3325                 long mSecRealtime = mClocks.elapsedRealtime();
   3326                 final long mSecUptime = mClocks.uptimeMillis();
   3327                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
   3328                     SparseIntArray uids = ent.getValue();
   3329                     for (int j=0; j<uids.size(); j++) {
   3330                         addHistoryEventLocked(mSecRealtime, mSecUptime,
   3331                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
   3332                     }
   3333                 }
   3334             }
   3335         } else {
   3336             // Record the currently running processes as starting, now that we are tracking them.
   3337             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
   3338                     HistoryItem.EVENT_PROC);
   3339             if (active != null) {
   3340                 long mSecRealtime = mClocks.elapsedRealtime();
   3341                 final long mSecUptime = mClocks.uptimeMillis();
   3342                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
   3343                     SparseIntArray uids = ent.getValue();
   3344                     for (int j=0; j<uids.size(); j++) {
   3345                         addHistoryEventLocked(mSecRealtime, mSecUptime,
   3346                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
   3347                     }
   3348                 }
   3349             }
   3350         }
   3351     }
   3352 
   3353     public void setNoAutoReset(boolean enabled) {
   3354         mNoAutoReset = enabled;
   3355     }
   3356 
   3357     private String mInitialAcquireWakeName;
   3358     private int mInitialAcquireWakeUid = -1;
   3359 
   3360     public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type,
   3361             boolean unimportantForLogging, long elapsedRealtime, long uptime) {
   3362         uid = mapUid(uid);
   3363         if (type == WAKE_TYPE_PARTIAL) {
   3364             // Only care about partial wake locks, since full wake locks
   3365             // will be canceled when the user puts the screen to sleep.
   3366             aggregateLastWakeupUptimeLocked(uptime);
   3367             if (historyName == null) {
   3368                 historyName = name;
   3369             }
   3370             if (mRecordAllHistory) {
   3371                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
   3372                         uid, 0)) {
   3373                     addHistoryEventLocked(elapsedRealtime, uptime,
   3374                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
   3375                 }
   3376             }
   3377             if (mWakeLockNesting == 0) {
   3378                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
   3379                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
   3380                         + Integer.toHexString(mHistoryCur.states));
   3381                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
   3382                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
   3383                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
   3384                 mWakeLockImportant = !unimportantForLogging;
   3385                 addHistoryRecordLocked(elapsedRealtime, uptime);
   3386             } else if (!mWakeLockImportant && !unimportantForLogging
   3387                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
   3388                 if (mHistoryLastWritten.wakelockTag != null) {
   3389                     // We'll try to update the last tag.
   3390                     mHistoryLastWritten.wakelockTag = null;
   3391                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
   3392                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
   3393                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
   3394                     addHistoryRecordLocked(elapsedRealtime, uptime);
   3395                 }
   3396                 mWakeLockImportant = true;
   3397             }
   3398             mWakeLockNesting++;
   3399         }
   3400         if (uid >= 0) {
   3401             if (mOnBatteryScreenOffTimeBase.isRunning()) {
   3402                 // We only update the cpu time when a wake lock is acquired if the screen is off.
   3403                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
   3404                 if (DEBUG_ENERGY_CPU) {
   3405                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
   3406                 }
   3407                 requestWakelockCpuUpdate();
   3408             }
   3409             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
   3410         }
   3411     }
   3412 
   3413     public void noteStopWakeLocked(int uid, int pid, String name, String historyName, int type,
   3414             long elapsedRealtime, long uptime) {
   3415         uid = mapUid(uid);
   3416         if (type == WAKE_TYPE_PARTIAL) {
   3417             mWakeLockNesting--;
   3418             if (mRecordAllHistory) {
   3419                 if (historyName == null) {
   3420                     historyName = name;
   3421                 }
   3422                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
   3423                         uid, 0)) {
   3424                     addHistoryEventLocked(elapsedRealtime, uptime,
   3425                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
   3426                 }
   3427             }
   3428             if (mWakeLockNesting == 0) {
   3429                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
   3430                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
   3431                         + Integer.toHexString(mHistoryCur.states));
   3432                 mInitialAcquireWakeName = null;
   3433                 mInitialAcquireWakeUid = -1;
   3434                 addHistoryRecordLocked(elapsedRealtime, uptime);
   3435             }
   3436         }
   3437         if (uid >= 0) {
   3438             if (mOnBatteryScreenOffTimeBase.isRunning()) {
   3439                 if (DEBUG_ENERGY_CPU) {
   3440                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
   3441                 }
   3442                 requestWakelockCpuUpdate();
   3443             }
   3444             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
   3445         }
   3446     }
   3447 
   3448     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
   3449             String historyName, int type, boolean unimportantForLogging) {
   3450         final long elapsedRealtime = mClocks.elapsedRealtime();
   3451         final long uptime = mClocks.uptimeMillis();
   3452         final int N = ws.size();
   3453         for (int i=0; i<N; i++) {
   3454             noteStartWakeLocked(ws.get(i), pid, name, historyName, type, unimportantForLogging,
   3455                     elapsedRealtime, uptime);
   3456         }
   3457     }
   3458 
   3459     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
   3460             String historyName, int type, WorkSource newWs, int newPid, String newName,
   3461             String newHistoryName, int newType, boolean newUnimportantForLogging) {
   3462         final long elapsedRealtime = mClocks.elapsedRealtime();
   3463         final long uptime = mClocks.uptimeMillis();
   3464         // For correct semantics, we start the need worksources first, so that we won't
   3465         // make inappropriate history items as if all wake locks went away and new ones
   3466         // appeared.  This is okay because tracking of wake locks allows nesting.
   3467         final int NN = newWs.size();
   3468         for (int i=0; i<NN; i++) {
   3469             noteStartWakeLocked(newWs.get(i), newPid, newName, newHistoryName, newType,
   3470                     newUnimportantForLogging, elapsedRealtime, uptime);
   3471         }
   3472         final int NO = ws.size();
   3473         for (int i=0; i<NO; i++) {
   3474             noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
   3475         }
   3476     }
   3477 
   3478     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
   3479             String historyName, int type) {
   3480         final long elapsedRealtime = mClocks.elapsedRealtime();
   3481         final long uptime = mClocks.uptimeMillis();
   3482         final int N = ws.size();
   3483         for (int i=0; i<N; i++) {
   3484             noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
   3485         }
   3486     }
   3487 
   3488     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
   3489         uid = mapUid(uid);
   3490         final long elapsedRealtime = mClocks.elapsedRealtime();
   3491         final long uptime = mClocks.uptimeMillis();
   3492         if (historyName == null) {
   3493             historyName = name;
   3494         }
   3495         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
   3496                 0)) {
   3497             return;
   3498         }
   3499         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
   3500                 historyName, uid);
   3501     }
   3502 
   3503     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
   3504         uid = mapUid(uid);
   3505         final long elapsedRealtime = mClocks.elapsedRealtime();
   3506         final long uptime = mClocks.uptimeMillis();
   3507         if (historyName == null) {
   3508             historyName = name;
   3509         }
   3510         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
   3511                 0)) {
   3512             return;
   3513         }
   3514         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
   3515                 historyName, uid);
   3516     }
   3517 
   3518     void aggregateLastWakeupUptimeLocked(long uptimeMs) {
   3519         if (mLastWakeupReason != null) {
   3520             long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
   3521             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
   3522             timer.add(deltaUptime * 1000, 1); // time in in microseconds
   3523             mLastWakeupReason = null;
   3524         }
   3525     }
   3526 
   3527     public void noteWakeupReasonLocked(String reason) {
   3528         final long elapsedRealtime = mClocks.elapsedRealtime();
   3529         final long uptime = mClocks.uptimeMillis();
   3530         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
   3531                 + Integer.toHexString(mHistoryCur.states));
   3532         aggregateLastWakeupUptimeLocked(uptime);
   3533         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
   3534         mHistoryCur.wakeReasonTag.string = reason;
   3535         mHistoryCur.wakeReasonTag.uid = 0;
   3536         mLastWakeupReason = reason;
   3537         mLastWakeupUptimeMs = uptime;
   3538         addHistoryRecordLocked(elapsedRealtime, uptime);
   3539     }
   3540 
   3541     public boolean startAddingCpuLocked() {
   3542         mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
   3543         return mOnBatteryInternal;
   3544     }
   3545 
   3546     public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
   3547                                       int statSystemTime, int statIOWaitTime, int statIrqTime,
   3548                                       int statSoftIrqTime, int statIdleTime) {
   3549         if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
   3550                 + " user=" + statUserTime + " sys=" + statSystemTime
   3551                 + " io=" + statIOWaitTime + " irq=" + statIrqTime
   3552                 + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
   3553         mCurStepCpuUserTime += totalUTime;
   3554         mCurStepCpuSystemTime += totalSTime;
   3555         mCurStepStatUserTime += statUserTime;
   3556         mCurStepStatSystemTime += statSystemTime;
   3557         mCurStepStatIOWaitTime += statIOWaitTime;
   3558         mCurStepStatIrqTime += statIrqTime;
   3559         mCurStepStatSoftIrqTime += statSoftIrqTime;
   3560         mCurStepStatIdleTime += statIdleTime;
   3561     }
   3562 
   3563     public void noteProcessDiedLocked(int uid, int pid) {
   3564         uid = mapUid(uid);
   3565         Uid u = mUidStats.get(uid);
   3566         if (u != null) {
   3567             u.mPids.remove(pid);
   3568         }
   3569     }
   3570 
   3571     public long getProcessWakeTime(int uid, int pid, long realtime) {
   3572         uid = mapUid(uid);
   3573         Uid u = mUidStats.get(uid);
   3574         if (u != null) {
   3575             Uid.Pid p = u.mPids.get(pid);
   3576             if (p != null) {
   3577                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
   3578             }
   3579         }
   3580         return 0;
   3581     }
   3582 
   3583     public void reportExcessiveWakeLocked(int uid, String proc, long overTime, long usedTime) {
   3584         uid = mapUid(uid);
   3585         Uid u = mUidStats.get(uid);
   3586         if (u != null) {
   3587             u.reportExcessiveWakeLocked(proc, overTime, usedTime);
   3588         }
   3589     }
   3590 
   3591     public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
   3592         uid = mapUid(uid);
   3593         Uid u = mUidStats.get(uid);
   3594         if (u != null) {
   3595             u.reportExcessiveCpuLocked(proc, overTime, usedTime);
   3596         }
   3597     }
   3598 
   3599     int mSensorNesting;
   3600 
   3601     public void noteStartSensorLocked(int uid, int sensor) {
   3602         uid = mapUid(uid);
   3603         final long elapsedRealtime = mClocks.elapsedRealtime();
   3604         final long uptime = mClocks.uptimeMillis();
   3605         if (mSensorNesting == 0) {
   3606             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
   3607             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
   3608                     + Integer.toHexString(mHistoryCur.states));
   3609             addHistoryRecordLocked(elapsedRealtime, uptime);
   3610         }
   3611         mSensorNesting++;
   3612         getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
   3613     }
   3614 
   3615     public void noteStopSensorLocked(int uid, int sensor) {
   3616         uid = mapUid(uid);
   3617         final long elapsedRealtime = mClocks.elapsedRealtime();
   3618         final long uptime = mClocks.uptimeMillis();
   3619         mSensorNesting--;
   3620         if (mSensorNesting == 0) {
   3621             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
   3622             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
   3623                     + Integer.toHexString(mHistoryCur.states));
   3624             addHistoryRecordLocked(elapsedRealtime, uptime);
   3625         }
   3626         getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
   3627     }
   3628 
   3629     int mGpsNesting;
   3630 
   3631     public void noteStartGpsLocked(int uid) {
   3632         uid = mapUid(uid);
   3633         final long elapsedRealtime = mClocks.elapsedRealtime();
   3634         final long uptime = mClocks.uptimeMillis();
   3635         if (mGpsNesting == 0) {
   3636             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
   3637             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
   3638                     + Integer.toHexString(mHistoryCur.states));
   3639             addHistoryRecordLocked(elapsedRealtime, uptime);
   3640         }
   3641         mGpsNesting++;
   3642         getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
   3643     }
   3644 
   3645     public void noteStopGpsLocked(int uid) {
   3646         uid = mapUid(uid);
   3647         final long elapsedRealtime = mClocks.elapsedRealtime();
   3648         final long uptime = mClocks.uptimeMillis();
   3649         mGpsNesting--;
   3650         if (mGpsNesting == 0) {
   3651             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
   3652             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
   3653                     + Integer.toHexString(mHistoryCur.states));
   3654             addHistoryRecordLocked(elapsedRealtime, uptime);
   3655         }
   3656         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
   3657     }
   3658 
   3659     public void noteScreenStateLocked(int state) {
   3660         if (mScreenState != state) {
   3661             recordDailyStatsIfNeededLocked(true);
   3662             final int oldState = mScreenState;
   3663             mScreenState = state;
   3664             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
   3665                     + ", newState=" + Display.stateToString(state));
   3666 
   3667             if (state != Display.STATE_UNKNOWN) {
   3668                 int stepState = state-1;
   3669                 if (stepState < 4) {
   3670                     mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
   3671                     mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
   3672                 } else {
   3673                     Slog.wtf(TAG, "Unexpected screen state: " + state);
   3674                 }
   3675             }
   3676 
   3677             if (state == Display.STATE_ON) {
   3678                 // Screen turning on.
   3679                 final long elapsedRealtime = mClocks.elapsedRealtime();
   3680                 final long uptime = mClocks.uptimeMillis();
   3681                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
   3682                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
   3683                         + Integer.toHexString(mHistoryCur.states));
   3684                 addHistoryRecordLocked(elapsedRealtime, uptime);
   3685                 mScreenOnTimer.startRunningLocked(elapsedRealtime);
   3686                 if (mScreenBrightnessBin >= 0) {
   3687                     mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
   3688                 }
   3689 
   3690                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
   3691                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
   3692 
   3693                 // Fake a wake lock, so we consider the device waked as long
   3694                 // as the screen is on.
   3695                 noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
   3696                         elapsedRealtime, uptime);
   3697 
   3698                 // Update discharge amounts.
   3699                 if (mOnBatteryInternal) {
   3700                     updateDischargeScreenLevelsLocked(false, true);
   3701                 }
   3702             } else if (oldState == Display.STATE_ON) {
   3703                 // Screen turning off or dozing.
   3704                 final long elapsedRealtime = mClocks.elapsedRealtime();
   3705                 final long uptime = mClocks.uptimeMillis();
   3706                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
   3707                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
   3708                         + Integer.toHexString(mHistoryCur.states));
   3709                 addHistoryRecordLocked(elapsedRealtime, uptime);
   3710                 mScreenOnTimer.stopRunningLocked(elapsedRealtime);
   3711                 if (mScreenBrightnessBin >= 0) {
   3712                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
   3713                 }
   3714 
   3715                 noteStopWakeLocked(-1, -1, "screen", "screen", WAKE_TYPE_PARTIAL,
   3716                         elapsedRealtime, uptime);
   3717 
   3718                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
   3719                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
   3720 
   3721                 // Update discharge amounts.
   3722                 if (mOnBatteryInternal) {
   3723                     updateDischargeScreenLevelsLocked(true, false);
   3724                 }
   3725             }
   3726         }
   3727     }
   3728 
   3729     public void noteScreenBrightnessLocked(int brightness) {
   3730         // Bin the brightness.
   3731         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
   3732         if (bin < 0) bin = 0;
   3733         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
   3734         if (mScreenBrightnessBin != bin) {
   3735             final long elapsedRealtime = mClocks.elapsedRealtime();
   3736             final long uptime = mClocks.uptimeMillis();
   3737             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
   3738                     | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
   3739             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
   3740                     + Integer.toHexString(mHistoryCur.states));
   3741             addHistoryRecordLocked(elapsedRealtime, uptime);
   3742             if (mScreenState == Display.STATE_ON) {
   3743                 if (mScreenBrightnessBin >= 0) {
   3744                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
   3745                 }
   3746                 mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
   3747             }
   3748             mScreenBrightnessBin = bin;
   3749         }
   3750     }
   3751 
   3752     public void noteUserActivityLocked(int uid, int event) {
   3753         if (mOnBatteryInternal) {
   3754             uid = mapUid(uid);
   3755             getUidStatsLocked(uid).noteUserActivityLocked(event);
   3756         }
   3757     }
   3758 
   3759     public void noteWakeUpLocked(String reason, int reasonUid) {
   3760         final long elapsedRealtime = mClocks.elapsedRealtime();
   3761         final long uptime = mClocks.uptimeMillis();
   3762         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
   3763                 reason, reasonUid);
   3764     }
   3765 
   3766     public void noteInteractiveLocked(boolean interactive) {
   3767         if (mInteractive != interactive) {
   3768             final long elapsedRealtime = mClocks.elapsedRealtime();
   3769             mInteractive = interactive;
   3770             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
   3771             if (interactive) {
   3772                 mInteractiveTimer.startRunningLocked(elapsedRealtime);
   3773             } else {
   3774                 mInteractiveTimer.stopRunningLocked(elapsedRealtime);
   3775             }
   3776         }
   3777     }
   3778 
   3779     public void noteConnectivityChangedLocked(int type, String extra) {
   3780         final long elapsedRealtime = mClocks.elapsedRealtime();
   3781         final long uptime = mClocks.uptimeMillis();
   3782         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
   3783                 extra, type);
   3784         mNumConnectivityChange++;
   3785     }
   3786 
   3787     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
   3788             final long uptimeMillis, int uid) {
   3789         uid = mapUid(uid);
   3790         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
   3791                 uid);
   3792         getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
   3793     }
   3794 
   3795     public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) {
   3796         final long elapsedRealtime = mClocks.elapsedRealtime();
   3797         final long uptime = mClocks.uptimeMillis();
   3798         if (mMobileRadioPowerState != powerState) {
   3799             long realElapsedRealtimeMs;
   3800             final boolean active =
   3801                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
   3802                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
   3803             if (active) {
   3804                 if (uid > 0) {
   3805                     noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid);
   3806                 }
   3807 
   3808                 mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
   3809                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
   3810             } else {
   3811                 realElapsedRealtimeMs = timestampNs / (1000*1000);
   3812                 long lastUpdateTimeMs = mMobileRadioActiveStartTime;
   3813                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
   3814                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
   3815                             + " is before start time " + lastUpdateTimeMs);
   3816                     realElapsedRealtimeMs = elapsedRealtime;
   3817                 } else if (realElapsedRealtimeMs < elapsedRealtime) {
   3818                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
   3819                             - realElapsedRealtimeMs);
   3820                 }
   3821                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
   3822             }
   3823             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
   3824                     + Integer.toHexString(mHistoryCur.states));
   3825             addHistoryRecordLocked(elapsedRealtime, uptime);
   3826             mMobileRadioPowerState = powerState;
   3827             if (active) {
   3828                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
   3829                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
   3830             } else {
   3831                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
   3832                 updateMobileRadioStateLocked(realElapsedRealtimeMs, null);
   3833                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
   3834             }
   3835         }
   3836     }
   3837 
   3838     public void notePowerSaveMode(boolean enabled) {
   3839         if (mPowerSaveModeEnabled != enabled) {
   3840             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
   3841             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
   3842             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
   3843             final long elapsedRealtime = mClocks.elapsedRealtime();
   3844             final long uptime = mClocks.uptimeMillis();
   3845             mPowerSaveModeEnabled = enabled;
   3846             if (enabled) {
   3847                 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
   3848                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
   3849                         + Integer.toHexString(mHistoryCur.states2));
   3850                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
   3851             } else {
   3852                 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
   3853                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
   3854                         + Integer.toHexString(mHistoryCur.states2));
   3855                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
   3856             }
   3857             addHistoryRecordLocked(elapsedRealtime, uptime);
   3858         }
   3859     }
   3860 
   3861     public void noteDeviceIdleModeLocked(int mode, String activeReason, int activeUid) {
   3862         final long elapsedRealtime = mClocks.elapsedRealtime();
   3863         final long uptime = mClocks.uptimeMillis();
   3864         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
   3865         if (mDeviceIdling && !nowIdling && activeReason == null) {
   3866             // We don't go out of general idling mode until explicitly taken out of
   3867             // device idle through going active or significant motion.
   3868             nowIdling = true;
   3869         }
   3870         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
   3871         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
   3872             // We don't go out of general light idling mode until explicitly taken out of
   3873             // device idle through going active or significant motion.
   3874             nowLightIdling = true;
   3875         }
   3876         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
   3877             addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
   3878                     activeReason, activeUid);
   3879         }
   3880         if (mDeviceIdling != nowIdling) {
   3881             mDeviceIdling = nowIdling;
   3882             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
   3883             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
   3884             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
   3885             if (nowIdling) {
   3886                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
   3887             } else {
   3888                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
   3889             }
   3890         }
   3891         if (mDeviceLightIdling != nowLightIdling) {
   3892             mDeviceLightIdling = nowLightIdling;
   3893             if (nowLightIdling) {
   3894                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
   3895             } else {
   3896                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
   3897             }
   3898         }
   3899         if (mDeviceIdleMode != mode) {
   3900             mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
   3901                     | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
   3902             if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
   3903                     + Integer.toHexString(mHistoryCur.states2));
   3904             addHistoryRecordLocked(elapsedRealtime, uptime);
   3905             long lastDuration = elapsedRealtime - mLastIdleTimeStart;
   3906             mLastIdleTimeStart = elapsedRealtime;
   3907             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
   3908                 if (lastDuration > mLongestLightIdleTime) {
   3909                     mLongestLightIdleTime = lastDuration;
   3910                 }
   3911                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
   3912             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
   3913                 if (lastDuration > mLongestFullIdleTime) {
   3914                     mLongestFullIdleTime = lastDuration;
   3915                 }
   3916                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
   3917             }
   3918             if (mode == DEVICE_IDLE_MODE_LIGHT) {
   3919                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
   3920             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
   3921                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
   3922             }
   3923             mDeviceIdleMode = mode;
   3924         }
   3925     }
   3926 
   3927     public void notePackageInstalledLocked(String pkgName, int versionCode) {
   3928         final long elapsedRealtime = mClocks.elapsedRealtime();
   3929         final long uptime = mClocks.uptimeMillis();
   3930         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
   3931                 pkgName, versionCode);
   3932         PackageChange pc = new PackageChange();
   3933         pc.mPackageName = pkgName;
   3934         pc.mUpdate = true;
   3935         pc.mVersionCode = versionCode;
   3936         addPackageChange(pc);
   3937     }
   3938 
   3939     public void notePackageUninstalledLocked(String pkgName) {
   3940         final long elapsedRealtime = mClocks.elapsedRealtime();
   3941         final long uptime = mClocks.uptimeMillis();
   3942         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
   3943                 pkgName, 0);
   3944         PackageChange pc = new PackageChange();
   3945         pc.mPackageName = pkgName;
   3946         pc.mUpdate = true;
   3947         addPackageChange(pc);
   3948     }
   3949 
   3950     private void addPackageChange(PackageChange pc) {
   3951         if (mDailyPackageChanges == null) {
   3952             mDailyPackageChanges = new ArrayList<>();
   3953         }
   3954         mDailyPackageChanges.add(pc);
   3955     }
   3956 
   3957     public void notePhoneOnLocked() {
   3958         if (!mPhoneOn) {
   3959             final long elapsedRealtime = mClocks.elapsedRealtime();
   3960             final long uptime = mClocks.uptimeMillis();
   3961             mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
   3962             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
   3963                     + Integer.toHexString(mHistoryCur.states));
   3964             addHistoryRecordLocked(elapsedRealtime, uptime);
   3965             mPhoneOn = true;
   3966             mPhoneOnTimer.startRunningLocked(elapsedRealtime);
   3967         }
   3968     }
   3969 
   3970     public void notePhoneOffLocked() {
   3971         if (mPhoneOn) {
   3972             final long elapsedRealtime = mClocks.elapsedRealtime();
   3973             final long uptime = mClocks.uptimeMillis();
   3974             mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
   3975             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
   3976                     + Integer.toHexString(mHistoryCur.states));
   3977             addHistoryRecordLocked(elapsedRealtime, uptime);
   3978             mPhoneOn = false;
   3979             mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
   3980         }
   3981     }
   3982 
   3983     void stopAllPhoneSignalStrengthTimersLocked(int except) {
   3984         final long elapsedRealtime = mClocks.elapsedRealtime();
   3985         for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   3986             if (i == except) {
   3987                 continue;
   3988             }
   3989             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
   3990                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
   3991             }
   3992         }
   3993     }
   3994 
   3995     private int fixPhoneServiceState(int state, int signalBin) {
   3996         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
   3997             // In this case we will always be STATE_OUT_OF_SERVICE, so need
   3998             // to infer that we are scanning from other data.
   3999             if (state == ServiceState.STATE_OUT_OF_SERVICE
   4000                     && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
   4001                 state = ServiceState.STATE_IN_SERVICE;
   4002             }
   4003         }
   4004 
   4005         return state;
   4006     }
   4007 
   4008     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
   4009         boolean scanning = false;
   4010         boolean newHistory = false;
   4011 
   4012         mPhoneServiceStateRaw = state;
   4013         mPhoneSimStateRaw = simState;
   4014         mPhoneSignalStrengthBinRaw = strengthBin;
   4015 
   4016         final long elapsedRealtime = mClocks.elapsedRealtime();
   4017         final long uptime = mClocks.uptimeMillis();
   4018 
   4019         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
   4020             // In this case we will always be STATE_OUT_OF_SERVICE, so need
   4021             // to infer that we are scanning from other data.
   4022             if (state == ServiceState.STATE_OUT_OF_SERVICE
   4023                     && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
   4024                 state = ServiceState.STATE_IN_SERVICE;
   4025             }
   4026         }
   4027 
   4028         // If the phone is powered off, stop all timers.
   4029         if (state == ServiceState.STATE_POWER_OFF) {
   4030             strengthBin = -1;
   4031 
   4032         // If we are in service, make sure the correct signal string timer is running.
   4033         } else if (state == ServiceState.STATE_IN_SERVICE) {
   4034             // Bin will be changed below.
   4035 
   4036         // If we're out of service, we are in the lowest signal strength
   4037         // bin and have the scanning bit set.
   4038         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
   4039             scanning = true;
   4040             strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
   4041             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
   4042                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
   4043                 newHistory = true;
   4044                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
   4045                         + Integer.toHexString(mHistoryCur.states));
   4046                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
   4047             }
   4048         }
   4049 
   4050         if (!scanning) {
   4051             // If we are no longer scanning, then stop the scanning timer.
   4052             if (mPhoneSignalScanningTimer.isRunningLocked()) {
   4053                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
   4054                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
   4055                         + Integer.toHexString(mHistoryCur.states));
   4056                 newHistory = true;
   4057                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
   4058             }
   4059         }
   4060 
   4061         if (mPhoneServiceState != state) {
   4062             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
   4063                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
   4064             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
   4065                     + Integer.toHexString(mHistoryCur.states));
   4066             newHistory = true;
   4067             mPhoneServiceState = state;
   4068         }
   4069 
   4070         if (mPhoneSignalStrengthBin != strengthBin) {
   4071             if (mPhoneSignalStrengthBin >= 0) {
   4072                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
   4073                         elapsedRealtime);
   4074             }
   4075             if (strengthBin >= 0) {
   4076                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
   4077                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
   4078                 }
   4079                 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
   4080                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
   4081                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
   4082                         + Integer.toHexString(mHistoryCur.states));
   4083                 newHistory = true;
   4084             } else {
   4085                 stopAllPhoneSignalStrengthTimersLocked(-1);
   4086             }
   4087             mPhoneSignalStrengthBin = strengthBin;
   4088         }
   4089 
   4090         if (newHistory) {
   4091             addHistoryRecordLocked(elapsedRealtime, uptime);
   4092         }
   4093     }
   4094 
   4095     /**
   4096      * Telephony stack updates the phone state.
   4097      * @param state phone state from ServiceState.getState()
   4098      */
   4099     public void notePhoneStateLocked(int state, int simState) {
   4100         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
   4101     }
   4102 
   4103     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
   4104         // Bin the strength.
   4105         int bin = signalStrength.getLevel();
   4106         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
   4107     }
   4108 
   4109     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
   4110         int bin = DATA_CONNECTION_NONE;
   4111         if (hasData) {
   4112             switch (dataType) {
   4113                 case TelephonyManager.NETWORK_TYPE_EDGE:
   4114                     bin = DATA_CONNECTION_EDGE;
   4115                     break;
   4116                 case TelephonyManager.NETWORK_TYPE_GPRS:
   4117                     bin = DATA_CONNECTION_GPRS;
   4118                     break;
   4119                 case TelephonyManager.NETWORK_TYPE_UMTS:
   4120                     bin = DATA_CONNECTION_UMTS;
   4121                     break;
   4122                 case TelephonyManager.NETWORK_TYPE_CDMA:
   4123                     bin = DATA_CONNECTION_CDMA;
   4124                     break;
   4125                 case TelephonyManager.NETWORK_TYPE_EVDO_0:
   4126                     bin = DATA_CONNECTION_EVDO_0;
   4127                     break;
   4128                 case TelephonyManager.NETWORK_TYPE_EVDO_A:
   4129                     bin = DATA_CONNECTION_EVDO_A;
   4130                     break;
   4131                 case TelephonyManager.NETWORK_TYPE_1xRTT:
   4132                     bin = DATA_CONNECTION_1xRTT;
   4133                     break;
   4134                 case TelephonyManager.NETWORK_TYPE_HSDPA:
   4135                     bin = DATA_CONNECTION_HSDPA;
   4136                     break;
   4137                 case TelephonyManager.NETWORK_TYPE_HSUPA:
   4138                     bin = DATA_CONNECTION_HSUPA;
   4139                     break;
   4140                 case TelephonyManager.NETWORK_TYPE_HSPA:
   4141                     bin = DATA_CONNECTION_HSPA;
   4142                     break;
   4143                 case TelephonyManager.NETWORK_TYPE_IDEN:
   4144                     bin = DATA_CONNECTION_IDEN;
   4145                     break;
   4146                 case TelephonyManager.NETWORK_TYPE_EVDO_B:
   4147                     bin = DATA_CONNECTION_EVDO_B;
   4148                     break;
   4149                 case TelephonyManager.NETWORK_TYPE_LTE:
   4150                     bin = DATA_CONNECTION_LTE;
   4151                     break;
   4152                 case TelephonyManager.NETWORK_TYPE_EHRPD:
   4153                     bin = DATA_CONNECTION_EHRPD;
   4154                     break;
   4155                 case TelephonyManager.NETWORK_TYPE_HSPAP:
   4156                     bin = DATA_CONNECTION_HSPAP;
   4157                     break;
   4158                 default:
   4159                     bin = DATA_CONNECTION_OTHER;
   4160                     break;
   4161             }
   4162         }
   4163         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
   4164         if (mPhoneDataConnectionType != bin) {
   4165             final long elapsedRealtime = mClocks.elapsedRealtime();
   4166             final long uptime = mClocks.uptimeMillis();
   4167             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
   4168                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
   4169             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
   4170                     + Integer.toHexString(mHistoryCur.states));
   4171             addHistoryRecordLocked(elapsedRealtime, uptime);
   4172             if (mPhoneDataConnectionType >= 0) {
   4173                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
   4174                         elapsedRealtime);
   4175             }
   4176             mPhoneDataConnectionType = bin;
   4177             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
   4178         }
   4179     }
   4180 
   4181     public void noteWifiOnLocked() {
   4182         if (!mWifiOn) {
   4183             final long elapsedRealtime = mClocks.elapsedRealtime();
   4184             final long uptime = mClocks.uptimeMillis();
   4185             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
   4186             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
   4187                     + Integer.toHexString(mHistoryCur.states));
   4188             addHistoryRecordLocked(elapsedRealtime, uptime);
   4189             mWifiOn = true;
   4190             mWifiOnTimer.startRunningLocked(elapsedRealtime);
   4191             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
   4192         }
   4193     }
   4194 
   4195     public void noteWifiOffLocked() {
   4196         final long elapsedRealtime = mClocks.elapsedRealtime();
   4197         final long uptime = mClocks.uptimeMillis();
   4198         if (mWifiOn) {
   4199             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
   4200             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
   4201                     + Integer.toHexString(mHistoryCur.states));
   4202             addHistoryRecordLocked(elapsedRealtime, uptime);
   4203             mWifiOn = false;
   4204             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
   4205             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
   4206         }
   4207     }
   4208 
   4209     public void noteAudioOnLocked(int uid) {
   4210         uid = mapUid(uid);
   4211         final long elapsedRealtime = mClocks.elapsedRealtime();
   4212         final long uptime = mClocks.uptimeMillis();
   4213         if (mAudioOnNesting == 0) {
   4214             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
   4215             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
   4216                     + Integer.toHexString(mHistoryCur.states));
   4217             addHistoryRecordLocked(elapsedRealtime, uptime);
   4218             mAudioOnTimer.startRunningLocked(elapsedRealtime);
   4219         }
   4220         mAudioOnNesting++;
   4221         getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
   4222     }
   4223 
   4224     public void noteAudioOffLocked(int uid) {
   4225         if (mAudioOnNesting == 0) {
   4226             return;
   4227         }
   4228         uid = mapUid(uid);
   4229         final long elapsedRealtime = mClocks.elapsedRealtime();
   4230         final long uptime = mClocks.uptimeMillis();
   4231         if (--mAudioOnNesting == 0) {
   4232             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
   4233             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
   4234                     + Integer.toHexString(mHistoryCur.states));
   4235             addHistoryRecordLocked(elapsedRealtime, uptime);
   4236             mAudioOnTimer.stopRunningLocked(elapsedRealtime);
   4237         }
   4238         getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
   4239     }
   4240 
   4241     public void noteVideoOnLocked(int uid) {
   4242         uid = mapUid(uid);
   4243         final long elapsedRealtime = mClocks.elapsedRealtime();
   4244         final long uptime = mClocks.uptimeMillis();
   4245         if (mVideoOnNesting == 0) {
   4246             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
   4247             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
   4248                     + Integer.toHexString(mHistoryCur.states));
   4249             addHistoryRecordLocked(elapsedRealtime, uptime);
   4250             mVideoOnTimer.startRunningLocked(elapsedRealtime);
   4251         }
   4252         mVideoOnNesting++;
   4253         getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
   4254     }
   4255 
   4256     public void noteVideoOffLocked(int uid) {
   4257         if (mVideoOnNesting == 0) {
   4258             return;
   4259         }
   4260         uid = mapUid(uid);
   4261         final long elapsedRealtime = mClocks.elapsedRealtime();
   4262         final long uptime = mClocks.uptimeMillis();
   4263         if (--mVideoOnNesting == 0) {
   4264             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
   4265             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
   4266                     + Integer.toHexString(mHistoryCur.states));
   4267             addHistoryRecordLocked(elapsedRealtime, uptime);
   4268             mVideoOnTimer.stopRunningLocked(elapsedRealtime);
   4269         }
   4270         getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
   4271     }
   4272 
   4273     public void noteResetAudioLocked() {
   4274         if (mAudioOnNesting > 0) {
   4275             final long elapsedRealtime = mClocks.elapsedRealtime();
   4276             final long uptime = mClocks.uptimeMillis();
   4277             mAudioOnNesting = 0;
   4278             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
   4279             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
   4280                     + Integer.toHexString(mHistoryCur.states));
   4281             addHistoryRecordLocked(elapsedRealtime, uptime);
   4282             mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
   4283             for (int i=0; i<mUidStats.size(); i++) {
   4284                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   4285                 uid.noteResetAudioLocked(elapsedRealtime);
   4286             }
   4287         }
   4288     }
   4289 
   4290     public void noteResetVideoLocked() {
   4291         if (mVideoOnNesting > 0) {
   4292             final long elapsedRealtime = mClocks.elapsedRealtime();
   4293             final long uptime = mClocks.uptimeMillis();
   4294             mAudioOnNesting = 0;
   4295             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
   4296             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
   4297                     + Integer.toHexString(mHistoryCur.states));
   4298             addHistoryRecordLocked(elapsedRealtime, uptime);
   4299             mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
   4300             for (int i=0; i<mUidStats.size(); i++) {
   4301                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   4302                 uid.noteResetVideoLocked(elapsedRealtime);
   4303             }
   4304         }
   4305     }
   4306 
   4307     public void noteActivityResumedLocked(int uid) {
   4308         uid = mapUid(uid);
   4309         getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
   4310     }
   4311 
   4312     public void noteActivityPausedLocked(int uid) {
   4313         uid = mapUid(uid);
   4314         getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
   4315     }
   4316 
   4317     public void noteVibratorOnLocked(int uid, long durationMillis) {
   4318         uid = mapUid(uid);
   4319         getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
   4320     }
   4321 
   4322     public void noteVibratorOffLocked(int uid) {
   4323         uid = mapUid(uid);
   4324         getUidStatsLocked(uid).noteVibratorOffLocked();
   4325     }
   4326 
   4327     public void noteFlashlightOnLocked(int uid) {
   4328         uid = mapUid(uid);
   4329         final long elapsedRealtime = mClocks.elapsedRealtime();
   4330         final long uptime = mClocks.uptimeMillis();
   4331         if (mFlashlightOnNesting++ == 0) {
   4332             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
   4333             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
   4334                     + Integer.toHexString(mHistoryCur.states2));
   4335             addHistoryRecordLocked(elapsedRealtime, uptime);
   4336             mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
   4337         }
   4338         getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
   4339     }
   4340 
   4341     public void noteFlashlightOffLocked(int uid) {
   4342         if (mFlashlightOnNesting == 0) {
   4343             return;
   4344         }
   4345         uid = mapUid(uid);
   4346         final long elapsedRealtime = mClocks.elapsedRealtime();
   4347         final long uptime = mClocks.uptimeMillis();
   4348         if (--mFlashlightOnNesting == 0) {
   4349             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
   4350             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
   4351                     + Integer.toHexString(mHistoryCur.states2));
   4352             addHistoryRecordLocked(elapsedRealtime, uptime);
   4353             mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
   4354         }
   4355         getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
   4356     }
   4357 
   4358     public void noteCameraOnLocked(int uid) {
   4359         uid = mapUid(uid);
   4360         final long elapsedRealtime = mClocks.elapsedRealtime();
   4361         final long uptime = mClocks.uptimeMillis();
   4362         if (mCameraOnNesting++ == 0) {
   4363             mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
   4364             if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
   4365                     + Integer.toHexString(mHistoryCur.states2));
   4366             addHistoryRecordLocked(elapsedRealtime, uptime);
   4367             mCameraOnTimer.startRunningLocked(elapsedRealtime);
   4368         }
   4369         getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
   4370     }
   4371 
   4372     public void noteCameraOffLocked(int uid) {
   4373         if (mCameraOnNesting == 0) {
   4374             return;
   4375         }
   4376         uid = mapUid(uid);
   4377         final long elapsedRealtime = mClocks.elapsedRealtime();
   4378         final long uptime = mClocks.uptimeMillis();
   4379         if (--mCameraOnNesting == 0) {
   4380             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
   4381             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
   4382                     + Integer.toHexString(mHistoryCur.states2));
   4383             addHistoryRecordLocked(elapsedRealtime, uptime);
   4384             mCameraOnTimer.stopRunningLocked(elapsedRealtime);
   4385         }
   4386         getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
   4387     }
   4388 
   4389     public void noteResetCameraLocked() {
   4390         if (mCameraOnNesting > 0) {
   4391             final long elapsedRealtime = mClocks.elapsedRealtime();
   4392             final long uptime = mClocks.uptimeMillis();
   4393             mCameraOnNesting = 0;
   4394             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
   4395             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
   4396                     + Integer.toHexString(mHistoryCur.states2));
   4397             addHistoryRecordLocked(elapsedRealtime, uptime);
   4398             mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
   4399             for (int i=0; i<mUidStats.size(); i++) {
   4400                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   4401                 uid.noteResetCameraLocked(elapsedRealtime);
   4402             }
   4403         }
   4404     }
   4405 
   4406     public void noteResetFlashlightLocked() {
   4407         if (mFlashlightOnNesting > 0) {
   4408             final long elapsedRealtime = mClocks.elapsedRealtime();
   4409             final long uptime = mClocks.uptimeMillis();
   4410             mFlashlightOnNesting = 0;
   4411             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
   4412             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
   4413                     + Integer.toHexString(mHistoryCur.states2));
   4414             addHistoryRecordLocked(elapsedRealtime, uptime);
   4415             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
   4416             for (int i=0; i<mUidStats.size(); i++) {
   4417                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   4418                 uid.noteResetFlashlightLocked(elapsedRealtime);
   4419             }
   4420         }
   4421     }
   4422 
   4423     private void noteBluetoothScanStartedLocked(int uid) {
   4424         uid = mapUid(uid);
   4425         final long elapsedRealtime = SystemClock.elapsedRealtime();
   4426         final long uptime = SystemClock.uptimeMillis();
   4427         if (mBluetoothScanNesting == 0) {
   4428             mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
   4429             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
   4430                     + Integer.toHexString(mHistoryCur.states2));
   4431             addHistoryRecordLocked(elapsedRealtime, uptime);
   4432             mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
   4433         }
   4434         mBluetoothScanNesting++;
   4435         getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime);
   4436     }
   4437 
   4438     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws) {
   4439         final int N = ws.size();
   4440         for (int i = 0; i < N; i++) {
   4441             noteBluetoothScanStartedLocked(ws.get(i));
   4442         }
   4443     }
   4444 
   4445     private void noteBluetoothScanStoppedLocked(int uid) {
   4446         uid = mapUid(uid);
   4447         final long elapsedRealtime = SystemClock.elapsedRealtime();
   4448         final long uptime = SystemClock.uptimeMillis();
   4449         mBluetoothScanNesting--;
   4450         if (mBluetoothScanNesting == 0) {
   4451             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
   4452             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
   4453                     + Integer.toHexString(mHistoryCur.states2));
   4454             addHistoryRecordLocked(elapsedRealtime, uptime);
   4455             mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
   4456         }
   4457         getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime);
   4458     }
   4459 
   4460     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws) {
   4461         final int N = ws.size();
   4462         for (int i = 0; i < N; i++) {
   4463             noteBluetoothScanStoppedLocked(ws.get(i));
   4464         }
   4465     }
   4466 
   4467     public void noteResetBluetoothScanLocked() {
   4468         if (mBluetoothScanNesting > 0) {
   4469             final long elapsedRealtime = SystemClock.elapsedRealtime();
   4470             final long uptime = SystemClock.uptimeMillis();
   4471             mBluetoothScanNesting = 0;
   4472             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
   4473             if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
   4474                     + Integer.toHexString(mHistoryCur.states2));
   4475             addHistoryRecordLocked(elapsedRealtime, uptime);
   4476             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
   4477             for (int i=0; i<mUidStats.size(); i++) {
   4478                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   4479                 uid.noteResetBluetoothScanLocked(elapsedRealtime);
   4480             }
   4481         }
   4482     }
   4483 
   4484     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
   4485             final long uptimeMillis, int uid) {
   4486         uid = mapUid(uid);
   4487         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
   4488                 uid);
   4489         getUidStatsLocked(uid).noteWifiRadioApWakeupLocked();
   4490     }
   4491 
   4492     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
   4493         final long elapsedRealtime = mClocks.elapsedRealtime();
   4494         final long uptime = mClocks.uptimeMillis();
   4495         if (mWifiRadioPowerState != powerState) {
   4496             final boolean active =
   4497                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
   4498                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
   4499             if (active) {
   4500                 if (uid > 0) {
   4501                     noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid);
   4502                 }
   4503                 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
   4504             } else {
   4505                 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
   4506             }
   4507             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
   4508                     + Integer.toHexString(mHistoryCur.states));
   4509             addHistoryRecordLocked(elapsedRealtime, uptime);
   4510             mWifiRadioPowerState = powerState;
   4511         }
   4512     }
   4513 
   4514     public void noteWifiRunningLocked(WorkSource ws) {
   4515         if (!mGlobalWifiRunning) {
   4516             final long elapsedRealtime = mClocks.elapsedRealtime();
   4517             final long uptime = mClocks.uptimeMillis();
   4518             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
   4519             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
   4520                     + Integer.toHexString(mHistoryCur.states));
   4521             addHistoryRecordLocked(elapsedRealtime, uptime);
   4522             mGlobalWifiRunning = true;
   4523             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
   4524             int N = ws.size();
   4525             for (int i=0; i<N; i++) {
   4526                 int uid = mapUid(ws.get(i));
   4527                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
   4528             }
   4529             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
   4530         } else {
   4531             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
   4532         }
   4533     }
   4534 
   4535     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
   4536         if (mGlobalWifiRunning) {
   4537             final long elapsedRealtime = mClocks.elapsedRealtime();
   4538             int N = oldWs.size();
   4539             for (int i=0; i<N; i++) {
   4540                 int uid = mapUid(oldWs.get(i));
   4541                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
   4542             }
   4543             N = newWs.size();
   4544             for (int i=0; i<N; i++) {
   4545                 int uid = mapUid(newWs.get(i));
   4546                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
   4547             }
   4548         } else {
   4549             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
   4550         }
   4551     }
   4552 
   4553     public void noteWifiStoppedLocked(WorkSource ws) {
   4554         if (mGlobalWifiRunning) {
   4555             final long elapsedRealtime = mClocks.elapsedRealtime();
   4556             final long uptime = mClocks.uptimeMillis();
   4557             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
   4558             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
   4559                     + Integer.toHexString(mHistoryCur.states));
   4560             addHistoryRecordLocked(elapsedRealtime, uptime);
   4561             mGlobalWifiRunning = false;
   4562             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
   4563             int N = ws.size();
   4564             for (int i=0; i<N; i++) {
   4565                 int uid = mapUid(ws.get(i));
   4566                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
   4567             }
   4568             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
   4569         } else {
   4570             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
   4571         }
   4572     }
   4573 
   4574     public void noteWifiStateLocked(int wifiState, String accessPoint) {
   4575         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
   4576         if (mWifiState != wifiState) {
   4577             final long elapsedRealtime = mClocks.elapsedRealtime();
   4578             if (mWifiState >= 0) {
   4579                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
   4580             }
   4581             mWifiState = wifiState;
   4582             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
   4583             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
   4584         }
   4585     }
   4586 
   4587     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
   4588         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
   4589         if (mWifiSupplState != supplState) {
   4590             final long elapsedRealtime = mClocks.elapsedRealtime();
   4591             final long uptime = mClocks.uptimeMillis();
   4592             if (mWifiSupplState >= 0) {
   4593                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
   4594             }
   4595             mWifiSupplState = supplState;
   4596             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
   4597             mHistoryCur.states2 =
   4598                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
   4599                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
   4600             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
   4601                     + Integer.toHexString(mHistoryCur.states2));
   4602             addHistoryRecordLocked(elapsedRealtime, uptime);
   4603         }
   4604     }
   4605 
   4606     void stopAllWifiSignalStrengthTimersLocked(int except) {
   4607         final long elapsedRealtime = mClocks.elapsedRealtime();
   4608         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   4609             if (i == except) {
   4610                 continue;
   4611             }
   4612             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
   4613                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
   4614             }
   4615         }
   4616     }
   4617 
   4618     public void noteWifiRssiChangedLocked(int newRssi) {
   4619         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
   4620         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
   4621         if (mWifiSignalStrengthBin != strengthBin) {
   4622             final long elapsedRealtime = mClocks.elapsedRealtime();
   4623             final long uptime = mClocks.uptimeMillis();
   4624             if (mWifiSignalStrengthBin >= 0) {
   4625                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
   4626                         elapsedRealtime);
   4627             }
   4628             if (strengthBin >= 0) {
   4629                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
   4630                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
   4631                 }
   4632                 mHistoryCur.states2 =
   4633                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
   4634                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
   4635                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
   4636                         + Integer.toHexString(mHistoryCur.states2));
   4637                 addHistoryRecordLocked(elapsedRealtime, uptime);
   4638             } else {
   4639                 stopAllWifiSignalStrengthTimersLocked(-1);
   4640             }
   4641             mWifiSignalStrengthBin = strengthBin;
   4642         }
   4643     }
   4644 
   4645     int mWifiFullLockNesting = 0;
   4646 
   4647     public void noteFullWifiLockAcquiredLocked(int uid) {
   4648         uid = mapUid(uid);
   4649         final long elapsedRealtime = mClocks.elapsedRealtime();
   4650         final long uptime = mClocks.uptimeMillis();
   4651         if (mWifiFullLockNesting == 0) {
   4652             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
   4653             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
   4654                     + Integer.toHexString(mHistoryCur.states));
   4655             addHistoryRecordLocked(elapsedRealtime, uptime);
   4656         }
   4657         mWifiFullLockNesting++;
   4658         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
   4659     }
   4660 
   4661     public void noteFullWifiLockReleasedLocked(int uid) {
   4662         uid = mapUid(uid);
   4663         final long elapsedRealtime = mClocks.elapsedRealtime();
   4664         final long uptime = mClocks.uptimeMillis();
   4665         mWifiFullLockNesting--;
   4666         if (mWifiFullLockNesting == 0) {
   4667             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
   4668             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
   4669                     + Integer.toHexString(mHistoryCur.states));
   4670             addHistoryRecordLocked(elapsedRealtime, uptime);
   4671         }
   4672         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
   4673     }
   4674 
   4675     int mWifiScanNesting = 0;
   4676 
   4677     public void noteWifiScanStartedLocked(int uid) {
   4678         uid = mapUid(uid);
   4679         final long elapsedRealtime = mClocks.elapsedRealtime();
   4680         final long uptime = mClocks.uptimeMillis();
   4681         if (mWifiScanNesting == 0) {
   4682             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
   4683             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
   4684                     + Integer.toHexString(mHistoryCur.states));
   4685             addHistoryRecordLocked(elapsedRealtime, uptime);
   4686         }
   4687         mWifiScanNesting++;
   4688         getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
   4689     }
   4690 
   4691     public void noteWifiScanStoppedLocked(int uid) {
   4692         uid = mapUid(uid);
   4693         final long elapsedRealtime = mClocks.elapsedRealtime();
   4694         final long uptime = mClocks.uptimeMillis();
   4695         mWifiScanNesting--;
   4696         if (mWifiScanNesting == 0) {
   4697             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
   4698             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
   4699                     + Integer.toHexString(mHistoryCur.states));
   4700             addHistoryRecordLocked(elapsedRealtime, uptime);
   4701         }
   4702         getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
   4703     }
   4704 
   4705     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
   4706         uid = mapUid(uid);
   4707         final long elapsedRealtime = mClocks.elapsedRealtime();
   4708         getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
   4709     }
   4710 
   4711     public void noteWifiBatchedScanStoppedLocked(int uid) {
   4712         uid = mapUid(uid);
   4713         final long elapsedRealtime = mClocks.elapsedRealtime();
   4714         getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
   4715     }
   4716 
   4717     int mWifiMulticastNesting = 0;
   4718 
   4719     public void noteWifiMulticastEnabledLocked(int uid) {
   4720         uid = mapUid(uid);
   4721         final long elapsedRealtime = mClocks.elapsedRealtime();
   4722         final long uptime = mClocks.uptimeMillis();
   4723         if (mWifiMulticastNesting == 0) {
   4724             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
   4725             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
   4726                     + Integer.toHexString(mHistoryCur.states));
   4727             addHistoryRecordLocked(elapsedRealtime, uptime);
   4728         }
   4729         mWifiMulticastNesting++;
   4730         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
   4731     }
   4732 
   4733     public void noteWifiMulticastDisabledLocked(int uid) {
   4734         uid = mapUid(uid);
   4735         final long elapsedRealtime = mClocks.elapsedRealtime();
   4736         final long uptime = mClocks.uptimeMillis();
   4737         mWifiMulticastNesting--;
   4738         if (mWifiMulticastNesting == 0) {
   4739             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
   4740             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
   4741                     + Integer.toHexString(mHistoryCur.states));
   4742             addHistoryRecordLocked(elapsedRealtime, uptime);
   4743         }
   4744         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
   4745     }
   4746 
   4747     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
   4748         int N = ws.size();
   4749         for (int i=0; i<N; i++) {
   4750             noteFullWifiLockAcquiredLocked(ws.get(i));
   4751         }
   4752     }
   4753 
   4754     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
   4755         int N = ws.size();
   4756         for (int i=0; i<N; i++) {
   4757             noteFullWifiLockReleasedLocked(ws.get(i));
   4758         }
   4759     }
   4760 
   4761     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
   4762         int N = ws.size();
   4763         for (int i=0; i<N; i++) {
   4764             noteWifiScanStartedLocked(ws.get(i));
   4765         }
   4766     }
   4767 
   4768     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
   4769         int N = ws.size();
   4770         for (int i=0; i<N; i++) {
   4771             noteWifiScanStoppedLocked(ws.get(i));
   4772         }
   4773     }
   4774 
   4775     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
   4776         int N = ws.size();
   4777         for (int i=0; i<N; i++) {
   4778             noteWifiBatchedScanStartedLocked(ws.get(i), csph);
   4779         }
   4780     }
   4781 
   4782     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
   4783         int N = ws.size();
   4784         for (int i=0; i<N; i++) {
   4785             noteWifiBatchedScanStoppedLocked(ws.get(i));
   4786         }
   4787     }
   4788 
   4789     public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) {
   4790         int N = ws.size();
   4791         for (int i=0; i<N; i++) {
   4792             noteWifiMulticastEnabledLocked(ws.get(i));
   4793         }
   4794     }
   4795 
   4796     public void noteWifiMulticastDisabledFromSourceLocked(WorkSource ws) {
   4797         int N = ws.size();
   4798         for (int i=0; i<N; i++) {
   4799             noteWifiMulticastDisabledLocked(ws.get(i));
   4800         }
   4801     }
   4802 
   4803     private static String[] includeInStringArray(String[] array, String str) {
   4804         if (ArrayUtils.indexOf(array, str) >= 0) {
   4805             return array;
   4806         }
   4807         String[] newArray = new String[array.length+1];
   4808         System.arraycopy(array, 0, newArray, 0, array.length);
   4809         newArray[array.length] = str;
   4810         return newArray;
   4811     }
   4812 
   4813     private static String[] excludeFromStringArray(String[] array, String str) {
   4814         int index = ArrayUtils.indexOf(array, str);
   4815         if (index >= 0) {
   4816             String[] newArray = new String[array.length-1];
   4817             if (index > 0) {
   4818                 System.arraycopy(array, 0, newArray, 0, index);
   4819             }
   4820             if (index < array.length-1) {
   4821                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
   4822             }
   4823             return newArray;
   4824         }
   4825         return array;
   4826     }
   4827 
   4828     public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
   4829         if (TextUtils.isEmpty(iface)) return;
   4830         if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
   4831             mMobileIfaces = includeInStringArray(mMobileIfaces, iface);
   4832             if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces);
   4833         } else {
   4834             mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface);
   4835             if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces);
   4836         }
   4837         if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
   4838             mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
   4839             if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
   4840         } else {
   4841             mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
   4842             if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
   4843         }
   4844     }
   4845 
   4846     public void noteNetworkStatsEnabledLocked() {
   4847         // During device boot, qtaguid isn't enabled until after the inital
   4848         // loading of battery stats. Now that they're enabled, take our initial
   4849         // snapshot for future delta calculation.
   4850         updateMobileRadioStateLocked(mClocks.elapsedRealtime(), null);
   4851         updateWifiStateLocked(null);
   4852     }
   4853 
   4854     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
   4855         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4856     }
   4857 
   4858     @Override public int getScreenOnCount(int which) {
   4859         return mScreenOnTimer.getCountLocked(which);
   4860     }
   4861 
   4862     @Override public long getScreenBrightnessTime(int brightnessBin,
   4863             long elapsedRealtimeUs, int which) {
   4864         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
   4865                 elapsedRealtimeUs, which);
   4866     }
   4867 
   4868     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
   4869         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4870     }
   4871 
   4872     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
   4873         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4874     }
   4875 
   4876     @Override public int getPowerSaveModeEnabledCount(int which) {
   4877         return mPowerSaveModeEnabledTimer.getCountLocked(which);
   4878     }
   4879 
   4880     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
   4881             int which) {
   4882         switch (mode) {
   4883             case DEVICE_IDLE_MODE_LIGHT:
   4884                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4885             case DEVICE_IDLE_MODE_DEEP:
   4886                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4887         }
   4888         return 0;
   4889     }
   4890 
   4891     @Override public int getDeviceIdleModeCount(int mode, int which) {
   4892         switch (mode) {
   4893             case DEVICE_IDLE_MODE_LIGHT:
   4894                 return mDeviceIdleModeLightTimer.getCountLocked(which);
   4895             case DEVICE_IDLE_MODE_DEEP:
   4896                 return mDeviceIdleModeFullTimer.getCountLocked(which);
   4897         }
   4898         return 0;
   4899     }
   4900 
   4901     @Override public long getLongestDeviceIdleModeTime(int mode) {
   4902         switch (mode) {
   4903             case DEVICE_IDLE_MODE_LIGHT:
   4904                 return mLongestLightIdleTime;
   4905             case DEVICE_IDLE_MODE_DEEP:
   4906                 return mLongestFullIdleTime;
   4907         }
   4908         return 0;
   4909     }
   4910 
   4911     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
   4912         switch (mode) {
   4913             case DEVICE_IDLE_MODE_LIGHT:
   4914                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4915             case DEVICE_IDLE_MODE_DEEP:
   4916                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4917         }
   4918         return 0;
   4919     }
   4920 
   4921     @Override public int getDeviceIdlingCount(int mode, int which) {
   4922         switch (mode) {
   4923             case DEVICE_IDLE_MODE_LIGHT:
   4924                 return mDeviceLightIdlingTimer.getCountLocked(which);
   4925             case DEVICE_IDLE_MODE_DEEP:
   4926                 return mDeviceIdlingTimer.getCountLocked(which);
   4927         }
   4928         return 0;
   4929     }
   4930 
   4931     @Override public int getNumConnectivityChange(int which) {
   4932         int val = mNumConnectivityChange;
   4933         if (which == STATS_CURRENT) {
   4934             val -= mLoadedNumConnectivityChange;
   4935         } else if (which == STATS_SINCE_UNPLUGGED) {
   4936             val -= mUnpluggedNumConnectivityChange;
   4937         }
   4938         return val;
   4939     }
   4940 
   4941     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
   4942         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4943     }
   4944 
   4945     @Override public int getPhoneOnCount(int which) {
   4946         return mPhoneOnTimer.getCountLocked(which);
   4947     }
   4948 
   4949     @Override public long getPhoneSignalStrengthTime(int strengthBin,
   4950             long elapsedRealtimeUs, int which) {
   4951         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
   4952                 elapsedRealtimeUs, which);
   4953     }
   4954 
   4955     @Override public long getPhoneSignalScanningTime(
   4956             long elapsedRealtimeUs, int which) {
   4957         return mPhoneSignalScanningTimer.getTotalTimeLocked(
   4958                 elapsedRealtimeUs, which);
   4959     }
   4960 
   4961     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
   4962         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
   4963     }
   4964 
   4965     @Override public long getPhoneDataConnectionTime(int dataType,
   4966             long elapsedRealtimeUs, int which) {
   4967         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
   4968                 elapsedRealtimeUs, which);
   4969     }
   4970 
   4971     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
   4972         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
   4973     }
   4974 
   4975     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
   4976         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4977     }
   4978 
   4979     @Override public int getMobileRadioActiveCount(int which) {
   4980         return mMobileRadioActiveTimer.getCountLocked(which);
   4981     }
   4982 
   4983     @Override public long getMobileRadioActiveAdjustedTime(int which) {
   4984         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
   4985     }
   4986 
   4987     @Override public long getMobileRadioActiveUnknownTime(int which) {
   4988         return mMobileRadioActiveUnknownTime.getCountLocked(which);
   4989     }
   4990 
   4991     @Override public int getMobileRadioActiveUnknownCount(int which) {
   4992         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
   4993     }
   4994 
   4995     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
   4996         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   4997     }
   4998 
   4999     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
   5000         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   5001     }
   5002 
   5003     @Override public long getWifiStateTime(int wifiState,
   5004             long elapsedRealtimeUs, int which) {
   5005         return mWifiStateTimer[wifiState].getTotalTimeLocked(
   5006                 elapsedRealtimeUs, which);
   5007     }
   5008 
   5009     @Override public int getWifiStateCount(int wifiState, int which) {
   5010         return mWifiStateTimer[wifiState].getCountLocked(which);
   5011     }
   5012 
   5013     @Override public long getWifiSupplStateTime(int state,
   5014             long elapsedRealtimeUs, int which) {
   5015         return mWifiSupplStateTimer[state].getTotalTimeLocked(
   5016                 elapsedRealtimeUs, which);
   5017     }
   5018 
   5019     @Override public int getWifiSupplStateCount(int state, int which) {
   5020         return mWifiSupplStateTimer[state].getCountLocked(which);
   5021     }
   5022 
   5023     @Override public long getWifiSignalStrengthTime(int strengthBin,
   5024             long elapsedRealtimeUs, int which) {
   5025         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
   5026                 elapsedRealtimeUs, which);
   5027     }
   5028 
   5029     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
   5030         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
   5031     }
   5032 
   5033     @Override
   5034     public ControllerActivityCounter getBluetoothControllerActivity() {
   5035         return mBluetoothActivity;
   5036     }
   5037 
   5038     @Override
   5039     public ControllerActivityCounter getWifiControllerActivity() {
   5040         return mWifiActivity;
   5041     }
   5042 
   5043     @Override
   5044     public ControllerActivityCounter getModemControllerActivity() {
   5045         return mModemActivity;
   5046     }
   5047 
   5048     @Override
   5049     public boolean hasBluetoothActivityReporting() {
   5050         return mHasBluetoothReporting;
   5051     }
   5052 
   5053     @Override
   5054     public boolean hasWifiActivityReporting() {
   5055         return mHasWifiReporting;
   5056     }
   5057 
   5058     @Override
   5059     public boolean hasModemActivityReporting() {
   5060         return mHasModemReporting;
   5061     }
   5062 
   5063     @Override
   5064     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
   5065         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   5066     }
   5067 
   5068     @Override
   5069     public long getFlashlightOnCount(int which) {
   5070         return mFlashlightOnTimer.getCountLocked(which);
   5071     }
   5072 
   5073     @Override
   5074     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
   5075         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   5076     }
   5077 
   5078     @Override
   5079     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
   5080         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   5081     }
   5082 
   5083     @Override
   5084     public long getNetworkActivityBytes(int type, int which) {
   5085         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
   5086             return mNetworkByteActivityCounters[type].getCountLocked(which);
   5087         } else {
   5088             return 0;
   5089         }
   5090     }
   5091 
   5092     @Override
   5093     public long getNetworkActivityPackets(int type, int which) {
   5094         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
   5095             return mNetworkPacketActivityCounters[type].getCountLocked(which);
   5096         } else {
   5097             return 0;
   5098         }
   5099     }
   5100 
   5101     @Override public long getStartClockTime() {
   5102         final long currentTime = System.currentTimeMillis();
   5103         if (ensureStartClockTime(currentTime)) {
   5104             recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
   5105                     mClocks.uptimeMillis());
   5106         }
   5107         return mStartClockTime;
   5108     }
   5109 
   5110     @Override public String getStartPlatformVersion() {
   5111         return mStartPlatformVersion;
   5112     }
   5113 
   5114     @Override public String getEndPlatformVersion() {
   5115         return mEndPlatformVersion;
   5116     }
   5117 
   5118     @Override public int getParcelVersion() {
   5119         return VERSION;
   5120     }
   5121 
   5122     @Override public boolean getIsOnBattery() {
   5123         return mOnBattery;
   5124     }
   5125 
   5126     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
   5127         return mUidStats;
   5128     }
   5129 
   5130     private static void detachTimerIfNotNull(BatteryStatsImpl.Timer timer) {
   5131         if (timer != null) {
   5132             timer.detach();
   5133         }
   5134     }
   5135 
   5136     private static boolean resetTimerIfNotNull(BatteryStatsImpl.Timer timer,
   5137             boolean detachIfReset) {
   5138         if (timer != null) {
   5139             return timer.reset(detachIfReset);
   5140         }
   5141         return true;
   5142     }
   5143 
   5144     private static void detachLongCounterIfNotNull(LongSamplingCounter counter) {
   5145         if (counter != null) {
   5146             counter.detach();
   5147         }
   5148     }
   5149 
   5150     private static void resetLongCounterIfNotNull(LongSamplingCounter counter,
   5151             boolean detachIfReset) {
   5152         if (counter != null) {
   5153             counter.reset(detachIfReset);
   5154         }
   5155     }
   5156 
   5157     /**
   5158      * The statistics associated with a particular uid.
   5159      */
   5160     public static class Uid extends BatteryStats.Uid {
   5161         /**
   5162          * BatteryStatsImpl that we are associated with.
   5163          */
   5164         protected BatteryStatsImpl mBsi;
   5165 
   5166         final int mUid;
   5167 
   5168         boolean mWifiRunning;
   5169         StopwatchTimer mWifiRunningTimer;
   5170 
   5171         boolean mFullWifiLockOut;
   5172         StopwatchTimer mFullWifiLockTimer;
   5173 
   5174         boolean mWifiScanStarted;
   5175         StopwatchTimer mWifiScanTimer;
   5176 
   5177         static final int NO_BATCHED_SCAN_STARTED = -1;
   5178         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
   5179         StopwatchTimer[] mWifiBatchedScanTimer;
   5180 
   5181         boolean mWifiMulticastEnabled;
   5182         StopwatchTimer mWifiMulticastTimer;
   5183 
   5184         StopwatchTimer mAudioTurnedOnTimer;
   5185         StopwatchTimer mVideoTurnedOnTimer;
   5186         StopwatchTimer mFlashlightTurnedOnTimer;
   5187         StopwatchTimer mCameraTurnedOnTimer;
   5188         StopwatchTimer mForegroundActivityTimer;
   5189         StopwatchTimer mBluetoothScanTimer;
   5190 
   5191         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
   5192         StopwatchTimer[] mProcessStateTimer;
   5193 
   5194         BatchTimer mVibratorOnTimer;
   5195 
   5196         Counter[] mUserActivityCounters;
   5197 
   5198         LongSamplingCounter[] mNetworkByteActivityCounters;
   5199         LongSamplingCounter[] mNetworkPacketActivityCounters;
   5200         LongSamplingCounter mMobileRadioActiveTime;
   5201         LongSamplingCounter mMobileRadioActiveCount;
   5202 
   5203         /**
   5204          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
   5205          */
   5206         private LongSamplingCounter mMobileRadioApWakeupCount;
   5207 
   5208         /**
   5209          * How many times this UID woke up the Application Processor due to a Wifi packet.
   5210          */
   5211         private LongSamplingCounter mWifiRadioApWakeupCount;
   5212 
   5213         /**
   5214          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
   5215          * Can be null if the UID has had no such activity.
   5216          */
   5217         private ControllerActivityCounterImpl mWifiControllerActivity;
   5218 
   5219         /**
   5220          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
   5221          * Can be null if the UID has had no such activity.
   5222          */
   5223         private ControllerActivityCounterImpl mBluetoothControllerActivity;
   5224 
   5225         /**
   5226          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
   5227          * Can be null if the UID has had no such activity.
   5228          */
   5229         private ControllerActivityCounterImpl mModemControllerActivity;
   5230 
   5231         /**
   5232          * The CPU times we had at the last history details update.
   5233          */
   5234         long mLastStepUserTime;
   5235         long mLastStepSystemTime;
   5236         long mCurStepUserTime;
   5237         long mCurStepSystemTime;
   5238 
   5239         LongSamplingCounter mUserCpuTime;
   5240         LongSamplingCounter mSystemCpuTime;
   5241         LongSamplingCounter mCpuPower;
   5242         LongSamplingCounter[][] mCpuClusterSpeed;
   5243 
   5244         /**
   5245          * The statistics we have collected for this uid's wake locks.
   5246          */
   5247         final OverflowArrayMap<Wakelock> mWakelockStats;
   5248 
   5249         /**
   5250          * The statistics we have collected for this uid's syncs.
   5251          */
   5252         final OverflowArrayMap<StopwatchTimer> mSyncStats;
   5253 
   5254         /**
   5255          * The statistics we have collected for this uid's jobs.
   5256          */
   5257         final OverflowArrayMap<StopwatchTimer> mJobStats;
   5258 
   5259         /**
   5260          * The statistics we have collected for this uid's sensor activations.
   5261          */
   5262         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
   5263 
   5264         /**
   5265          * The statistics we have collected for this uid's processes.
   5266          */
   5267         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
   5268 
   5269         /**
   5270          * The statistics we have collected for this uid's processes.
   5271          */
   5272         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
   5273 
   5274         /**
   5275          * The transient wake stats we have collected for this uid's pids.
   5276          */
   5277         final SparseArray<Pid> mPids = new SparseArray<>();
   5278 
   5279         public Uid(BatteryStatsImpl bsi, int uid) {
   5280             mBsi = bsi;
   5281             mUid = uid;
   5282 
   5283             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   5284             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   5285             mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   5286 
   5287             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
   5288                 @Override public Wakelock instantiateObject() {
   5289                     return new Wakelock(mBsi, Uid.this);
   5290                 }
   5291             };
   5292             mSyncStats = mBsi.new OverflowArrayMap<StopwatchTimer>(uid) {
   5293                 @Override public StopwatchTimer instantiateObject() {
   5294                     return new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null,
   5295                             mBsi.mOnBatteryTimeBase);
   5296                 }
   5297             };
   5298             mJobStats = mBsi.new OverflowArrayMap<StopwatchTimer>(uid) {
   5299                 @Override public StopwatchTimer instantiateObject() {
   5300                     return new StopwatchTimer(mBsi.mClocks, Uid.this, JOB, null,
   5301                             mBsi.mOnBatteryTimeBase);
   5302                 }
   5303             };
   5304 
   5305             mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
   5306                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
   5307             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
   5308                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
   5309             mWifiScanTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_SCAN,
   5310                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase);
   5311             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
   5312             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
   5313                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
   5314             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
   5315         }
   5316 
   5317         @Override
   5318         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
   5319             return mWakelockStats.getMap();
   5320         }
   5321 
   5322         @Override
   5323         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
   5324             return mSyncStats.getMap();
   5325         }
   5326 
   5327         @Override
   5328         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
   5329             return mJobStats.getMap();
   5330         }
   5331 
   5332         @Override
   5333         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
   5334             return mSensorStats;
   5335         }
   5336 
   5337         @Override
   5338         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
   5339             return mProcessStats;
   5340         }
   5341 
   5342         @Override
   5343         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
   5344             return mPackageStats;
   5345         }
   5346 
   5347         @Override
   5348         public int getUid() {
   5349             return mUid;
   5350         }
   5351 
   5352         @Override
   5353         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
   5354             if (!mWifiRunning) {
   5355                 mWifiRunning = true;
   5356                 if (mWifiRunningTimer == null) {
   5357                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
   5358                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
   5359                 }
   5360                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
   5361             }
   5362         }
   5363 
   5364         @Override
   5365         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
   5366             if (mWifiRunning) {
   5367                 mWifiRunning = false;
   5368                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
   5369             }
   5370         }
   5371 
   5372         @Override
   5373         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
   5374             if (!mFullWifiLockOut) {
   5375                 mFullWifiLockOut = true;
   5376                 if (mFullWifiLockTimer == null) {
   5377                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
   5378                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
   5379                 }
   5380                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
   5381             }
   5382         }
   5383 
   5384         @Override
   5385         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
   5386             if (mFullWifiLockOut) {
   5387                 mFullWifiLockOut = false;
   5388                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
   5389             }
   5390         }
   5391 
   5392         @Override
   5393         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
   5394             if (!mWifiScanStarted) {
   5395                 mWifiScanStarted = true;
   5396                 if (mWifiScanTimer == null) {
   5397                     mWifiScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
   5398                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase);
   5399                 }
   5400                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
   5401             }
   5402         }
   5403 
   5404         @Override
   5405         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
   5406             if (mWifiScanStarted) {
   5407                 mWifiScanStarted = false;
   5408                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
   5409             }
   5410         }
   5411 
   5412         @Override
   5413         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
   5414             int bin = 0;
   5415             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
   5416                 csph = csph >> 3;
   5417                 bin++;
   5418             }
   5419 
   5420             if (mWifiBatchedScanBinStarted == bin) return;
   5421 
   5422             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
   5423                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
   5424                         stopRunningLocked(elapsedRealtimeMs);
   5425             }
   5426             mWifiBatchedScanBinStarted = bin;
   5427             if (mWifiBatchedScanTimer[bin] == null) {
   5428                 makeWifiBatchedScanBin(bin, null);
   5429             }
   5430             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
   5431         }
   5432 
   5433         @Override
   5434         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
   5435             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
   5436                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
   5437                         stopRunningLocked(elapsedRealtimeMs);
   5438                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
   5439             }
   5440         }
   5441 
   5442         @Override
   5443         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
   5444             if (!mWifiMulticastEnabled) {
   5445                 mWifiMulticastEnabled = true;
   5446                 if (mWifiMulticastTimer == null) {
   5447                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   5448                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
   5449                 }
   5450                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
   5451             }
   5452         }
   5453 
   5454         @Override
   5455         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
   5456             if (mWifiMulticastEnabled) {
   5457                 mWifiMulticastEnabled = false;
   5458                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
   5459             }
   5460         }
   5461 
   5462         @Override
   5463         public ControllerActivityCounter getWifiControllerActivity() {
   5464             return mWifiControllerActivity;
   5465         }
   5466 
   5467         @Override
   5468         public ControllerActivityCounter getBluetoothControllerActivity() {
   5469             return mBluetoothControllerActivity;
   5470         }
   5471 
   5472         @Override
   5473         public ControllerActivityCounter getModemControllerActivity() {
   5474             return mModemControllerActivity;
   5475         }
   5476 
   5477         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
   5478             if (mWifiControllerActivity == null) {
   5479                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   5480                         NUM_BT_TX_LEVELS);
   5481             }
   5482             return mWifiControllerActivity;
   5483         }
   5484 
   5485         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
   5486             if (mBluetoothControllerActivity == null) {
   5487                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   5488                         NUM_BT_TX_LEVELS);
   5489             }
   5490             return mBluetoothControllerActivity;
   5491         }
   5492 
   5493         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
   5494             if (mModemControllerActivity == null) {
   5495                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   5496                         ModemActivityInfo.TX_POWER_LEVELS);
   5497             }
   5498             return mModemControllerActivity;
   5499         }
   5500 
   5501         public StopwatchTimer createAudioTurnedOnTimerLocked() {
   5502             if (mAudioTurnedOnTimer == null) {
   5503                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
   5504                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
   5505             }
   5506             return mAudioTurnedOnTimer;
   5507         }
   5508 
   5509         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
   5510             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
   5511         }
   5512 
   5513         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
   5514             if (mAudioTurnedOnTimer != null) {
   5515                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
   5516             }
   5517         }
   5518 
   5519         public void noteResetAudioLocked(long elapsedRealtimeMs) {
   5520             if (mAudioTurnedOnTimer != null) {
   5521                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
   5522             }
   5523         }
   5524 
   5525         public StopwatchTimer createVideoTurnedOnTimerLocked() {
   5526             if (mVideoTurnedOnTimer == null) {
   5527                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
   5528                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
   5529             }
   5530             return mVideoTurnedOnTimer;
   5531         }
   5532 
   5533         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
   5534             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
   5535         }
   5536 
   5537         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
   5538             if (mVideoTurnedOnTimer != null) {
   5539                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
   5540             }
   5541         }
   5542 
   5543         public void noteResetVideoLocked(long elapsedRealtimeMs) {
   5544             if (mVideoTurnedOnTimer != null) {
   5545                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
   5546             }
   5547         }
   5548 
   5549         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
   5550             if (mFlashlightTurnedOnTimer == null) {
   5551                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   5552                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
   5553             }
   5554             return mFlashlightTurnedOnTimer;
   5555         }
   5556 
   5557         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
   5558             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
   5559         }
   5560 
   5561         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
   5562             if (mFlashlightTurnedOnTimer != null) {
   5563                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
   5564             }
   5565         }
   5566 
   5567         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
   5568             if (mFlashlightTurnedOnTimer != null) {
   5569                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
   5570             }
   5571         }
   5572 
   5573         public StopwatchTimer createCameraTurnedOnTimerLocked() {
   5574             if (mCameraTurnedOnTimer == null) {
   5575                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
   5576                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
   5577             }
   5578             return mCameraTurnedOnTimer;
   5579         }
   5580 
   5581         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
   5582             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
   5583         }
   5584 
   5585         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
   5586             if (mCameraTurnedOnTimer != null) {
   5587                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
   5588             }
   5589         }
   5590 
   5591         public void noteResetCameraLocked(long elapsedRealtimeMs) {
   5592             if (mCameraTurnedOnTimer != null) {
   5593                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
   5594             }
   5595         }
   5596 
   5597         public StopwatchTimer createForegroundActivityTimerLocked() {
   5598             if (mForegroundActivityTimer == null) {
   5599                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   5600                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
   5601             }
   5602             return mForegroundActivityTimer;
   5603         }
   5604 
   5605         public StopwatchTimer createBluetoothScanTimerLocked() {
   5606             if (mBluetoothScanTimer == null) {
   5607                 mBluetoothScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
   5608                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase);
   5609             }
   5610             return mBluetoothScanTimer;
   5611         }
   5612 
   5613         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs) {
   5614             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
   5615         }
   5616 
   5617         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs) {
   5618             if (mBluetoothScanTimer != null) {
   5619                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
   5620             }
   5621         }
   5622 
   5623         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
   5624             if (mBluetoothScanTimer != null) {
   5625                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
   5626             }
   5627         }
   5628 
   5629         @Override
   5630         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
   5631             // We always start, since we want multiple foreground PIDs to nest
   5632             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
   5633         }
   5634 
   5635         @Override
   5636         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
   5637             if (mForegroundActivityTimer != null) {
   5638                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
   5639             }
   5640         }
   5641 
   5642         public BatchTimer createVibratorOnTimerLocked() {
   5643             if (mVibratorOnTimer == null) {
   5644                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
   5645                         mBsi.mOnBatteryTimeBase);
   5646             }
   5647             return mVibratorOnTimer;
   5648         }
   5649 
   5650         public void noteVibratorOnLocked(long durationMillis) {
   5651             createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
   5652         }
   5653 
   5654         public void noteVibratorOffLocked() {
   5655             if (mVibratorOnTimer != null) {
   5656                 mVibratorOnTimer.abortLastDuration(mBsi);
   5657             }
   5658         }
   5659 
   5660         @Override
   5661         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
   5662             if (mWifiRunningTimer == null) {
   5663                 return 0;
   5664             }
   5665             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   5666         }
   5667 
   5668         @Override
   5669         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
   5670             if (mFullWifiLockTimer == null) {
   5671                 return 0;
   5672             }
   5673             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   5674         }
   5675 
   5676         @Override
   5677         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
   5678             if (mWifiScanTimer == null) {
   5679                 return 0;
   5680             }
   5681             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   5682         }
   5683 
   5684         @Override
   5685         public int getWifiScanCount(int which) {
   5686             if (mWifiScanTimer == null) {
   5687                 return 0;
   5688             }
   5689             return mWifiScanTimer.getCountLocked(which);
   5690         }
   5691 
   5692         @Override
   5693         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
   5694             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
   5695             if (mWifiBatchedScanTimer[csphBin] == null) {
   5696                 return 0;
   5697             }
   5698             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
   5699         }
   5700 
   5701         @Override
   5702         public int getWifiBatchedScanCount(int csphBin, int which) {
   5703             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
   5704             if (mWifiBatchedScanTimer[csphBin] == null) {
   5705                 return 0;
   5706             }
   5707             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
   5708         }
   5709 
   5710         @Override
   5711         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
   5712             if (mWifiMulticastTimer == null) {
   5713                 return 0;
   5714             }
   5715             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   5716         }
   5717 
   5718         @Override
   5719         public Timer getAudioTurnedOnTimer() {
   5720             return mAudioTurnedOnTimer;
   5721         }
   5722 
   5723         @Override
   5724         public Timer getVideoTurnedOnTimer() {
   5725             return mVideoTurnedOnTimer;
   5726         }
   5727 
   5728         @Override
   5729         public Timer getFlashlightTurnedOnTimer() {
   5730             return mFlashlightTurnedOnTimer;
   5731         }
   5732 
   5733         @Override
   5734         public Timer getCameraTurnedOnTimer() {
   5735             return mCameraTurnedOnTimer;
   5736         }
   5737 
   5738         @Override
   5739         public Timer getForegroundActivityTimer() {
   5740             return mForegroundActivityTimer;
   5741         }
   5742 
   5743         @Override
   5744         public Timer getBluetoothScanTimer() {
   5745             return mBluetoothScanTimer;
   5746         }
   5747 
   5748         void makeProcessState(int i, Parcel in) {
   5749             if (i < 0 || i >= NUM_PROCESS_STATE) return;
   5750 
   5751             if (in == null) {
   5752                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
   5753                         mBsi.mOnBatteryTimeBase);
   5754             } else {
   5755                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
   5756                         mBsi.mOnBatteryTimeBase, in);
   5757             }
   5758         }
   5759 
   5760         @Override
   5761         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
   5762             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
   5763             if (mProcessStateTimer[state] == null) {
   5764                 return 0;
   5765             }
   5766             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
   5767         }
   5768 
   5769         @Override
   5770         public Timer getProcessStateTimer(int state) {
   5771             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
   5772             return mProcessStateTimer[state];
   5773         }
   5774 
   5775         @Override
   5776         public Timer getVibratorOnTimer() {
   5777             return mVibratorOnTimer;
   5778         }
   5779 
   5780         @Override
   5781         public void noteUserActivityLocked(int type) {
   5782             if (mUserActivityCounters == null) {
   5783                 initUserActivityLocked();
   5784             }
   5785             if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
   5786                 mUserActivityCounters[type].stepAtomic();
   5787             } else {
   5788                 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
   5789                         new Throwable());
   5790             }
   5791         }
   5792 
   5793         @Override
   5794         public boolean hasUserActivity() {
   5795             return mUserActivityCounters != null;
   5796         }
   5797 
   5798         @Override
   5799         public int getUserActivityCount(int type, int which) {
   5800             if (mUserActivityCounters == null) {
   5801                 return 0;
   5802             }
   5803             return mUserActivityCounters[type].getCountLocked(which);
   5804         }
   5805 
   5806         void makeWifiBatchedScanBin(int i, Parcel in) {
   5807             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
   5808 
   5809             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
   5810             if (collected == null) {
   5811                 collected = new ArrayList<StopwatchTimer>();
   5812                 mBsi.mWifiBatchedScanTimers.put(i, collected);
   5813             }
   5814             if (in == null) {
   5815                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
   5816                         collected, mBsi.mOnBatteryTimeBase);
   5817             } else {
   5818                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
   5819                         collected, mBsi.mOnBatteryTimeBase, in);
   5820             }
   5821         }
   5822 
   5823 
   5824         void initUserActivityLocked() {
   5825             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
   5826             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   5827                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
   5828             }
   5829         }
   5830 
   5831         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
   5832             if (mNetworkByteActivityCounters == null) {
   5833                 initNetworkActivityLocked();
   5834             }
   5835             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
   5836                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
   5837                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
   5838             } else {
   5839                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
   5840                         new Throwable());
   5841             }
   5842         }
   5843 
   5844         void noteMobileRadioActiveTimeLocked(long batteryUptime) {
   5845             if (mNetworkByteActivityCounters == null) {
   5846                 initNetworkActivityLocked();
   5847             }
   5848             mMobileRadioActiveTime.addCountLocked(batteryUptime);
   5849             mMobileRadioActiveCount.addCountLocked(1);
   5850         }
   5851 
   5852         @Override
   5853         public boolean hasNetworkActivity() {
   5854             return mNetworkByteActivityCounters != null;
   5855         }
   5856 
   5857         @Override
   5858         public long getNetworkActivityBytes(int type, int which) {
   5859             if (mNetworkByteActivityCounters != null && type >= 0
   5860                     && type < mNetworkByteActivityCounters.length) {
   5861                 return mNetworkByteActivityCounters[type].getCountLocked(which);
   5862             } else {
   5863                 return 0;
   5864             }
   5865         }
   5866 
   5867         @Override
   5868         public long getNetworkActivityPackets(int type, int which) {
   5869             if (mNetworkPacketActivityCounters != null && type >= 0
   5870                     && type < mNetworkPacketActivityCounters.length) {
   5871                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
   5872             } else {
   5873                 return 0;
   5874             }
   5875         }
   5876 
   5877         @Override
   5878         public long getMobileRadioActiveTime(int which) {
   5879             return mMobileRadioActiveTime != null
   5880                     ? mMobileRadioActiveTime.getCountLocked(which) : 0;
   5881         }
   5882 
   5883         @Override
   5884         public int getMobileRadioActiveCount(int which) {
   5885             return mMobileRadioActiveCount != null
   5886                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
   5887         }
   5888 
   5889         @Override
   5890         public long getUserCpuTimeUs(int which) {
   5891             return mUserCpuTime.getCountLocked(which);
   5892         }
   5893 
   5894         @Override
   5895         public long getSystemCpuTimeUs(int which) {
   5896             return mSystemCpuTime.getCountLocked(which);
   5897         }
   5898 
   5899         @Override
   5900         public long getCpuPowerMaUs(int which) {
   5901             return mCpuPower.getCountLocked(which);
   5902         }
   5903 
   5904         @Override
   5905         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
   5906             if (mCpuClusterSpeed != null) {
   5907                 if (cluster >= 0 && cluster < mCpuClusterSpeed.length) {
   5908                     final LongSamplingCounter[] cpuSpeeds = mCpuClusterSpeed[cluster];
   5909                     if (cpuSpeeds != null) {
   5910                         if (step >= 0 && step < cpuSpeeds.length) {
   5911                             final LongSamplingCounter c = cpuSpeeds[step];
   5912                             if (c != null) {
   5913                                 return c.getCountLocked(which);
   5914                             }
   5915                         }
   5916                     }
   5917                 }
   5918             }
   5919             return 0;
   5920         }
   5921 
   5922         public void noteMobileRadioApWakeupLocked() {
   5923             if (mMobileRadioApWakeupCount == null) {
   5924                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   5925             }
   5926             mMobileRadioApWakeupCount.addCountLocked(1);
   5927         }
   5928 
   5929         @Override
   5930         public long getMobileRadioApWakeupCount(int which) {
   5931             if (mMobileRadioApWakeupCount != null) {
   5932                 return mMobileRadioApWakeupCount.getCountLocked(which);
   5933             }
   5934             return 0;
   5935         }
   5936 
   5937         public void noteWifiRadioApWakeupLocked() {
   5938             if (mWifiRadioApWakeupCount == null) {
   5939                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   5940             }
   5941             mWifiRadioApWakeupCount.addCountLocked(1);
   5942         }
   5943 
   5944         @Override
   5945         public long getWifiRadioApWakeupCount(int which) {
   5946             if (mWifiRadioApWakeupCount != null) {
   5947                 return mWifiRadioApWakeupCount.getCountLocked(which);
   5948             }
   5949             return 0;
   5950         }
   5951 
   5952         void initNetworkActivityLocked() {
   5953             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   5954             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   5955             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   5956                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   5957                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   5958             }
   5959             mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   5960             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   5961         }
   5962 
   5963         /**
   5964          * Clear all stats for this uid.  Returns true if the uid is completely
   5965          * inactive so can be dropped.
   5966          */
   5967         boolean reset() {
   5968             boolean active = false;
   5969 
   5970             if (mWifiRunningTimer != null) {
   5971                 active |= !mWifiRunningTimer.reset(false);
   5972                 active |= mWifiRunning;
   5973             }
   5974             if (mFullWifiLockTimer != null) {
   5975                 active |= !mFullWifiLockTimer.reset(false);
   5976                 active |= mFullWifiLockOut;
   5977             }
   5978             if (mWifiScanTimer != null) {
   5979                 active |= !mWifiScanTimer.reset(false);
   5980                 active |= mWifiScanStarted;
   5981             }
   5982             if (mWifiBatchedScanTimer != null) {
   5983                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   5984                     if (mWifiBatchedScanTimer[i] != null) {
   5985                         active |= !mWifiBatchedScanTimer[i].reset(false);
   5986                     }
   5987                 }
   5988                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
   5989             }
   5990             if (mWifiMulticastTimer != null) {
   5991                 active |= !mWifiMulticastTimer.reset(false);
   5992                 active |= mWifiMulticastEnabled;
   5993             }
   5994 
   5995             active |= !resetTimerIfNotNull(mAudioTurnedOnTimer, false);
   5996             active |= !resetTimerIfNotNull(mVideoTurnedOnTimer, false);
   5997             active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false);
   5998             active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false);
   5999             active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
   6000             active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
   6001 
   6002             if (mProcessStateTimer != null) {
   6003                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
   6004                     if (mProcessStateTimer[i] != null) {
   6005                         active |= !mProcessStateTimer[i].reset(false);
   6006                     }
   6007                 }
   6008                 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
   6009             }
   6010             if (mVibratorOnTimer != null) {
   6011                 if (mVibratorOnTimer.reset(false)) {
   6012                     mVibratorOnTimer.detach();
   6013                     mVibratorOnTimer = null;
   6014                 } else {
   6015                     active = true;
   6016                 }
   6017             }
   6018 
   6019             if (mUserActivityCounters != null) {
   6020                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   6021                     mUserActivityCounters[i].reset(false);
   6022                 }
   6023             }
   6024 
   6025             if (mNetworkByteActivityCounters != null) {
   6026                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   6027                     mNetworkByteActivityCounters[i].reset(false);
   6028                     mNetworkPacketActivityCounters[i].reset(false);
   6029                 }
   6030                 mMobileRadioActiveTime.reset(false);
   6031                 mMobileRadioActiveCount.reset(false);
   6032             }
   6033 
   6034             if (mWifiControllerActivity != null) {
   6035                 mWifiControllerActivity.reset(false);
   6036             }
   6037 
   6038             if (mBluetoothControllerActivity != null) {
   6039                 mBluetoothControllerActivity.reset(false);
   6040             }
   6041 
   6042             if (mModemControllerActivity != null) {
   6043                 mModemControllerActivity.reset(false);
   6044             }
   6045 
   6046             mUserCpuTime.reset(false);
   6047             mSystemCpuTime.reset(false);
   6048             mCpuPower.reset(false);
   6049 
   6050             if (mCpuClusterSpeed != null) {
   6051                 for (LongSamplingCounter[] speeds : mCpuClusterSpeed) {
   6052                     if (speeds != null) {
   6053                         for (LongSamplingCounter speed : speeds) {
   6054                             if (speed != null) {
   6055                                 speed.reset(false);
   6056                             }
   6057                         }
   6058                     }
   6059                 }
   6060             }
   6061 
   6062             resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false);
   6063             resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false);
   6064 
   6065             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
   6066             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
   6067                 Wakelock wl = wakeStats.valueAt(iw);
   6068                 if (wl.reset()) {
   6069                     wakeStats.removeAt(iw);
   6070                 } else {
   6071                     active = true;
   6072                 }
   6073             }
   6074             mWakelockStats.cleanup();
   6075             final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
   6076             for (int is=syncStats.size()-1; is>=0; is--) {
   6077                 StopwatchTimer timer = syncStats.valueAt(is);
   6078                 if (timer.reset(false)) {
   6079                     syncStats.removeAt(is);
   6080                     timer.detach();
   6081                 } else {
   6082                     active = true;
   6083                 }
   6084             }
   6085             mSyncStats.cleanup();
   6086             final ArrayMap<String, StopwatchTimer> jobStats = mJobStats.getMap();
   6087             for (int ij=jobStats.size()-1; ij>=0; ij--) {
   6088                 StopwatchTimer timer = jobStats.valueAt(ij);
   6089                 if (timer.reset(false)) {
   6090                     jobStats.removeAt(ij);
   6091                     timer.detach();
   6092                 } else {
   6093                     active = true;
   6094                 }
   6095             }
   6096             mJobStats.cleanup();
   6097             for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
   6098                 Sensor s = mSensorStats.valueAt(ise);
   6099                 if (s.reset()) {
   6100                     mSensorStats.removeAt(ise);
   6101                 } else {
   6102                     active = true;
   6103                 }
   6104             }
   6105             for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
   6106                 Proc proc = mProcessStats.valueAt(ip);
   6107                 proc.detach();
   6108             }
   6109             mProcessStats.clear();
   6110             if (mPids.size() > 0) {
   6111                 for (int i=mPids.size()-1; i>=0; i--) {
   6112                     Pid pid = mPids.valueAt(i);
   6113                     if (pid.mWakeNesting > 0) {
   6114                         active = true;
   6115                     } else {
   6116                         mPids.removeAt(i);
   6117                     }
   6118                 }
   6119             }
   6120             if (mPackageStats.size() > 0) {
   6121                 Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
   6122                 while (it.hasNext()) {
   6123                     Map.Entry<String, Pkg> pkgEntry = it.next();
   6124                     Pkg p = pkgEntry.getValue();
   6125                     p.detach();
   6126                     if (p.mServiceStats.size() > 0) {
   6127                         Iterator<Map.Entry<String, Pkg.Serv>> it2
   6128                                 = p.mServiceStats.entrySet().iterator();
   6129                         while (it2.hasNext()) {
   6130                             Map.Entry<String, Pkg.Serv> servEntry = it2.next();
   6131                             servEntry.getValue().detach();
   6132                         }
   6133                     }
   6134                 }
   6135                 mPackageStats.clear();
   6136             }
   6137 
   6138             mLastStepUserTime = mLastStepSystemTime = 0;
   6139             mCurStepUserTime = mCurStepSystemTime = 0;
   6140 
   6141             if (!active) {
   6142                 if (mWifiRunningTimer != null) {
   6143                     mWifiRunningTimer.detach();
   6144                 }
   6145                 if (mFullWifiLockTimer != null) {
   6146                     mFullWifiLockTimer.detach();
   6147                 }
   6148                 if (mWifiScanTimer != null) {
   6149                     mWifiScanTimer.detach();
   6150                 }
   6151                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   6152                     if (mWifiBatchedScanTimer[i] != null) {
   6153                         mWifiBatchedScanTimer[i].detach();
   6154                     }
   6155                 }
   6156                 if (mWifiMulticastTimer != null) {
   6157                     mWifiMulticastTimer.detach();
   6158                 }
   6159                 if (mAudioTurnedOnTimer != null) {
   6160                     mAudioTurnedOnTimer.detach();
   6161                     mAudioTurnedOnTimer = null;
   6162                 }
   6163                 if (mVideoTurnedOnTimer != null) {
   6164                     mVideoTurnedOnTimer.detach();
   6165                     mVideoTurnedOnTimer = null;
   6166                 }
   6167                 if (mFlashlightTurnedOnTimer != null) {
   6168                     mFlashlightTurnedOnTimer.detach();
   6169                     mFlashlightTurnedOnTimer = null;
   6170                 }
   6171                 if (mCameraTurnedOnTimer != null) {
   6172                     mCameraTurnedOnTimer.detach();
   6173                     mCameraTurnedOnTimer = null;
   6174                 }
   6175                 if (mForegroundActivityTimer != null) {
   6176                     mForegroundActivityTimer.detach();
   6177                     mForegroundActivityTimer = null;
   6178                 }
   6179                 if (mBluetoothScanTimer != null) {
   6180                     mBluetoothScanTimer.detach();
   6181                     mBluetoothScanTimer = null;
   6182                 }
   6183                 if (mUserActivityCounters != null) {
   6184                     for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   6185                         mUserActivityCounters[i].detach();
   6186                     }
   6187                 }
   6188                 if (mNetworkByteActivityCounters != null) {
   6189                     for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   6190                         mNetworkByteActivityCounters[i].detach();
   6191                         mNetworkPacketActivityCounters[i].detach();
   6192                     }
   6193                 }
   6194 
   6195                 if (mWifiControllerActivity != null) {
   6196                     mWifiControllerActivity.detach();
   6197                 }
   6198 
   6199                 if (mBluetoothControllerActivity != null) {
   6200                     mBluetoothControllerActivity.detach();
   6201                 }
   6202 
   6203                 if (mModemControllerActivity != null) {
   6204                     mModemControllerActivity.detach();
   6205                 }
   6206 
   6207                 mPids.clear();
   6208 
   6209                 mUserCpuTime.detach();
   6210                 mSystemCpuTime.detach();
   6211                 mCpuPower.detach();
   6212 
   6213                 if (mCpuClusterSpeed != null) {
   6214                     for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
   6215                         if (cpuSpeeds != null) {
   6216                             for (LongSamplingCounter c : cpuSpeeds) {
   6217                                 if (c != null) {
   6218                                     c.detach();
   6219                                 }
   6220                             }
   6221                         }
   6222                     }
   6223                 }
   6224 
   6225                 detachLongCounterIfNotNull(mMobileRadioApWakeupCount);
   6226                 detachLongCounterIfNotNull(mWifiRadioApWakeupCount);
   6227             }
   6228 
   6229             return !active;
   6230         }
   6231 
   6232         void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
   6233             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
   6234             int NW = wakeStats.size();
   6235             out.writeInt(NW);
   6236             for (int iw=0; iw<NW; iw++) {
   6237                 out.writeString(wakeStats.keyAt(iw));
   6238                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
   6239                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
   6240             }
   6241 
   6242             final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
   6243             int NS = syncStats.size();
   6244             out.writeInt(NS);
   6245             for (int is=0; is<NS; is++) {
   6246                 out.writeString(syncStats.keyAt(is));
   6247                 StopwatchTimer timer = syncStats.valueAt(is);
   6248                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
   6249             }
   6250 
   6251             final ArrayMap<String, StopwatchTimer> jobStats = mJobStats.getMap();
   6252             int NJ = jobStats.size();
   6253             out.writeInt(NJ);
   6254             for (int ij=0; ij<NJ; ij++) {
   6255                 out.writeString(jobStats.keyAt(ij));
   6256                 StopwatchTimer timer = jobStats.valueAt(ij);
   6257                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
   6258             }
   6259 
   6260             int NSE = mSensorStats.size();
   6261             out.writeInt(NSE);
   6262             for (int ise=0; ise<NSE; ise++) {
   6263                 out.writeInt(mSensorStats.keyAt(ise));
   6264                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
   6265                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
   6266             }
   6267 
   6268             int NP = mProcessStats.size();
   6269             out.writeInt(NP);
   6270             for (int ip=0; ip<NP; ip++) {
   6271                 out.writeString(mProcessStats.keyAt(ip));
   6272                 Uid.Proc proc = mProcessStats.valueAt(ip);
   6273                 proc.writeToParcelLocked(out);
   6274             }
   6275 
   6276             out.writeInt(mPackageStats.size());
   6277             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
   6278                 out.writeString(pkgEntry.getKey());
   6279                 Uid.Pkg pkg = pkgEntry.getValue();
   6280                 pkg.writeToParcelLocked(out);
   6281             }
   6282 
   6283             if (mWifiRunningTimer != null) {
   6284                 out.writeInt(1);
   6285                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
   6286             } else {
   6287                 out.writeInt(0);
   6288             }
   6289             if (mFullWifiLockTimer != null) {
   6290                 out.writeInt(1);
   6291                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
   6292             } else {
   6293                 out.writeInt(0);
   6294             }
   6295             if (mWifiScanTimer != null) {
   6296                 out.writeInt(1);
   6297                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
   6298             } else {
   6299                 out.writeInt(0);
   6300             }
   6301             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   6302                 if (mWifiBatchedScanTimer[i] != null) {
   6303                     out.writeInt(1);
   6304                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
   6305                 } else {
   6306                     out.writeInt(0);
   6307                 }
   6308             }
   6309             if (mWifiMulticastTimer != null) {
   6310                 out.writeInt(1);
   6311                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
   6312             } else {
   6313                 out.writeInt(0);
   6314             }
   6315 
   6316             if (mAudioTurnedOnTimer != null) {
   6317                 out.writeInt(1);
   6318                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
   6319             } else {
   6320                 out.writeInt(0);
   6321             }
   6322             if (mVideoTurnedOnTimer != null) {
   6323                 out.writeInt(1);
   6324                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
   6325             } else {
   6326                 out.writeInt(0);
   6327             }
   6328             if (mFlashlightTurnedOnTimer != null) {
   6329                 out.writeInt(1);
   6330                 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
   6331             } else {
   6332                 out.writeInt(0);
   6333             }
   6334             if (mCameraTurnedOnTimer != null) {
   6335                 out.writeInt(1);
   6336                 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
   6337             } else {
   6338                 out.writeInt(0);
   6339             }
   6340             if (mForegroundActivityTimer != null) {
   6341                 out.writeInt(1);
   6342                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
   6343             } else {
   6344                 out.writeInt(0);
   6345             }
   6346             if (mBluetoothScanTimer != null) {
   6347                 out.writeInt(1);
   6348                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
   6349             } else {
   6350                 out.writeInt(0);
   6351             }
   6352             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
   6353                 if (mProcessStateTimer[i] != null) {
   6354                     out.writeInt(1);
   6355                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
   6356                 } else {
   6357                     out.writeInt(0);
   6358                 }
   6359             }
   6360             if (mVibratorOnTimer != null) {
   6361                 out.writeInt(1);
   6362                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
   6363             } else {
   6364                 out.writeInt(0);
   6365             }
   6366             if (mUserActivityCounters != null) {
   6367                 out.writeInt(1);
   6368                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   6369                     mUserActivityCounters[i].writeToParcel(out);
   6370                 }
   6371             } else {
   6372                 out.writeInt(0);
   6373             }
   6374             if (mNetworkByteActivityCounters != null) {
   6375                 out.writeInt(1);
   6376                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   6377                     mNetworkByteActivityCounters[i].writeToParcel(out);
   6378                     mNetworkPacketActivityCounters[i].writeToParcel(out);
   6379                 }
   6380                 mMobileRadioActiveTime.writeToParcel(out);
   6381                 mMobileRadioActiveCount.writeToParcel(out);
   6382             } else {
   6383                 out.writeInt(0);
   6384             }
   6385 
   6386             if (mWifiControllerActivity != null) {
   6387                 out.writeInt(1);
   6388                 mWifiControllerActivity.writeToParcel(out, 0);
   6389             } else {
   6390                 out.writeInt(0);
   6391             }
   6392 
   6393             if (mBluetoothControllerActivity != null) {
   6394                 out.writeInt(1);
   6395                 mBluetoothControllerActivity.writeToParcel(out, 0);
   6396             } else {
   6397                 out.writeInt(0);
   6398             }
   6399 
   6400             if (mModemControllerActivity != null) {
   6401                 out.writeInt(1);
   6402                 mModemControllerActivity.writeToParcel(out, 0);
   6403             } else {
   6404                 out.writeInt(0);
   6405             }
   6406 
   6407             mUserCpuTime.writeToParcel(out);
   6408             mSystemCpuTime.writeToParcel(out);
   6409             mCpuPower.writeToParcel(out);
   6410 
   6411             if (mCpuClusterSpeed != null) {
   6412                 out.writeInt(1);
   6413                 out.writeInt(mCpuClusterSpeed.length);
   6414                 for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
   6415                     if (cpuSpeeds != null) {
   6416                         out.writeInt(1);
   6417                         out.writeInt(cpuSpeeds.length);
   6418                         for (LongSamplingCounter c : cpuSpeeds) {
   6419                             if (c != null) {
   6420                                 out.writeInt(1);
   6421                                 c.writeToParcel(out);
   6422                             } else {
   6423                                 out.writeInt(0);
   6424                             }
   6425                         }
   6426                     } else {
   6427                         out.writeInt(0);
   6428                     }
   6429                 }
   6430             } else {
   6431                 out.writeInt(0);
   6432             }
   6433 
   6434             if (mMobileRadioApWakeupCount != null) {
   6435                 out.writeInt(1);
   6436                 mMobileRadioApWakeupCount.writeToParcel(out);
   6437             } else {
   6438                 out.writeInt(0);
   6439             }
   6440 
   6441             if (mWifiRadioApWakeupCount != null) {
   6442                 out.writeInt(1);
   6443                 mWifiRadioApWakeupCount.writeToParcel(out);
   6444             } else {
   6445                 out.writeInt(0);
   6446             }
   6447         }
   6448 
   6449         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
   6450             int numWakelocks = in.readInt();
   6451             mWakelockStats.clear();
   6452             for (int j = 0; j < numWakelocks; j++) {
   6453                 String wakelockName = in.readString();
   6454                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
   6455                 wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in);
   6456                 mWakelockStats.add(wakelockName, wakelock);
   6457             }
   6458 
   6459             int numSyncs = in.readInt();
   6460             mSyncStats.clear();
   6461             for (int j = 0; j < numSyncs; j++) {
   6462                 String syncName = in.readString();
   6463                 if (in.readInt() != 0) {
   6464                     mSyncStats.add(syncName,
   6465                             new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null, timeBase, in));
   6466                 }
   6467             }
   6468 
   6469             int numJobs = in.readInt();
   6470             mJobStats.clear();
   6471             for (int j = 0; j < numJobs; j++) {
   6472                 String jobName = in.readString();
   6473                 if (in.readInt() != 0) {
   6474                     mJobStats.add(jobName, new StopwatchTimer(mBsi.mClocks, Uid.this, JOB, null,
   6475                                 timeBase, in));
   6476                 }
   6477             }
   6478 
   6479             int numSensors = in.readInt();
   6480             mSensorStats.clear();
   6481             for (int k = 0; k < numSensors; k++) {
   6482                 int sensorNumber = in.readInt();
   6483                 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
   6484                 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, in);
   6485                 mSensorStats.put(sensorNumber, sensor);
   6486             }
   6487 
   6488             int numProcs = in.readInt();
   6489             mProcessStats.clear();
   6490             for (int k = 0; k < numProcs; k++) {
   6491                 String processName = in.readString();
   6492                 Uid.Proc proc = new Proc(mBsi, processName);
   6493                 proc.readFromParcelLocked(in);
   6494                 mProcessStats.put(processName, proc);
   6495             }
   6496 
   6497             int numPkgs = in.readInt();
   6498             mPackageStats.clear();
   6499             for (int l = 0; l < numPkgs; l++) {
   6500                 String packageName = in.readString();
   6501                 Uid.Pkg pkg = new Pkg(mBsi);
   6502                 pkg.readFromParcelLocked(in);
   6503                 mPackageStats.put(packageName, pkg);
   6504             }
   6505 
   6506             mWifiRunning = false;
   6507             if (in.readInt() != 0) {
   6508                 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
   6509                         mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
   6510             } else {
   6511                 mWifiRunningTimer = null;
   6512             }
   6513             mFullWifiLockOut = false;
   6514             if (in.readInt() != 0) {
   6515                 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
   6516                         mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
   6517             } else {
   6518                 mFullWifiLockTimer = null;
   6519             }
   6520             mWifiScanStarted = false;
   6521             if (in.readInt() != 0) {
   6522                 mWifiScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
   6523                         mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, in);
   6524             } else {
   6525                 mWifiScanTimer = null;
   6526             }
   6527             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
   6528             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   6529                 if (in.readInt() != 0) {
   6530                     makeWifiBatchedScanBin(i, in);
   6531                 } else {
   6532                     mWifiBatchedScanTimer[i] = null;
   6533                 }
   6534             }
   6535             mWifiMulticastEnabled = false;
   6536             if (in.readInt() != 0) {
   6537                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
   6538                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
   6539             } else {
   6540                 mWifiMulticastTimer = null;
   6541             }
   6542             if (in.readInt() != 0) {
   6543                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
   6544                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
   6545             } else {
   6546                 mAudioTurnedOnTimer = null;
   6547             }
   6548             if (in.readInt() != 0) {
   6549                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
   6550                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
   6551             } else {
   6552                 mVideoTurnedOnTimer = null;
   6553             }
   6554             if (in.readInt() != 0) {
   6555                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   6556                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
   6557             } else {
   6558                 mFlashlightTurnedOnTimer = null;
   6559             }
   6560             if (in.readInt() != 0) {
   6561                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
   6562                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
   6563             } else {
   6564                 mCameraTurnedOnTimer = null;
   6565             }
   6566             if (in.readInt() != 0) {
   6567                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   6568                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
   6569             } else {
   6570                 mForegroundActivityTimer = null;
   6571             }
   6572             if (in.readInt() != 0) {
   6573                 mBluetoothScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
   6574                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase, in);
   6575             } else {
   6576                 mBluetoothScanTimer = null;
   6577             }
   6578             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
   6579             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
   6580                 if (in.readInt() != 0) {
   6581                     makeProcessState(i, in);
   6582                 } else {
   6583                     mProcessStateTimer[i] = null;
   6584                 }
   6585             }
   6586             if (in.readInt() != 0) {
   6587                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
   6588                         mBsi.mOnBatteryTimeBase, in);
   6589             } else {
   6590                 mVibratorOnTimer = null;
   6591             }
   6592             if (in.readInt() != 0) {
   6593                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
   6594                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   6595                     mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
   6596                 }
   6597             } else {
   6598                 mUserActivityCounters = null;
   6599             }
   6600             if (in.readInt() != 0) {
   6601                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   6602                 mNetworkPacketActivityCounters
   6603                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   6604                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   6605                     mNetworkByteActivityCounters[i]
   6606                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   6607                     mNetworkPacketActivityCounters[i]
   6608                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   6609                 }
   6610                 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   6611                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   6612             } else {
   6613                 mNetworkByteActivityCounters = null;
   6614                 mNetworkPacketActivityCounters = null;
   6615             }
   6616 
   6617             if (in.readInt() != 0) {
   6618                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   6619                         NUM_WIFI_TX_LEVELS, in);
   6620             } else {
   6621                 mWifiControllerActivity = null;
   6622             }
   6623 
   6624             if (in.readInt() != 0) {
   6625                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   6626                         NUM_BT_TX_LEVELS, in);
   6627             } else {
   6628                 mBluetoothControllerActivity = null;
   6629             }
   6630 
   6631             if (in.readInt() != 0) {
   6632                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   6633                         ModemActivityInfo.TX_POWER_LEVELS, in);
   6634             } else {
   6635                 mModemControllerActivity = null;
   6636             }
   6637 
   6638             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   6639             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   6640             mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   6641 
   6642             if (in.readInt() != 0) {
   6643                 int numCpuClusters = in.readInt();
   6644                 if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
   6645                     throw new ParcelFormatException("Incompatible number of cpu clusters");
   6646                 }
   6647 
   6648                 mCpuClusterSpeed = new LongSamplingCounter[numCpuClusters][];
   6649                 for (int cluster = 0; cluster < numCpuClusters; cluster++) {
   6650                     if (in.readInt() != 0) {
   6651                         int numSpeeds = in.readInt();
   6652                         if (mBsi.mPowerProfile != null &&
   6653                                 mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
   6654                             throw new ParcelFormatException("Incompatible number of cpu speeds");
   6655                         }
   6656 
   6657                         final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
   6658                         mCpuClusterSpeed[cluster] = cpuSpeeds;
   6659                         for (int speed = 0; speed < numSpeeds; speed++) {
   6660                             if (in.readInt() != 0) {
   6661                                 cpuSpeeds[speed] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   6662                             }
   6663                         }
   6664                     } else {
   6665                         mCpuClusterSpeed[cluster] = null;
   6666                     }
   6667                 }
   6668             } else {
   6669                 mCpuClusterSpeed = null;
   6670             }
   6671 
   6672             if (in.readInt() != 0) {
   6673                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   6674             } else {
   6675                 mMobileRadioApWakeupCount = null;
   6676             }
   6677 
   6678             if (in.readInt() != 0) {
   6679                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   6680             } else {
   6681                 mWifiRadioApWakeupCount = null;
   6682             }
   6683         }
   6684 
   6685         /**
   6686          * The statistics associated with a particular wake lock.
   6687          */
   6688         public static class Wakelock extends BatteryStats.Uid.Wakelock {
   6689             /**
   6690              * BatteryStatsImpl that we are associated with.
   6691              */
   6692             protected BatteryStatsImpl mBsi;
   6693 
   6694             /**
   6695              * BatteryStatsImpl that we are associated with.
   6696              */
   6697             protected Uid mUid;
   6698 
   6699             /**
   6700              * How long (in ms) this uid has been keeping the device partially awake.
   6701              */
   6702             DurationTimer mTimerPartial;
   6703 
   6704             /**
   6705              * How long (in ms) this uid has been keeping the device fully awake.
   6706              */
   6707             StopwatchTimer mTimerFull;
   6708 
   6709             /**
   6710              * How long (in ms) this uid has had a window keeping the device awake.
   6711              */
   6712             StopwatchTimer mTimerWindow;
   6713 
   6714             /**
   6715              * How long (in ms) this uid has had a draw wake lock.
   6716              */
   6717             StopwatchTimer mTimerDraw;
   6718 
   6719             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
   6720                 mBsi = bsi;
   6721                 mUid = uid;
   6722             }
   6723 
   6724             /**
   6725              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
   6726              * proper timer pool from the given BatteryStatsImpl object.
   6727              *
   6728              * @param in the Parcel to be read from.
   6729              * return a new Timer, or null.
   6730              */
   6731             private StopwatchTimer readStopwatchTimerFromParcel(int type,
   6732                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
   6733                 if (in.readInt() == 0) {
   6734                     return null;
   6735                 }
   6736 
   6737                 return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
   6738             }
   6739 
   6740             /**
   6741              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
   6742              * proper timer pool from the given BatteryStatsImpl object.
   6743              *
   6744              * @param in the Parcel to be read from.
   6745              * return a new Timer, or null.
   6746              */
   6747             private DurationTimer readDurationTimerFromParcel(int type,
   6748                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
   6749                 if (in.readInt() == 0) {
   6750                     return null;
   6751                 }
   6752 
   6753                 return new DurationTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
   6754             }
   6755 
   6756             boolean reset() {
   6757                 boolean wlactive = false;
   6758                 if (mTimerFull != null) {
   6759                     wlactive |= !mTimerFull.reset(false);
   6760                 }
   6761                 if (mTimerPartial != null) {
   6762                     wlactive |= !mTimerPartial.reset(false);
   6763                 }
   6764                 if (mTimerWindow != null) {
   6765                     wlactive |= !mTimerWindow.reset(false);
   6766                 }
   6767                 if (mTimerDraw != null) {
   6768                     wlactive |= !mTimerDraw.reset(false);
   6769                 }
   6770                 if (!wlactive) {
   6771                     if (mTimerFull != null) {
   6772                         mTimerFull.detach();
   6773                         mTimerFull = null;
   6774                     }
   6775                     if (mTimerPartial != null) {
   6776                         mTimerPartial.detach();
   6777                         mTimerPartial = null;
   6778                     }
   6779                     if (mTimerWindow != null) {
   6780                         mTimerWindow.detach();
   6781                         mTimerWindow = null;
   6782                     }
   6783                     if (mTimerDraw != null) {
   6784                         mTimerDraw.detach();
   6785                         mTimerDraw = null;
   6786                     }
   6787                 }
   6788                 return !wlactive;
   6789             }
   6790 
   6791             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
   6792                 mTimerPartial = readDurationTimerFromParcel(WAKE_TYPE_PARTIAL,
   6793                         mBsi.mPartialTimers, screenOffTimeBase, in);
   6794                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
   6795                         mBsi.mFullTimers, timeBase, in);
   6796                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
   6797                         mBsi.mWindowTimers, timeBase, in);
   6798                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
   6799                         mBsi.mDrawTimers, timeBase, in);
   6800             }
   6801 
   6802             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
   6803                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
   6804                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
   6805                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
   6806                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
   6807             }
   6808 
   6809             @Override
   6810             public Timer getWakeTime(int type) {
   6811                 switch (type) {
   6812                 case WAKE_TYPE_FULL: return mTimerFull;
   6813                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
   6814                 case WAKE_TYPE_WINDOW: return mTimerWindow;
   6815                 case WAKE_TYPE_DRAW: return mTimerDraw;
   6816                 default: throw new IllegalArgumentException("type = " + type);
   6817                 }
   6818             }
   6819 
   6820             public StopwatchTimer getStopwatchTimer(int type) {
   6821                 switch (type) {
   6822                     case WAKE_TYPE_PARTIAL: {
   6823                         DurationTimer t = mTimerPartial;
   6824                         if (t == null) {
   6825                             t = new DurationTimer(mBsi.mClocks, mUid, WAKE_TYPE_PARTIAL,
   6826                                     mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase);
   6827                             mTimerPartial = t;
   6828                         }
   6829                         return t;
   6830                     }
   6831                     case WAKE_TYPE_FULL: {
   6832                         StopwatchTimer t = mTimerFull;
   6833                         if (t == null) {
   6834                             t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_FULL,
   6835                                     mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
   6836                             mTimerFull = t;
   6837                         }
   6838                         return t;
   6839                     }
   6840                     case WAKE_TYPE_WINDOW: {
   6841                         StopwatchTimer t = mTimerWindow;
   6842                         if (t == null) {
   6843                             t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_WINDOW,
   6844                                     mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
   6845                             mTimerWindow = t;
   6846                         }
   6847                         return t;
   6848                     }
   6849                     case WAKE_TYPE_DRAW: {
   6850                         StopwatchTimer t = mTimerDraw;
   6851                         if (t == null) {
   6852                             t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_DRAW,
   6853                                     mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
   6854                             mTimerDraw = t;
   6855                         }
   6856                         return t;
   6857                     }
   6858                     default:
   6859                         throw new IllegalArgumentException("type=" + type);
   6860                 }
   6861             }
   6862         }
   6863 
   6864         public static class Sensor extends BatteryStats.Uid.Sensor {
   6865             /**
   6866              * BatteryStatsImpl that we are associated with.
   6867              */
   6868             protected BatteryStatsImpl mBsi;
   6869 
   6870             /**
   6871              * BatteryStatsImpl that we are associated with.
   6872              */
   6873             protected Uid mUid;
   6874 
   6875             final int mHandle;
   6876             StopwatchTimer mTimer;
   6877 
   6878             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
   6879                 mBsi = bsi;
   6880                 mUid = uid;
   6881                 mHandle = handle;
   6882             }
   6883 
   6884             private StopwatchTimer readTimerFromParcel(TimeBase timeBase, Parcel in) {
   6885                 if (in.readInt() == 0) {
   6886                     return null;
   6887                 }
   6888 
   6889                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
   6890                 if (pool == null) {
   6891                     pool = new ArrayList<StopwatchTimer>();
   6892                     mBsi.mSensorTimers.put(mHandle, pool);
   6893                 }
   6894                 return new StopwatchTimer(mBsi.mClocks, mUid, 0, pool, timeBase, in);
   6895             }
   6896 
   6897             boolean reset() {
   6898                 if (mTimer.reset(true)) {
   6899                     mTimer = null;
   6900                     return true;
   6901                 }
   6902                 return false;
   6903             }
   6904 
   6905             void readFromParcelLocked(TimeBase timeBase, Parcel in) {
   6906                 mTimer = readTimerFromParcel(timeBase, in);
   6907             }
   6908 
   6909             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
   6910                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
   6911             }
   6912 
   6913             @Override
   6914             public Timer getSensorTime() {
   6915                 return mTimer;
   6916             }
   6917 
   6918             @Override
   6919             public int getHandle() {
   6920                 return mHandle;
   6921             }
   6922         }
   6923 
   6924         /**
   6925          * The statistics associated with a particular process.
   6926          */
   6927         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
   6928             /**
   6929              * BatteryStatsImpl that we are associated with.
   6930              */
   6931             protected BatteryStatsImpl mBsi;
   6932 
   6933             /**
   6934              * The name of this process.
   6935              */
   6936             final String mName;
   6937 
   6938             /**
   6939              * Remains true until removed from the stats.
   6940              */
   6941             boolean mActive = true;
   6942 
   6943             /**
   6944              * Total time (in ms) spent executing in user code.
   6945              */
   6946             long mUserTime;
   6947 
   6948             /**
   6949              * Total time (in ms) spent executing in kernel code.
   6950              */
   6951             long mSystemTime;
   6952 
   6953             /**
   6954              * Amount of time (in ms) the process was running in the foreground.
   6955              */
   6956             long mForegroundTime;
   6957 
   6958             /**
   6959              * Number of times the process has been started.
   6960              */
   6961             int mStarts;
   6962 
   6963             /**
   6964              * Number of times the process has crashed.
   6965              */
   6966             int mNumCrashes;
   6967 
   6968             /**
   6969              * Number of times the process has had an ANR.
   6970              */
   6971             int mNumAnrs;
   6972 
   6973             /**
   6974              * The amount of user time loaded from a previous save.
   6975              */
   6976             long mLoadedUserTime;
   6977 
   6978             /**
   6979              * The amount of system time loaded from a previous save.
   6980              */
   6981             long mLoadedSystemTime;
   6982 
   6983             /**
   6984              * The amount of foreground time loaded from a previous save.
   6985              */
   6986             long mLoadedForegroundTime;
   6987 
   6988             /**
   6989              * The number of times the process has started from a previous save.
   6990              */
   6991             int mLoadedStarts;
   6992 
   6993             /**
   6994              * Number of times the process has crashed from a previous save.
   6995              */
   6996             int mLoadedNumCrashes;
   6997 
   6998             /**
   6999              * Number of times the process has had an ANR from a previous save.
   7000              */
   7001             int mLoadedNumAnrs;
   7002 
   7003             /**
   7004              * The amount of user time when last unplugged.
   7005              */
   7006             long mUnpluggedUserTime;
   7007 
   7008             /**
   7009              * The amount of system time when last unplugged.
   7010              */
   7011             long mUnpluggedSystemTime;
   7012 
   7013             /**
   7014              * The amount of foreground time since unplugged.
   7015              */
   7016             long mUnpluggedForegroundTime;
   7017 
   7018             /**
   7019              * The number of times the process has started before unplugged.
   7020              */
   7021             int mUnpluggedStarts;
   7022 
   7023             /**
   7024              * Number of times the process has crashed before unplugged.
   7025              */
   7026             int mUnpluggedNumCrashes;
   7027 
   7028             /**
   7029              * Number of times the process has had an ANR before unplugged.
   7030              */
   7031             int mUnpluggedNumAnrs;
   7032 
   7033             ArrayList<ExcessivePower> mExcessivePower;
   7034 
   7035             public Proc(BatteryStatsImpl bsi, String name) {
   7036                 mBsi = bsi;
   7037                 mName = name;
   7038                 mBsi.mOnBatteryTimeBase.add(this);
   7039             }
   7040 
   7041             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   7042                 mUnpluggedUserTime = mUserTime;
   7043                 mUnpluggedSystemTime = mSystemTime;
   7044                 mUnpluggedForegroundTime = mForegroundTime;
   7045                 mUnpluggedStarts = mStarts;
   7046                 mUnpluggedNumCrashes = mNumCrashes;
   7047                 mUnpluggedNumAnrs = mNumAnrs;
   7048             }
   7049 
   7050             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   7051             }
   7052 
   7053             void detach() {
   7054                 mActive = false;
   7055                 mBsi.mOnBatteryTimeBase.remove(this);
   7056             }
   7057 
   7058             public int countExcessivePowers() {
   7059                 return mExcessivePower != null ? mExcessivePower.size() : 0;
   7060             }
   7061 
   7062             public ExcessivePower getExcessivePower(int i) {
   7063                 if (mExcessivePower != null) {
   7064                     return mExcessivePower.get(i);
   7065                 }
   7066                 return null;
   7067             }
   7068 
   7069             public void addExcessiveWake(long overTime, long usedTime) {
   7070                 if (mExcessivePower == null) {
   7071                     mExcessivePower = new ArrayList<ExcessivePower>();
   7072                 }
   7073                 ExcessivePower ew = new ExcessivePower();
   7074                 ew.type = ExcessivePower.TYPE_WAKE;
   7075                 ew.overTime = overTime;
   7076                 ew.usedTime = usedTime;
   7077                 mExcessivePower.add(ew);
   7078             }
   7079 
   7080             public void addExcessiveCpu(long overTime, long usedTime) {
   7081                 if (mExcessivePower == null) {
   7082                     mExcessivePower = new ArrayList<ExcessivePower>();
   7083                 }
   7084                 ExcessivePower ew = new ExcessivePower();
   7085                 ew.type = ExcessivePower.TYPE_CPU;
   7086                 ew.overTime = overTime;
   7087                 ew.usedTime = usedTime;
   7088                 mExcessivePower.add(ew);
   7089             }
   7090 
   7091             void writeExcessivePowerToParcelLocked(Parcel out) {
   7092                 if (mExcessivePower == null) {
   7093                     out.writeInt(0);
   7094                     return;
   7095                 }
   7096 
   7097                 final int N = mExcessivePower.size();
   7098                 out.writeInt(N);
   7099                 for (int i=0; i<N; i++) {
   7100                     ExcessivePower ew = mExcessivePower.get(i);
   7101                     out.writeInt(ew.type);
   7102                     out.writeLong(ew.overTime);
   7103                     out.writeLong(ew.usedTime);
   7104                 }
   7105             }
   7106 
   7107             void readExcessivePowerFromParcelLocked(Parcel in) {
   7108                 final int N = in.readInt();
   7109                 if (N == 0) {
   7110                     mExcessivePower = null;
   7111                     return;
   7112                 }
   7113 
   7114                 if (N > 10000) {
   7115                     throw new ParcelFormatException(
   7116                             "File corrupt: too many excessive power entries " + N);
   7117                 }
   7118 
   7119                 mExcessivePower = new ArrayList<>();
   7120                 for (int i=0; i<N; i++) {
   7121                     ExcessivePower ew = new ExcessivePower();
   7122                     ew.type = in.readInt();
   7123                     ew.overTime = in.readLong();
   7124                     ew.usedTime = in.readLong();
   7125                     mExcessivePower.add(ew);
   7126                 }
   7127             }
   7128 
   7129             void writeToParcelLocked(Parcel out) {
   7130                 out.writeLong(mUserTime);
   7131                 out.writeLong(mSystemTime);
   7132                 out.writeLong(mForegroundTime);
   7133                 out.writeInt(mStarts);
   7134                 out.writeInt(mNumCrashes);
   7135                 out.writeInt(mNumAnrs);
   7136                 out.writeLong(mLoadedUserTime);
   7137                 out.writeLong(mLoadedSystemTime);
   7138                 out.writeLong(mLoadedForegroundTime);
   7139                 out.writeInt(mLoadedStarts);
   7140                 out.writeInt(mLoadedNumCrashes);
   7141                 out.writeInt(mLoadedNumAnrs);
   7142                 out.writeLong(mUnpluggedUserTime);
   7143                 out.writeLong(mUnpluggedSystemTime);
   7144                 out.writeLong(mUnpluggedForegroundTime);
   7145                 out.writeInt(mUnpluggedStarts);
   7146                 out.writeInt(mUnpluggedNumCrashes);
   7147                 out.writeInt(mUnpluggedNumAnrs);
   7148                 writeExcessivePowerToParcelLocked(out);
   7149             }
   7150 
   7151             void readFromParcelLocked(Parcel in) {
   7152                 mUserTime = in.readLong();
   7153                 mSystemTime = in.readLong();
   7154                 mForegroundTime = in.readLong();
   7155                 mStarts = in.readInt();
   7156                 mNumCrashes = in.readInt();
   7157                 mNumAnrs = in.readInt();
   7158                 mLoadedUserTime = in.readLong();
   7159                 mLoadedSystemTime = in.readLong();
   7160                 mLoadedForegroundTime = in.readLong();
   7161                 mLoadedStarts = in.readInt();
   7162                 mLoadedNumCrashes = in.readInt();
   7163                 mLoadedNumAnrs = in.readInt();
   7164                 mUnpluggedUserTime = in.readLong();
   7165                 mUnpluggedSystemTime = in.readLong();
   7166                 mUnpluggedForegroundTime = in.readLong();
   7167                 mUnpluggedStarts = in.readInt();
   7168                 mUnpluggedNumCrashes = in.readInt();
   7169                 mUnpluggedNumAnrs = in.readInt();
   7170                 readExcessivePowerFromParcelLocked(in);
   7171             }
   7172 
   7173             public void addCpuTimeLocked(int utime, int stime) {
   7174                 mUserTime += utime;
   7175                 mSystemTime += stime;
   7176             }
   7177 
   7178             public void addForegroundTimeLocked(long ttime) {
   7179                 mForegroundTime += ttime;
   7180             }
   7181 
   7182             public void incStartsLocked() {
   7183                 mStarts++;
   7184             }
   7185 
   7186             public void incNumCrashesLocked() {
   7187                 mNumCrashes++;
   7188             }
   7189 
   7190             public void incNumAnrsLocked() {
   7191                 mNumAnrs++;
   7192             }
   7193 
   7194             @Override
   7195             public boolean isActive() {
   7196                 return mActive;
   7197             }
   7198 
   7199             @Override
   7200             public long getUserTime(int which) {
   7201                 long val = mUserTime;
   7202                 if (which == STATS_CURRENT) {
   7203                     val -= mLoadedUserTime;
   7204                 } else if (which == STATS_SINCE_UNPLUGGED) {
   7205                     val -= mUnpluggedUserTime;
   7206                 }
   7207                 return val;
   7208             }
   7209 
   7210             @Override
   7211             public long getSystemTime(int which) {
   7212                 long val = mSystemTime;
   7213                 if (which == STATS_CURRENT) {
   7214                     val -= mLoadedSystemTime;
   7215                 } else if (which == STATS_SINCE_UNPLUGGED) {
   7216                     val -= mUnpluggedSystemTime;
   7217                 }
   7218                 return val;
   7219             }
   7220 
   7221             @Override
   7222             public long getForegroundTime(int which) {
   7223                 long val = mForegroundTime;
   7224                 if (which == STATS_CURRENT) {
   7225                     val -= mLoadedForegroundTime;
   7226                 } else if (which == STATS_SINCE_UNPLUGGED) {
   7227                     val -= mUnpluggedForegroundTime;
   7228                 }
   7229                 return val;
   7230             }
   7231 
   7232             @Override
   7233             public int getStarts(int which) {
   7234                 int val = mStarts;
   7235                 if (which == STATS_CURRENT) {
   7236                     val -= mLoadedStarts;
   7237                 } else if (which == STATS_SINCE_UNPLUGGED) {
   7238                     val -= mUnpluggedStarts;
   7239                 }
   7240                 return val;
   7241             }
   7242 
   7243             @Override
   7244             public int getNumCrashes(int which) {
   7245                 int val = mNumCrashes;
   7246                 if (which == STATS_CURRENT) {
   7247                     val -= mLoadedNumCrashes;
   7248                 } else if (which == STATS_SINCE_UNPLUGGED) {
   7249                     val -= mUnpluggedNumCrashes;
   7250                 }
   7251                 return val;
   7252             }
   7253 
   7254             @Override
   7255             public int getNumAnrs(int which) {
   7256                 int val = mNumAnrs;
   7257                 if (which == STATS_CURRENT) {
   7258                     val -= mLoadedNumAnrs;
   7259                 } else if (which == STATS_SINCE_UNPLUGGED) {
   7260                     val -= mUnpluggedNumAnrs;
   7261                 }
   7262                 return val;
   7263             }
   7264         }
   7265 
   7266         /**
   7267          * The statistics associated with a particular package.
   7268          */
   7269         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
   7270             /**
   7271              * BatteryStatsImpl that we are associated with.
   7272              */
   7273             protected BatteryStatsImpl mBsi;
   7274 
   7275             /**
   7276              * Number of times wakeup alarms have occurred for this app.
   7277              */
   7278             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
   7279 
   7280             /**
   7281              * The statics we have collected for this package's services.
   7282              */
   7283             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
   7284 
   7285             public Pkg(BatteryStatsImpl bsi) {
   7286                 mBsi = bsi;
   7287                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
   7288             }
   7289 
   7290             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   7291             }
   7292 
   7293             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   7294             }
   7295 
   7296             void detach() {
   7297                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
   7298             }
   7299 
   7300             void readFromParcelLocked(Parcel in) {
   7301                 int numWA = in.readInt();
   7302                 mWakeupAlarms.clear();
   7303                 for (int i=0; i<numWA; i++) {
   7304                     String tag = in.readString();
   7305                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryTimeBase, in));
   7306                 }
   7307 
   7308                 int numServs = in.readInt();
   7309                 mServiceStats.clear();
   7310                 for (int m = 0; m < numServs; m++) {
   7311                     String serviceName = in.readString();
   7312                     Uid.Pkg.Serv serv = new Serv(mBsi);
   7313                     mServiceStats.put(serviceName, serv);
   7314 
   7315                     serv.readFromParcelLocked(in);
   7316                 }
   7317             }
   7318 
   7319             void writeToParcelLocked(Parcel out) {
   7320                 int numWA = mWakeupAlarms.size();
   7321                 out.writeInt(numWA);
   7322                 for (int i=0; i<numWA; i++) {
   7323                     out.writeString(mWakeupAlarms.keyAt(i));
   7324                     mWakeupAlarms.valueAt(i).writeToParcel(out);
   7325                 }
   7326 
   7327                 final int NS = mServiceStats.size();
   7328                 out.writeInt(NS);
   7329                 for (int i=0; i<NS; i++) {
   7330                     out.writeString(mServiceStats.keyAt(i));
   7331                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
   7332                     serv.writeToParcelLocked(out);
   7333                 }
   7334             }
   7335 
   7336             @Override
   7337             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
   7338                 return mWakeupAlarms;
   7339             }
   7340 
   7341             public void noteWakeupAlarmLocked(String tag) {
   7342                 Counter c = mWakeupAlarms.get(tag);
   7343                 if (c == null) {
   7344                     c = new Counter(mBsi.mOnBatteryTimeBase);
   7345                     mWakeupAlarms.put(tag, c);
   7346                 }
   7347                 c.stepAtomic();
   7348             }
   7349 
   7350             @Override
   7351             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
   7352                 return mServiceStats;
   7353             }
   7354 
   7355             /**
   7356              * The statistics associated with a particular service.
   7357              */
   7358             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
   7359                 /**
   7360                  * BatteryStatsImpl that we are associated with.
   7361                  */
   7362                 protected BatteryStatsImpl mBsi;
   7363 
   7364                 /**
   7365                  * The android package in which this service resides.
   7366                  */
   7367                 protected Pkg mPkg;
   7368 
   7369                 /**
   7370                  * Total time (ms in battery uptime) the service has been left started.
   7371                  */
   7372                 protected long mStartTime;
   7373 
   7374                 /**
   7375                  * If service has been started and not yet stopped, this is
   7376                  * when it was started.
   7377                  */
   7378                 protected long mRunningSince;
   7379 
   7380                 /**
   7381                  * True if we are currently running.
   7382                  */
   7383                 protected boolean mRunning;
   7384 
   7385                 /**
   7386                  * Total number of times startService() has been called.
   7387                  */
   7388                 protected int mStarts;
   7389 
   7390                 /**
   7391                  * Total time (ms in battery uptime) the service has been left launched.
   7392                  */
   7393                 protected long mLaunchedTime;
   7394 
   7395                 /**
   7396                  * If service has been launched and not yet exited, this is
   7397                  * when it was launched (ms in battery uptime).
   7398                  */
   7399                 protected long mLaunchedSince;
   7400 
   7401                 /**
   7402                  * True if we are currently launched.
   7403                  */
   7404                 protected boolean mLaunched;
   7405 
   7406                 /**
   7407                  * Total number times the service has been launched.
   7408                  */
   7409                 protected int mLaunches;
   7410 
   7411                 /**
   7412                  * The amount of time spent started loaded from a previous save
   7413                  * (ms in battery uptime).
   7414                  */
   7415                 protected long mLoadedStartTime;
   7416 
   7417                 /**
   7418                  * The number of starts loaded from a previous save.
   7419                  */
   7420                 protected int mLoadedStarts;
   7421 
   7422                 /**
   7423                  * The number of launches loaded from a previous save.
   7424                  */
   7425                 protected int mLoadedLaunches;
   7426 
   7427                 /**
   7428                  * The amount of time spent started as of the last run (ms
   7429                  * in battery uptime).
   7430                  */
   7431                 protected long mLastStartTime;
   7432 
   7433                 /**
   7434                  * The number of starts as of the last run.
   7435                  */
   7436                 protected int mLastStarts;
   7437 
   7438                 /**
   7439                  * The number of launches as of the last run.
   7440                  */
   7441                 protected int mLastLaunches;
   7442 
   7443                 /**
   7444                  * The amount of time spent started when last unplugged (ms
   7445                  * in battery uptime).
   7446                  */
   7447                 protected long mUnpluggedStartTime;
   7448 
   7449                 /**
   7450                  * The number of starts when last unplugged.
   7451                  */
   7452                 protected int mUnpluggedStarts;
   7453 
   7454                 /**
   7455                  * The number of launches when last unplugged.
   7456                  */
   7457                 protected int mUnpluggedLaunches;
   7458 
   7459                 /**
   7460                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
   7461                  */
   7462                 public Serv(BatteryStatsImpl bsi) {
   7463                     mBsi = bsi;
   7464                     mBsi.mOnBatteryTimeBase.add(this);
   7465                 }
   7466 
   7467                 public void onTimeStarted(long elapsedRealtime, long baseUptime,
   7468                         long baseRealtime) {
   7469                     mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
   7470                     mUnpluggedStarts = mStarts;
   7471                     mUnpluggedLaunches = mLaunches;
   7472                 }
   7473 
   7474                 public void onTimeStopped(long elapsedRealtime, long baseUptime,
   7475                         long baseRealtime) {
   7476                 }
   7477 
   7478                 /**
   7479                  * Remove this Serv as a listener from the time base.
   7480                  */
   7481                 public void detach() {
   7482                     mBsi.mOnBatteryTimeBase.remove(this);
   7483                 }
   7484 
   7485                 public void readFromParcelLocked(Parcel in) {
   7486                     mStartTime = in.readLong();
   7487                     mRunningSince = in.readLong();
   7488                     mRunning = in.readInt() != 0;
   7489                     mStarts = in.readInt();
   7490                     mLaunchedTime = in.readLong();
   7491                     mLaunchedSince = in.readLong();
   7492                     mLaunched = in.readInt() != 0;
   7493                     mLaunches = in.readInt();
   7494                     mLoadedStartTime = in.readLong();
   7495                     mLoadedStarts = in.readInt();
   7496                     mLoadedLaunches = in.readInt();
   7497                     mLastStartTime = 0;
   7498                     mLastStarts = 0;
   7499                     mLastLaunches = 0;
   7500                     mUnpluggedStartTime = in.readLong();
   7501                     mUnpluggedStarts = in.readInt();
   7502                     mUnpluggedLaunches = in.readInt();
   7503                 }
   7504 
   7505                 public void writeToParcelLocked(Parcel out) {
   7506                     out.writeLong(mStartTime);
   7507                     out.writeLong(mRunningSince);
   7508                     out.writeInt(mRunning ? 1 : 0);
   7509                     out.writeInt(mStarts);
   7510                     out.writeLong(mLaunchedTime);
   7511                     out.writeLong(mLaunchedSince);
   7512                     out.writeInt(mLaunched ? 1 : 0);
   7513                     out.writeInt(mLaunches);
   7514                     out.writeLong(mLoadedStartTime);
   7515                     out.writeInt(mLoadedStarts);
   7516                     out.writeInt(mLoadedLaunches);
   7517                     out.writeLong(mUnpluggedStartTime);
   7518                     out.writeInt(mUnpluggedStarts);
   7519                     out.writeInt(mUnpluggedLaunches);
   7520                 }
   7521 
   7522                 public long getLaunchTimeToNowLocked(long batteryUptime) {
   7523                     if (!mLaunched) return mLaunchedTime;
   7524                     return mLaunchedTime + batteryUptime - mLaunchedSince;
   7525                 }
   7526 
   7527                 public long getStartTimeToNowLocked(long batteryUptime) {
   7528                     if (!mRunning) return mStartTime;
   7529                     return mStartTime + batteryUptime - mRunningSince;
   7530                 }
   7531 
   7532                 public void startLaunchedLocked() {
   7533                     if (!mLaunched) {
   7534                         mLaunches++;
   7535                         mLaunchedSince = mBsi.getBatteryUptimeLocked();
   7536                         mLaunched = true;
   7537                     }
   7538                 }
   7539 
   7540                 public void stopLaunchedLocked() {
   7541                     if (mLaunched) {
   7542                         long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
   7543                         if (time > 0) {
   7544                             mLaunchedTime += time;
   7545                         } else {
   7546                             mLaunches--;
   7547                         }
   7548                         mLaunched = false;
   7549                     }
   7550                 }
   7551 
   7552                 public void startRunningLocked() {
   7553                     if (!mRunning) {
   7554                         mStarts++;
   7555                         mRunningSince = mBsi.getBatteryUptimeLocked();
   7556                         mRunning = true;
   7557                     }
   7558                 }
   7559 
   7560                 public void stopRunningLocked() {
   7561                     if (mRunning) {
   7562                         long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
   7563                         if (time > 0) {
   7564                             mStartTime += time;
   7565                         } else {
   7566                             mStarts--;
   7567                         }
   7568                         mRunning = false;
   7569                     }
   7570                 }
   7571 
   7572                 public BatteryStatsImpl getBatteryStats() {
   7573                     return mBsi;
   7574                 }
   7575 
   7576                 @Override
   7577                 public int getLaunches(int which) {
   7578                     int val = mLaunches;
   7579                     if (which == STATS_CURRENT) {
   7580                         val -= mLoadedLaunches;
   7581                     } else if (which == STATS_SINCE_UNPLUGGED) {
   7582                         val -= mUnpluggedLaunches;
   7583                     }
   7584                     return val;
   7585                 }
   7586 
   7587                 @Override
   7588                 public long getStartTime(long now, int which) {
   7589                     long val = getStartTimeToNowLocked(now);
   7590                     if (which == STATS_CURRENT) {
   7591                         val -= mLoadedStartTime;
   7592                     } else if (which == STATS_SINCE_UNPLUGGED) {
   7593                         val -= mUnpluggedStartTime;
   7594                     }
   7595                     return val;
   7596                 }
   7597 
   7598                 @Override
   7599                 public int getStarts(int which) {
   7600                     int val = mStarts;
   7601                     if (which == STATS_CURRENT) {
   7602                         val -= mLoadedStarts;
   7603                     } else if (which == STATS_SINCE_UNPLUGGED) {
   7604                         val -= mUnpluggedStarts;
   7605                     }
   7606 
   7607                     return val;
   7608                 }
   7609             }
   7610 
   7611             final Serv newServiceStatsLocked() {
   7612                 return new Serv(mBsi);
   7613             }
   7614         }
   7615 
   7616         /**
   7617          * Retrieve the statistics object for a particular process, creating
   7618          * if needed.
   7619          */
   7620         public Proc getProcessStatsLocked(String name) {
   7621             Proc ps = mProcessStats.get(name);
   7622             if (ps == null) {
   7623                 ps = new Proc(mBsi, name);
   7624                 mProcessStats.put(name, ps);
   7625             }
   7626 
   7627             return ps;
   7628         }
   7629 
   7630         public void updateUidProcessStateLocked(int procState) {
   7631             int uidRunningState;
   7632             if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
   7633                 uidRunningState = ActivityManager.PROCESS_STATE_NONEXISTENT;
   7634             } else if (procState == ActivityManager.PROCESS_STATE_TOP) {
   7635                 uidRunningState = PROCESS_STATE_TOP;
   7636             } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
   7637                 // Persistent and other foreground states go here.
   7638                 uidRunningState = PROCESS_STATE_FOREGROUND_SERVICE;
   7639             } else if (procState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
   7640                 uidRunningState = PROCESS_STATE_TOP_SLEEPING;
   7641             } else if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
   7642                 // Persistent and other foreground states go here.
   7643                 uidRunningState = PROCESS_STATE_FOREGROUND;
   7644             } else if (procState <= ActivityManager.PROCESS_STATE_RECEIVER) {
   7645                 uidRunningState = PROCESS_STATE_BACKGROUND;
   7646             } else {
   7647                 uidRunningState = PROCESS_STATE_CACHED;
   7648             }
   7649 
   7650             if (mProcessState == uidRunningState) return;
   7651 
   7652             final long elapsedRealtime = mBsi.mClocks.elapsedRealtime();
   7653 
   7654             if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
   7655                 mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtime);
   7656             }
   7657             mProcessState = uidRunningState;
   7658             if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
   7659                 if (mProcessStateTimer[uidRunningState] == null) {
   7660                     makeProcessState(uidRunningState, null);
   7661                 }
   7662                 mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtime);
   7663             }
   7664         }
   7665 
   7666         public SparseArray<? extends Pid> getPidStats() {
   7667             return mPids;
   7668         }
   7669 
   7670         public Pid getPidStatsLocked(int pid) {
   7671             Pid p = mPids.get(pid);
   7672             if (p == null) {
   7673                 p = new Pid();
   7674                 mPids.put(pid, p);
   7675             }
   7676             return p;
   7677         }
   7678 
   7679         /**
   7680          * Retrieve the statistics object for a particular service, creating
   7681          * if needed.
   7682          */
   7683         public Pkg getPackageStatsLocked(String name) {
   7684             Pkg ps = mPackageStats.get(name);
   7685             if (ps == null) {
   7686                 ps = new Pkg(mBsi);
   7687                 mPackageStats.put(name, ps);
   7688             }
   7689 
   7690             return ps;
   7691         }
   7692 
   7693         /**
   7694          * Retrieve the statistics object for a particular service, creating
   7695          * if needed.
   7696          */
   7697         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
   7698             Pkg ps = getPackageStatsLocked(pkg);
   7699             Pkg.Serv ss = ps.mServiceStats.get(serv);
   7700             if (ss == null) {
   7701                 ss = ps.newServiceStatsLocked();
   7702                 ps.mServiceStats.put(serv, ss);
   7703             }
   7704 
   7705             return ss;
   7706         }
   7707 
   7708         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
   7709             StopwatchTimer timer = mSyncStats.instantiateObject();
   7710             timer.readSummaryFromParcelLocked(in);
   7711             mSyncStats.add(name, timer);
   7712         }
   7713 
   7714         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
   7715             StopwatchTimer timer = mJobStats.instantiateObject();
   7716             timer.readSummaryFromParcelLocked(in);
   7717             mJobStats.add(name, timer);
   7718         }
   7719 
   7720         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
   7721             Wakelock wl = new Wakelock(mBsi, this);
   7722             mWakelockStats.add(wlName, wl);
   7723             if (in.readInt() != 0) {
   7724                 wl.getStopwatchTimer(WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
   7725             }
   7726             if (in.readInt() != 0) {
   7727                 wl.getStopwatchTimer(WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
   7728             }
   7729             if (in.readInt() != 0) {
   7730                 wl.getStopwatchTimer(WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
   7731             }
   7732             if (in.readInt() != 0) {
   7733                 wl.getStopwatchTimer(WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
   7734             }
   7735         }
   7736 
   7737         public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
   7738             Sensor se = mSensorStats.get(sensor);
   7739             if (se == null) {
   7740                 if (!create) {
   7741                     return null;
   7742                 }
   7743                 se = new Sensor(mBsi, this, sensor);
   7744                 mSensorStats.put(sensor, se);
   7745             }
   7746             StopwatchTimer t = se.mTimer;
   7747             if (t != null) {
   7748                 return t;
   7749             }
   7750             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
   7751             if (timers == null) {
   7752                 timers = new ArrayList<StopwatchTimer>();
   7753                 mBsi.mSensorTimers.put(sensor, timers);
   7754             }
   7755             t = new StopwatchTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
   7756                     mBsi.mOnBatteryTimeBase);
   7757             se.mTimer = t;
   7758             return t;
   7759         }
   7760 
   7761         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
   7762             StopwatchTimer t = mSyncStats.startObject(name);
   7763             if (t != null) {
   7764                 t.startRunningLocked(elapsedRealtimeMs);
   7765             }
   7766         }
   7767 
   7768         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
   7769             StopwatchTimer t = mSyncStats.stopObject(name);
   7770             if (t != null) {
   7771                 t.stopRunningLocked(elapsedRealtimeMs);
   7772             }
   7773         }
   7774 
   7775         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
   7776             StopwatchTimer t = mJobStats.startObject(name);
   7777             if (t != null) {
   7778                 t.startRunningLocked(elapsedRealtimeMs);
   7779             }
   7780         }
   7781 
   7782         public void noteStopJobLocked(String name, long elapsedRealtimeMs) {
   7783             StopwatchTimer t = mJobStats.stopObject(name);
   7784             if (t != null) {
   7785                 t.stopRunningLocked(elapsedRealtimeMs);
   7786             }
   7787         }
   7788 
   7789         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
   7790             Wakelock wl = mWakelockStats.startObject(name);
   7791             if (wl != null) {
   7792                 wl.getStopwatchTimer(type).startRunningLocked(elapsedRealtimeMs);
   7793             }
   7794             if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
   7795                 Pid p = getPidStatsLocked(pid);
   7796                 if (p.mWakeNesting++ == 0) {
   7797                     p.mWakeStartMs = elapsedRealtimeMs;
   7798                 }
   7799             }
   7800         }
   7801 
   7802         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
   7803             Wakelock wl = mWakelockStats.stopObject(name);
   7804             if (wl != null) {
   7805                 wl.getStopwatchTimer(type).stopRunningLocked(elapsedRealtimeMs);
   7806             }
   7807             if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
   7808                 Pid p = mPids.get(pid);
   7809                 if (p != null && p.mWakeNesting > 0) {
   7810                     if (p.mWakeNesting-- == 1) {
   7811                         p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
   7812                         p.mWakeStartMs = 0;
   7813                     }
   7814                 }
   7815             }
   7816         }
   7817 
   7818         public void reportExcessiveWakeLocked(String proc, long overTime, long usedTime) {
   7819             Proc p = getProcessStatsLocked(proc);
   7820             if (p != null) {
   7821                 p.addExcessiveWake(overTime, usedTime);
   7822             }
   7823         }
   7824 
   7825         public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
   7826             Proc p = getProcessStatsLocked(proc);
   7827             if (p != null) {
   7828                 p.addExcessiveCpu(overTime, usedTime);
   7829             }
   7830         }
   7831 
   7832         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
   7833             StopwatchTimer t = getSensorTimerLocked(sensor, true);
   7834             if (t != null) {
   7835                 t.startRunningLocked(elapsedRealtimeMs);
   7836             }
   7837         }
   7838 
   7839         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
   7840             // Don't create a timer if one doesn't already exist
   7841             StopwatchTimer t = getSensorTimerLocked(sensor, false);
   7842             if (t != null) {
   7843                 t.stopRunningLocked(elapsedRealtimeMs);
   7844             }
   7845         }
   7846 
   7847         public void noteStartGps(long elapsedRealtimeMs) {
   7848             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
   7849             if (t != null) {
   7850                 t.startRunningLocked(elapsedRealtimeMs);
   7851             }
   7852         }
   7853 
   7854         public void noteStopGps(long elapsedRealtimeMs) {
   7855             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
   7856             if (t != null) {
   7857                 t.stopRunningLocked(elapsedRealtimeMs);
   7858             }
   7859         }
   7860 
   7861         public BatteryStatsImpl getBatteryStats() {
   7862             return mBsi;
   7863         }
   7864     }
   7865 
   7866     public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
   7867         this(new SystemClocks(), systemDir, handler, externalSync, null);
   7868     }
   7869 
   7870     public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync,
   7871                             PlatformIdleStateCallback cb) {
   7872         this(new SystemClocks(), systemDir, handler, externalSync, cb);
   7873     }
   7874 
   7875     public BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
   7876             ExternalStatsSync externalSync, PlatformIdleStateCallback cb) {
   7877         init(clocks);
   7878 
   7879         if (systemDir != null) {
   7880             mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
   7881                     new File(systemDir, "batterystats.bin.tmp"));
   7882         } else {
   7883             mFile = null;
   7884         }
   7885         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
   7886         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
   7887         mExternalSync = externalSync;
   7888         mHandler = new MyHandler(handler.getLooper());
   7889         mStartCount++;
   7890         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
   7891         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   7892             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
   7893                     mOnBatteryTimeBase);
   7894         }
   7895         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
   7896         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
   7897                 mOnBatteryTimeBase);
   7898         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
   7899                 mOnBatteryTimeBase);
   7900         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
   7901         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
   7902         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
   7903         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
   7904         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   7905             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
   7906                     mOnBatteryTimeBase);
   7907         }
   7908         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
   7909                 mOnBatteryTimeBase);
   7910         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   7911             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
   7912                     mOnBatteryTimeBase);
   7913         }
   7914         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   7915             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
   7916             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
   7917         }
   7918         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
   7919         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
   7920                 NUM_BT_TX_LEVELS);
   7921         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
   7922                 ModemActivityInfo.TX_POWER_LEVELS);
   7923 
   7924         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
   7925         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
   7926                 mOnBatteryTimeBase);
   7927         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
   7928         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
   7929         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
   7930         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
   7931         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
   7932         for (int i=0; i<NUM_WIFI_STATES; i++) {
   7933             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
   7934                     mOnBatteryTimeBase);
   7935         }
   7936         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   7937             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
   7938                     mOnBatteryTimeBase);
   7939         }
   7940         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   7941             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
   7942                     mOnBatteryTimeBase);
   7943         }
   7944         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
   7945         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
   7946         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
   7947         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
   7948         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
   7949         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
   7950         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
   7951         mOnBattery = mOnBatteryInternal = false;
   7952         long uptime = mClocks.uptimeMillis() * 1000;
   7953         long realtime = mClocks.elapsedRealtime() * 1000;
   7954         initTimes(uptime, realtime);
   7955         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
   7956         mDischargeStartLevel = 0;
   7957         mDischargeUnplugLevel = 0;
   7958         mDischargePlugLevel = -1;
   7959         mDischargeCurrentLevel = 0;
   7960         mCurrentBatteryLevel = 0;
   7961         initDischarge();
   7962         clearHistoryLocked();
   7963         updateDailyDeadlineLocked();
   7964         mPlatformIdleStateCallback = cb;
   7965     }
   7966 
   7967     public BatteryStatsImpl(Parcel p) {
   7968         this(new SystemClocks(), p);
   7969     }
   7970 
   7971     public BatteryStatsImpl(Clocks clocks, Parcel p) {
   7972         init(clocks);
   7973         mFile = null;
   7974         mCheckinFile = null;
   7975         mDailyFile = null;
   7976         mHandler = null;
   7977         mExternalSync = null;
   7978         clearHistoryLocked();
   7979         readFromParcel(p);
   7980         mPlatformIdleStateCallback = null;
   7981     }
   7982 
   7983     public void setPowerProfile(PowerProfile profile) {
   7984         synchronized (this) {
   7985             mPowerProfile = profile;
   7986 
   7987             // We need to initialize the KernelCpuSpeedReaders to read from
   7988             // the first cpu of each core. Once we have the PowerProfile, we have access to this
   7989             // information.
   7990             final int numClusters = mPowerProfile.getNumCpuClusters();
   7991             mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
   7992             int firstCpuOfCluster = 0;
   7993             for (int i = 0; i < numClusters; i++) {
   7994                 final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
   7995                 mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
   7996                         numSpeedSteps);
   7997                 firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
   7998             }
   7999 
   8000             if (mEstimatedBatteryCapacity == -1) {
   8001                 // Initialize the estimated battery capacity to a known preset one.
   8002                 mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
   8003             }
   8004         }
   8005     }
   8006 
   8007     public void setCallback(BatteryCallback cb) {
   8008         mCallback = cb;
   8009     }
   8010 
   8011     public void setRadioScanningTimeout(long timeout) {
   8012         if (mPhoneSignalScanningTimer != null) {
   8013             mPhoneSignalScanningTimer.setTimeout(timeout);
   8014         }
   8015     }
   8016 
   8017     public void updateDailyDeadlineLocked() {
   8018         // Get the current time.
   8019         long currentTime = mDailyStartTime = System.currentTimeMillis();
   8020         Calendar calDeadline = Calendar.getInstance();
   8021         calDeadline.setTimeInMillis(currentTime);
   8022 
   8023         // Move time up to the next day, ranging from 1am to 3pm.
   8024         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
   8025         calDeadline.set(Calendar.MILLISECOND, 0);
   8026         calDeadline.set(Calendar.SECOND, 0);
   8027         calDeadline.set(Calendar.MINUTE, 0);
   8028         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
   8029         mNextMinDailyDeadline = calDeadline.getTimeInMillis();
   8030         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
   8031         mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
   8032     }
   8033 
   8034     public void recordDailyStatsIfNeededLocked(boolean settled) {
   8035         long currentTime = System.currentTimeMillis();
   8036         if (currentTime >= mNextMaxDailyDeadline) {
   8037             recordDailyStatsLocked();
   8038         } else if (settled && currentTime >= mNextMinDailyDeadline) {
   8039             recordDailyStatsLocked();
   8040         } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
   8041             recordDailyStatsLocked();
   8042         }
   8043     }
   8044 
   8045     public void recordDailyStatsLocked() {
   8046         DailyItem item = new DailyItem();
   8047         item.mStartTime = mDailyStartTime;
   8048         item.mEndTime = System.currentTimeMillis();
   8049         boolean hasData = false;
   8050         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
   8051             hasData = true;
   8052             item.mDischargeSteps = new LevelStepTracker(
   8053                     mDailyDischargeStepTracker.mNumStepDurations,
   8054                     mDailyDischargeStepTracker.mStepDurations);
   8055         }
   8056         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
   8057             hasData = true;
   8058             item.mChargeSteps = new LevelStepTracker(
   8059                     mDailyChargeStepTracker.mNumStepDurations,
   8060                     mDailyChargeStepTracker.mStepDurations);
   8061         }
   8062         if (mDailyPackageChanges != null) {
   8063             hasData = true;
   8064             item.mPackageChanges = mDailyPackageChanges;
   8065             mDailyPackageChanges = null;
   8066         }
   8067         mDailyDischargeStepTracker.init();
   8068         mDailyChargeStepTracker.init();
   8069         updateDailyDeadlineLocked();
   8070 
   8071         if (hasData) {
   8072             mDailyItems.add(item);
   8073             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
   8074                 mDailyItems.remove(0);
   8075             }
   8076             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
   8077             try {
   8078                 XmlSerializer out = new FastXmlSerializer();
   8079                 out.setOutput(memStream, StandardCharsets.UTF_8.name());
   8080                 writeDailyItemsLocked(out);
   8081                 BackgroundThread.getHandler().post(new Runnable() {
   8082                     @Override
   8083                     public void run() {
   8084                         synchronized (mCheckinFile) {
   8085                             FileOutputStream stream = null;
   8086                             try {
   8087                                 stream = mDailyFile.startWrite();
   8088                                 memStream.writeTo(stream);
   8089                                 stream.flush();
   8090                                 FileUtils.sync(stream);
   8091                                 stream.close();
   8092                                 mDailyFile.finishWrite(stream);
   8093                             } catch (IOException e) {
   8094                                 Slog.w("BatteryStats",
   8095                                         "Error writing battery daily items", e);
   8096                                 mDailyFile.failWrite(stream);
   8097                             }
   8098                         }
   8099                     }
   8100                 });
   8101             } catch (IOException e) {
   8102             }
   8103         }
   8104     }
   8105 
   8106     private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
   8107         StringBuilder sb = new StringBuilder(64);
   8108         out.startDocument(null, true);
   8109         out.startTag(null, "daily-items");
   8110         for (int i=0; i<mDailyItems.size(); i++) {
   8111             final DailyItem dit = mDailyItems.get(i);
   8112             out.startTag(null, "item");
   8113             out.attribute(null, "start", Long.toString(dit.mStartTime));
   8114             out.attribute(null, "end", Long.toString(dit.mEndTime));
   8115             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
   8116             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
   8117             if (dit.mPackageChanges != null) {
   8118                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
   8119                     PackageChange pc = dit.mPackageChanges.get(j);
   8120                     if (pc.mUpdate) {
   8121                         out.startTag(null, "upd");
   8122                         out.attribute(null, "pkg", pc.mPackageName);
   8123                         out.attribute(null, "ver", Integer.toString(pc.mVersionCode));
   8124                         out.endTag(null, "upd");
   8125                     } else {
   8126                         out.startTag(null, "rem");
   8127                         out.attribute(null, "pkg", pc.mPackageName);
   8128                         out.endTag(null, "rem");
   8129                     }
   8130                 }
   8131             }
   8132             out.endTag(null, "item");
   8133         }
   8134         out.endTag(null, "daily-items");
   8135         out.endDocument();
   8136     }
   8137 
   8138     private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
   8139             StringBuilder tmpBuilder) throws IOException {
   8140         if (steps != null) {
   8141             out.startTag(null, tag);
   8142             out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
   8143             for (int i=0; i<steps.mNumStepDurations; i++) {
   8144                 out.startTag(null, "s");
   8145                 tmpBuilder.setLength(0);
   8146                 steps.encodeEntryAt(i, tmpBuilder);
   8147                 out.attribute(null, "v", tmpBuilder.toString());
   8148                 out.endTag(null, "s");
   8149             }
   8150             out.endTag(null, tag);
   8151         }
   8152     }
   8153 
   8154     public void readDailyStatsLocked() {
   8155         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
   8156         mDailyItems.clear();
   8157         FileInputStream stream;
   8158         try {
   8159             stream = mDailyFile.openRead();
   8160         } catch (FileNotFoundException e) {
   8161             return;
   8162         }
   8163         try {
   8164             XmlPullParser parser = Xml.newPullParser();
   8165             parser.setInput(stream, StandardCharsets.UTF_8.name());
   8166             readDailyItemsLocked(parser);
   8167         } catch (XmlPullParserException e) {
   8168         } finally {
   8169             try {
   8170                 stream.close();
   8171             } catch (IOException e) {
   8172             }
   8173         }
   8174     }
   8175 
   8176     private void readDailyItemsLocked(XmlPullParser parser) {
   8177         try {
   8178             int type;
   8179             while ((type = parser.next()) != XmlPullParser.START_TAG
   8180                     && type != XmlPullParser.END_DOCUMENT) {
   8181                 ;
   8182             }
   8183 
   8184             if (type != XmlPullParser.START_TAG) {
   8185                 throw new IllegalStateException("no start tag found");
   8186             }
   8187 
   8188             int outerDepth = parser.getDepth();
   8189             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   8190                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   8191                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   8192                     continue;
   8193                 }
   8194 
   8195                 String tagName = parser.getName();
   8196                 if (tagName.equals("item")) {
   8197                     readDailyItemTagLocked(parser);
   8198                 } else {
   8199                     Slog.w(TAG, "Unknown element under <daily-items>: "
   8200                             + parser.getName());
   8201                     XmlUtils.skipCurrentTag(parser);
   8202                 }
   8203             }
   8204 
   8205         } catch (IllegalStateException e) {
   8206             Slog.w(TAG, "Failed parsing daily " + e);
   8207         } catch (NullPointerException e) {
   8208             Slog.w(TAG, "Failed parsing daily " + e);
   8209         } catch (NumberFormatException e) {
   8210             Slog.w(TAG, "Failed parsing daily " + e);
   8211         } catch (XmlPullParserException e) {
   8212             Slog.w(TAG, "Failed parsing daily " + e);
   8213         } catch (IOException e) {
   8214             Slog.w(TAG, "Failed parsing daily " + e);
   8215         } catch (IndexOutOfBoundsException e) {
   8216             Slog.w(TAG, "Failed parsing daily " + e);
   8217         }
   8218     }
   8219 
   8220     void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
   8221             XmlPullParserException, IOException {
   8222         DailyItem dit = new DailyItem();
   8223         String attr = parser.getAttributeValue(null, "start");
   8224         if (attr != null) {
   8225             dit.mStartTime = Long.parseLong(attr);
   8226         }
   8227         attr = parser.getAttributeValue(null, "end");
   8228         if (attr != null) {
   8229             dit.mEndTime = Long.parseLong(attr);
   8230         }
   8231         int outerDepth = parser.getDepth();
   8232         int type;
   8233         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   8234                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   8235             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   8236                 continue;
   8237             }
   8238 
   8239             String tagName = parser.getName();
   8240             if (tagName.equals("dis")) {
   8241                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
   8242             } else if (tagName.equals("chg")) {
   8243                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
   8244             } else if (tagName.equals("upd")) {
   8245                 if (dit.mPackageChanges == null) {
   8246                     dit.mPackageChanges = new ArrayList<>();
   8247                 }
   8248                 PackageChange pc = new PackageChange();
   8249                 pc.mUpdate = true;
   8250                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
   8251                 String verStr = parser.getAttributeValue(null, "ver");
   8252                 pc.mVersionCode = verStr != null ? Integer.parseInt(verStr) : 0;
   8253                 dit.mPackageChanges.add(pc);
   8254                 XmlUtils.skipCurrentTag(parser);
   8255             } else if (tagName.equals("rem")) {
   8256                 if (dit.mPackageChanges == null) {
   8257                     dit.mPackageChanges = new ArrayList<>();
   8258                 }
   8259                 PackageChange pc = new PackageChange();
   8260                 pc.mUpdate = false;
   8261                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
   8262                 dit.mPackageChanges.add(pc);
   8263                 XmlUtils.skipCurrentTag(parser);
   8264             } else {
   8265                 Slog.w(TAG, "Unknown element under <item>: "
   8266                         + parser.getName());
   8267                 XmlUtils.skipCurrentTag(parser);
   8268             }
   8269         }
   8270         mDailyItems.add(dit);
   8271     }
   8272 
   8273     void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
   8274             String tag)
   8275             throws NumberFormatException, XmlPullParserException, IOException {
   8276         final String numAttr = parser.getAttributeValue(null, "n");
   8277         if (numAttr == null) {
   8278             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
   8279             XmlUtils.skipCurrentTag(parser);
   8280             return;
   8281         }
   8282         final int num = Integer.parseInt(numAttr);
   8283         LevelStepTracker steps = new LevelStepTracker(num);
   8284         if (isCharge) {
   8285             dit.mChargeSteps = steps;
   8286         } else {
   8287             dit.mDischargeSteps = steps;
   8288         }
   8289         int i = 0;
   8290         int outerDepth = parser.getDepth();
   8291         int type;
   8292         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   8293                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   8294             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   8295                 continue;
   8296             }
   8297 
   8298             String tagName = parser.getName();
   8299             if ("s".equals(tagName)) {
   8300                 if (i < num) {
   8301                     String valueAttr = parser.getAttributeValue(null, "v");
   8302                     if (valueAttr != null) {
   8303                         steps.decodeEntryAt(i, valueAttr);
   8304                         i++;
   8305                     }
   8306                 }
   8307             } else {
   8308                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
   8309                         + parser.getName());
   8310                 XmlUtils.skipCurrentTag(parser);
   8311             }
   8312         }
   8313         steps.mNumStepDurations = i;
   8314     }
   8315 
   8316     @Override
   8317     public DailyItem getDailyItemLocked(int daysAgo) {
   8318         int index = mDailyItems.size()-1-daysAgo;
   8319         return index >= 0 ? mDailyItems.get(index) : null;
   8320     }
   8321 
   8322     @Override
   8323     public long getCurrentDailyStartTime() {
   8324         return mDailyStartTime;
   8325     }
   8326 
   8327     @Override
   8328     public long getNextMinDailyDeadline() {
   8329         return mNextMinDailyDeadline;
   8330     }
   8331 
   8332     @Override
   8333     public long getNextMaxDailyDeadline() {
   8334         return mNextMaxDailyDeadline;
   8335     }
   8336 
   8337     @Override
   8338     public boolean startIteratingOldHistoryLocked() {
   8339         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
   8340                 + " pos=" + mHistoryBuffer.dataPosition());
   8341         if ((mHistoryIterator = mHistory) == null) {
   8342             return false;
   8343         }
   8344         mHistoryBuffer.setDataPosition(0);
   8345         mHistoryReadTmp.clear();
   8346         mReadOverflow = false;
   8347         mIteratingHistory = true;
   8348         return true;
   8349     }
   8350 
   8351     @Override
   8352     public boolean getNextOldHistoryLocked(HistoryItem out) {
   8353         boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
   8354         if (!end) {
   8355             readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
   8356             mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
   8357         }
   8358         HistoryItem cur = mHistoryIterator;
   8359         if (cur == null) {
   8360             if (!mReadOverflow && !end) {
   8361                 Slog.w(TAG, "Old history ends before new history!");
   8362             }
   8363             return false;
   8364         }
   8365         out.setTo(cur);
   8366         mHistoryIterator = cur.next;
   8367         if (!mReadOverflow) {
   8368             if (end) {
   8369                 Slog.w(TAG, "New history ends before old history!");
   8370             } else if (!out.same(mHistoryReadTmp)) {
   8371                 PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
   8372                 pw.println("Histories differ!");
   8373                 pw.println("Old history:");
   8374                 (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
   8375                 pw.println("New history:");
   8376                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
   8377                         true);
   8378                 pw.flush();
   8379             }
   8380         }
   8381         return true;
   8382     }
   8383 
   8384     @Override
   8385     public void finishIteratingOldHistoryLocked() {
   8386         mIteratingHistory = false;
   8387         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
   8388         mHistoryIterator = null;
   8389     }
   8390 
   8391     public int getHistoryTotalSize() {
   8392         return MAX_HISTORY_BUFFER;
   8393     }
   8394 
   8395     public int getHistoryUsedSize() {
   8396         return mHistoryBuffer.dataSize();
   8397     }
   8398 
   8399     @Override
   8400     public boolean startIteratingHistoryLocked() {
   8401         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
   8402                 + " pos=" + mHistoryBuffer.dataPosition());
   8403         if (mHistoryBuffer.dataSize() <= 0) {
   8404             return false;
   8405         }
   8406         mHistoryBuffer.setDataPosition(0);
   8407         mReadOverflow = false;
   8408         mIteratingHistory = true;
   8409         mReadHistoryStrings = new String[mHistoryTagPool.size()];
   8410         mReadHistoryUids = new int[mHistoryTagPool.size()];
   8411         mReadHistoryChars = 0;
   8412         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
   8413             final HistoryTag tag = ent.getKey();
   8414             final int idx = ent.getValue();
   8415             mReadHistoryStrings[idx] = tag.string;
   8416             mReadHistoryUids[idx] = tag.uid;
   8417             mReadHistoryChars += tag.string.length() + 1;
   8418         }
   8419         return true;
   8420     }
   8421 
   8422     @Override
   8423     public int getHistoryStringPoolSize() {
   8424         return mReadHistoryStrings.length;
   8425     }
   8426 
   8427     @Override
   8428     public int getHistoryStringPoolBytes() {
   8429         // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
   8430         // Each string character is 2 bytes.
   8431         return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
   8432     }
   8433 
   8434     @Override
   8435     public String getHistoryTagPoolString(int index) {
   8436         return mReadHistoryStrings[index];
   8437     }
   8438 
   8439     @Override
   8440     public int getHistoryTagPoolUid(int index) {
   8441         return mReadHistoryUids[index];
   8442     }
   8443 
   8444     @Override
   8445     public boolean getNextHistoryLocked(HistoryItem out) {
   8446         final int pos = mHistoryBuffer.dataPosition();
   8447         if (pos == 0) {
   8448             out.clear();
   8449         }
   8450         boolean end = pos >= mHistoryBuffer.dataSize();
   8451         if (end) {
   8452             return false;
   8453         }
   8454 
   8455         final long lastRealtime = out.time;
   8456         final long lastWalltime = out.currentTime;
   8457         readHistoryDelta(mHistoryBuffer, out);
   8458         if (out.cmd != HistoryItem.CMD_CURRENT_TIME
   8459                 && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
   8460             out.currentTime = lastWalltime + (out.time - lastRealtime);
   8461         }
   8462         return true;
   8463     }
   8464 
   8465     @Override
   8466     public void finishIteratingHistoryLocked() {
   8467         mIteratingHistory = false;
   8468         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
   8469         mReadHistoryStrings = null;
   8470     }
   8471 
   8472     @Override
   8473     public long getHistoryBaseTime() {
   8474         return mHistoryBaseTime;
   8475     }
   8476 
   8477     @Override
   8478     public int getStartCount() {
   8479         return mStartCount;
   8480     }
   8481 
   8482     public boolean isOnBattery() {
   8483         return mOnBattery;
   8484     }
   8485 
   8486     public boolean isCharging() {
   8487         return mCharging;
   8488     }
   8489 
   8490     public boolean isScreenOn() {
   8491         return mScreenState == Display.STATE_ON;
   8492     }
   8493 
   8494     void initTimes(long uptime, long realtime) {
   8495         mStartClockTime = System.currentTimeMillis();
   8496         mOnBatteryTimeBase.init(uptime, realtime);
   8497         mOnBatteryScreenOffTimeBase.init(uptime, realtime);
   8498         mRealtime = 0;
   8499         mUptime = 0;
   8500         mRealtimeStart = realtime;
   8501         mUptimeStart = uptime;
   8502     }
   8503 
   8504     void initDischarge() {
   8505         mLowDischargeAmountSinceCharge = 0;
   8506         mHighDischargeAmountSinceCharge = 0;
   8507         mDischargeAmountScreenOn = 0;
   8508         mDischargeAmountScreenOnSinceCharge = 0;
   8509         mDischargeAmountScreenOff = 0;
   8510         mDischargeAmountScreenOffSinceCharge = 0;
   8511         mDischargeStepTracker.init();
   8512         mChargeStepTracker.init();
   8513         mDischargeScreenOffCounter.reset(false);
   8514         mDischargeCounter.reset(false);
   8515     }
   8516 
   8517     public void resetAllStatsCmdLocked() {
   8518         resetAllStatsLocked();
   8519         final long mSecUptime = mClocks.uptimeMillis();
   8520         long uptime = mSecUptime * 1000;
   8521         long mSecRealtime = mClocks.elapsedRealtime();
   8522         long realtime = mSecRealtime * 1000;
   8523         mDischargeStartLevel = mHistoryCur.batteryLevel;
   8524         pullPendingStateUpdatesLocked();
   8525         addHistoryRecordLocked(mSecRealtime, mSecUptime);
   8526         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
   8527                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
   8528         mOnBatteryTimeBase.reset(uptime, realtime);
   8529         mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
   8530         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
   8531             if (mScreenState == Display.STATE_ON) {
   8532                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
   8533                 mDischargeScreenOffUnplugLevel = 0;
   8534             } else {
   8535                 mDischargeScreenOnUnplugLevel = 0;
   8536                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
   8537             }
   8538             mDischargeAmountScreenOn = 0;
   8539             mDischargeAmountScreenOff = 0;
   8540         }
   8541         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
   8542     }
   8543 
   8544     private void resetAllStatsLocked() {
   8545         final long uptimeMillis = mClocks.uptimeMillis();
   8546         final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
   8547         mStartCount = 0;
   8548         initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
   8549         mScreenOnTimer.reset(false);
   8550         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   8551             mScreenBrightnessTimer[i].reset(false);
   8552         }
   8553 
   8554         if (mPowerProfile != null) {
   8555             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
   8556         } else {
   8557             mEstimatedBatteryCapacity = -1;
   8558         }
   8559         mInteractiveTimer.reset(false);
   8560         mPowerSaveModeEnabledTimer.reset(false);
   8561         mLastIdleTimeStart = elapsedRealtimeMillis;
   8562         mLongestLightIdleTime = 0;
   8563         mLongestFullIdleTime = 0;
   8564         mDeviceIdleModeLightTimer.reset(false);
   8565         mDeviceIdleModeFullTimer.reset(false);
   8566         mDeviceLightIdlingTimer.reset(false);
   8567         mDeviceIdlingTimer.reset(false);
   8568         mPhoneOnTimer.reset(false);
   8569         mAudioOnTimer.reset(false);
   8570         mVideoOnTimer.reset(false);
   8571         mFlashlightOnTimer.reset(false);
   8572         mCameraOnTimer.reset(false);
   8573         mBluetoothScanTimer.reset(false);
   8574         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   8575             mPhoneSignalStrengthsTimer[i].reset(false);
   8576         }
   8577         mPhoneSignalScanningTimer.reset(false);
   8578         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   8579             mPhoneDataConnectionsTimer[i].reset(false);
   8580         }
   8581         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   8582             mNetworkByteActivityCounters[i].reset(false);
   8583             mNetworkPacketActivityCounters[i].reset(false);
   8584         }
   8585         mMobileRadioActiveTimer.reset(false);
   8586         mMobileRadioActivePerAppTimer.reset(false);
   8587         mMobileRadioActiveAdjustedTime.reset(false);
   8588         mMobileRadioActiveUnknownTime.reset(false);
   8589         mMobileRadioActiveUnknownCount.reset(false);
   8590         mWifiOnTimer.reset(false);
   8591         mGlobalWifiRunningTimer.reset(false);
   8592         for (int i=0; i<NUM_WIFI_STATES; i++) {
   8593             mWifiStateTimer[i].reset(false);
   8594         }
   8595         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   8596             mWifiSupplStateTimer[i].reset(false);
   8597         }
   8598         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   8599             mWifiSignalStrengthsTimer[i].reset(false);
   8600         }
   8601         mWifiActivity.reset(false);
   8602         mBluetoothActivity.reset(false);
   8603         mModemActivity.reset(false);
   8604         mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
   8605 
   8606         for (int i=0; i<mUidStats.size(); i++) {
   8607             if (mUidStats.valueAt(i).reset()) {
   8608                 mUidStats.remove(mUidStats.keyAt(i));
   8609                 i--;
   8610             }
   8611         }
   8612 
   8613         if (mKernelWakelockStats.size() > 0) {
   8614             for (SamplingTimer timer : mKernelWakelockStats.values()) {
   8615                 mOnBatteryScreenOffTimeBase.remove(timer);
   8616             }
   8617             mKernelWakelockStats.clear();
   8618         }
   8619 
   8620         if (mWakeupReasonStats.size() > 0) {
   8621             for (SamplingTimer timer : mWakeupReasonStats.values()) {
   8622                 mOnBatteryTimeBase.remove(timer);
   8623             }
   8624             mWakeupReasonStats.clear();
   8625         }
   8626 
   8627         mLastHistoryStepDetails = null;
   8628         mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
   8629         mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
   8630         mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
   8631         mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
   8632         mLastStepStatUserTime = mCurStepStatUserTime = 0;
   8633         mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
   8634         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
   8635         mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
   8636         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
   8637         mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
   8638 
   8639         initDischarge();
   8640 
   8641         clearHistoryLocked();
   8642     }
   8643 
   8644     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
   8645         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
   8646             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
   8647                 // Not recording process starts/stops.
   8648                 continue;
   8649             }
   8650             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
   8651             if (active == null) {
   8652                 continue;
   8653             }
   8654             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
   8655                 SparseIntArray uids = ent.getValue();
   8656                 for (int j=0; j<uids.size(); j++) {
   8657                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
   8658                             uids.keyAt(j));
   8659                 }
   8660             }
   8661         }
   8662     }
   8663 
   8664     void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) {
   8665         if (oldScreenOn) {
   8666             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
   8667             if (diff > 0) {
   8668                 mDischargeAmountScreenOn += diff;
   8669                 mDischargeAmountScreenOnSinceCharge += diff;
   8670             }
   8671         } else {
   8672             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
   8673             if (diff > 0) {
   8674                 mDischargeAmountScreenOff += diff;
   8675                 mDischargeAmountScreenOffSinceCharge += diff;
   8676             }
   8677         }
   8678         if (newScreenOn) {
   8679             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
   8680             mDischargeScreenOffUnplugLevel = 0;
   8681         } else {
   8682             mDischargeScreenOnUnplugLevel = 0;
   8683             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
   8684         }
   8685     }
   8686 
   8687     public void pullPendingStateUpdatesLocked() {
   8688         if (mOnBatteryInternal) {
   8689             final boolean screenOn = mScreenState == Display.STATE_ON;
   8690             updateDischargeScreenLevelsLocked(screenOn, screenOn);
   8691         }
   8692     }
   8693 
   8694     private String[] mMobileIfaces = EmptyArray.STRING;
   8695     private String[] mWifiIfaces = EmptyArray.STRING;
   8696 
   8697     private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
   8698 
   8699     private static final int NETWORK_STATS_LAST = 0;
   8700     private static final int NETWORK_STATS_NEXT = 1;
   8701     private static final int NETWORK_STATS_DELTA = 2;
   8702 
   8703     private NetworkStats[] mMobileNetworkStats;
   8704     private NetworkStats[] mWifiNetworkStats;
   8705 
   8706     /**
   8707      * Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer
   8708      * as a buffer of NetworkStats objects to cycle through when computing deltas.
   8709      */
   8710     private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces,
   8711                                                     NetworkStats[] networkStatsBuffer)
   8712             throws IOException {
   8713         if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED,
   8714                 false)) {
   8715             return null;
   8716         }
   8717 
   8718         final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL,
   8719                 ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]);
   8720         networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats,
   8721                 networkStatsBuffer[NETWORK_STATS_LAST], null, null,
   8722                 networkStatsBuffer[NETWORK_STATS_DELTA]);
   8723         networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST];
   8724         networkStatsBuffer[NETWORK_STATS_LAST] = stats;
   8725         return networkStatsBuffer[NETWORK_STATS_DELTA];
   8726     }
   8727 
   8728     /**
   8729      * Distribute WiFi energy info and network traffic to apps.
   8730      * @param info The energy information from the WiFi controller.
   8731      */
   8732     public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
   8733         if (DEBUG_ENERGY) {
   8734             Slog.d(TAG, "Updating wifi stats");
   8735         }
   8736 
   8737         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
   8738         NetworkStats delta = null;
   8739         try {
   8740             if (!ArrayUtils.isEmpty(mWifiIfaces)) {
   8741                 delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats);
   8742             }
   8743         } catch (IOException e) {
   8744             Slog.wtf(TAG, "Failed to get wifi network stats", e);
   8745             return;
   8746         }
   8747 
   8748         if (!mOnBatteryInternal) {
   8749             return;
   8750         }
   8751 
   8752         SparseLongArray rxPackets = new SparseLongArray();
   8753         SparseLongArray txPackets = new SparseLongArray();
   8754         long totalTxPackets = 0;
   8755         long totalRxPackets = 0;
   8756         if (delta != null) {
   8757             final int size = delta.size();
   8758             for (int i = 0; i < size; i++) {
   8759                 final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
   8760 
   8761                 if (DEBUG_ENERGY) {
   8762                     Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
   8763                             + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
   8764                             + " txPackets=" + entry.txPackets);
   8765                 }
   8766 
   8767                 if (entry.rxBytes == 0 && entry.txBytes == 0) {
   8768                     // Skip the lookup below since there is no work to do.
   8769                     continue;
   8770                 }
   8771 
   8772                 final Uid u = getUidStatsLocked(mapUid(entry.uid));
   8773                 if (entry.rxBytes != 0) {
   8774                     u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
   8775                             entry.rxPackets);
   8776                     mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
   8777                             entry.rxBytes);
   8778                     mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
   8779                             entry.rxPackets);
   8780 
   8781                     rxPackets.put(u.getUid(), entry.rxPackets);
   8782 
   8783                     // Sum the total number of packets so that the Rx Power can
   8784                     // be evenly distributed amongst the apps.
   8785                     totalRxPackets += entry.rxPackets;
   8786                 }
   8787 
   8788                 if (entry.txBytes != 0) {
   8789                     u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
   8790                             entry.txPackets);
   8791                     mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
   8792                             entry.txBytes);
   8793                     mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
   8794                             entry.txPackets);
   8795 
   8796                     txPackets.put(u.getUid(), entry.txPackets);
   8797 
   8798                     // Sum the total number of packets so that the Tx Power can
   8799                     // be evenly distributed amongst the apps.
   8800                     totalTxPackets += entry.txPackets;
   8801                 }
   8802             }
   8803         }
   8804 
   8805         if (info != null) {
   8806             mHasWifiReporting = true;
   8807 
   8808             // Measured in mAms
   8809             final long txTimeMs = info.getControllerTxTimeMillis();
   8810             final long rxTimeMs = info.getControllerRxTimeMillis();
   8811             final long idleTimeMs = info.getControllerIdleTimeMillis();
   8812             final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
   8813 
   8814             long leftOverRxTimeMs = rxTimeMs;
   8815             long leftOverTxTimeMs = txTimeMs;
   8816 
   8817             if (DEBUG_ENERGY) {
   8818                 Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
   8819                 Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
   8820                 Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
   8821                 Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
   8822                 Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
   8823             }
   8824 
   8825             long totalWifiLockTimeMs = 0;
   8826             long totalScanTimeMs = 0;
   8827 
   8828             // On the first pass, collect some totals so that we can normalize power
   8829             // calculations if we need to.
   8830             final int uidStatsSize = mUidStats.size();
   8831             for (int i = 0; i < uidStatsSize; i++) {
   8832                 final Uid uid = mUidStats.valueAt(i);
   8833 
   8834                 // Sum the total scan power for all apps.
   8835                 totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
   8836                         elapsedRealtimeMs * 1000) / 1000;
   8837 
   8838                 // Sum the total time holding wifi lock for all apps.
   8839                 totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
   8840                         elapsedRealtimeMs * 1000) / 1000;
   8841             }
   8842 
   8843             if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
   8844                 Slog.d(TAG, "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
   8845                         + rxTimeMs + " ms). Normalizing scan time.");
   8846             }
   8847             if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
   8848                 Slog.d(TAG, "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
   8849                         + txTimeMs + " ms). Normalizing scan time.");
   8850             }
   8851 
   8852             // Actually assign and distribute power usage to apps.
   8853             for (int i = 0; i < uidStatsSize; i++) {
   8854                 final Uid uid = mUidStats.valueAt(i);
   8855 
   8856                 long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
   8857                         elapsedRealtimeMs * 1000) / 1000;
   8858                 if (scanTimeSinceMarkMs > 0) {
   8859                     // Set the new mark so that next time we get new data since this point.
   8860                     uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
   8861 
   8862                     long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
   8863                     long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
   8864 
   8865                     // Our total scan time is more than the reported Tx/Rx time.
   8866                     // This is possible because the cost of a scan is approximate.
   8867                     // Let's normalize the result so that we evenly blame each app
   8868                     // scanning.
   8869                     //
   8870                     // This means that we may have apps that transmitted/received packets not be
   8871                     // blamed for this, but this is fine as scans are relatively more expensive.
   8872                     if (totalScanTimeMs > rxTimeMs) {
   8873                         scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
   8874                                 totalScanTimeMs;
   8875                     }
   8876                     if (totalScanTimeMs > txTimeMs) {
   8877                         scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
   8878                                 totalScanTimeMs;
   8879                     }
   8880 
   8881                     if (DEBUG_ENERGY) {
   8882                         Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
   8883                                 + scanRxTimeSinceMarkMs + " ms  Tx:"
   8884                                 + scanTxTimeSinceMarkMs + " ms)");
   8885                     }
   8886 
   8887                     ControllerActivityCounterImpl activityCounter =
   8888                             uid.getOrCreateWifiControllerActivityLocked();
   8889                     activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
   8890                     activityCounter.getTxTimeCounters()[0].addCountLocked(scanTxTimeSinceMarkMs);
   8891                     leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
   8892                     leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
   8893                 }
   8894 
   8895                 // Distribute evenly the power consumed while Idle to each app holding a WiFi
   8896                 // lock.
   8897                 final long wifiLockTimeSinceMarkMs = uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
   8898                         elapsedRealtimeMs * 1000) / 1000;
   8899                 if (wifiLockTimeSinceMarkMs > 0) {
   8900                     // Set the new mark so that next time we get new data since this point.
   8901                     uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
   8902 
   8903                     final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
   8904                             / totalWifiLockTimeMs;
   8905                     if (DEBUG_ENERGY) {
   8906                         Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
   8907                                 + myIdleTimeMs + " ms");
   8908                     }
   8909                     uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
   8910                             .addCountLocked(myIdleTimeMs);
   8911                 }
   8912             }
   8913 
   8914             if (DEBUG_ENERGY) {
   8915                 Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
   8916                 Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
   8917             }
   8918 
   8919             // Distribute the remaining Tx power appropriately between all apps that transmitted
   8920             // packets.
   8921             for (int i = 0; i < txPackets.size(); i++) {
   8922                 final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
   8923                 final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) / totalTxPackets;
   8924                 if (DEBUG_ENERGY) {
   8925                     Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
   8926                 }
   8927                 uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
   8928                         .addCountLocked(myTxTimeMs);
   8929             }
   8930 
   8931             // Distribute the remaining Rx power appropriately between all apps that received
   8932             // packets.
   8933             for (int i = 0; i < rxPackets.size(); i++) {
   8934                 final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
   8935                 final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) / totalRxPackets;
   8936                 if (DEBUG_ENERGY) {
   8937                     Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
   8938                 }
   8939                 uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
   8940                         .addCountLocked(myRxTimeMs);
   8941             }
   8942 
   8943             // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
   8944 
   8945             // Update WiFi controller stats.
   8946             mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
   8947             mWifiActivity.getTxTimeCounters()[0].addCountLocked(info.getControllerTxTimeMillis());
   8948             mWifiActivity.getIdleTimeCounter().addCountLocked(info.getControllerIdleTimeMillis());
   8949 
   8950             // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
   8951             final double opVolt = mPowerProfile.getAveragePower(
   8952                     PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
   8953             if (opVolt != 0) {
   8954                 // We store the power drain as mAms.
   8955                 mWifiActivity.getPowerCounter().addCountLocked(
   8956                         (long)(info.getControllerEnergyUsed() / opVolt));
   8957             }
   8958         }
   8959     }
   8960 
   8961     /**
   8962      * Distribute Cell radio energy info and network traffic to apps.
   8963      */
   8964     public void updateMobileRadioStateLocked(final long elapsedRealtimeMs,
   8965                                              final ModemActivityInfo activityInfo) {
   8966         if (DEBUG_ENERGY) {
   8967             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
   8968         }
   8969 
   8970         NetworkStats delta = null;
   8971         try {
   8972             if (!ArrayUtils.isEmpty(mMobileIfaces)) {
   8973                 delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats);
   8974             }
   8975         } catch (IOException e) {
   8976             Slog.wtf(TAG, "Failed to get mobile network stats", e);
   8977             return;
   8978         }
   8979 
   8980         if (!mOnBatteryInternal) {
   8981             return;
   8982         }
   8983 
   8984         long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
   8985                 elapsedRealtimeMs * 1000);
   8986         mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
   8987 
   8988         long totalRxPackets = 0;
   8989         long totalTxPackets = 0;
   8990         if (delta != null) {
   8991             final int size = delta.size();
   8992             for (int i = 0; i < size; i++) {
   8993                 final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
   8994                 if (entry.rxPackets == 0 && entry.txPackets == 0) {
   8995                     continue;
   8996                 }
   8997 
   8998                 if (DEBUG_ENERGY) {
   8999                     Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
   9000                             + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
   9001                             + " txPackets=" + entry.txPackets);
   9002                 }
   9003 
   9004                 totalRxPackets += entry.rxPackets;
   9005                 totalTxPackets += entry.txPackets;
   9006 
   9007                 final Uid u = getUidStatsLocked(mapUid(entry.uid));
   9008                 u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets);
   9009                 u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets);
   9010 
   9011                 mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
   9012                         entry.rxBytes);
   9013                 mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
   9014                         entry.txBytes);
   9015                 mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
   9016                         entry.rxPackets);
   9017                 mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
   9018                         entry.txPackets);
   9019             }
   9020 
   9021             // Now distribute proportional blame to the apps that did networking.
   9022             long totalPackets = totalRxPackets + totalTxPackets;
   9023             if (totalPackets > 0) {
   9024                 for (int i = 0; i < size; i++) {
   9025                     final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
   9026                     if (entry.rxPackets == 0 && entry.txPackets == 0) {
   9027                         continue;
   9028                     }
   9029 
   9030                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
   9031 
   9032                     // Distribute total radio active time in to this app.
   9033                     final long appPackets = entry.rxPackets + entry.txPackets;
   9034                     final long appRadioTime = (radioTime * appPackets) / totalPackets;
   9035                     u.noteMobileRadioActiveTimeLocked(appRadioTime);
   9036 
   9037                     // Remove this app from the totals, so that we don't lose any time
   9038                     // due to rounding.
   9039                     radioTime -= appRadioTime;
   9040                     totalPackets -= appPackets;
   9041 
   9042                     if (activityInfo != null) {
   9043                         ControllerActivityCounterImpl activityCounter =
   9044                                 u.getOrCreateModemControllerActivityLocked();
   9045                         if (totalRxPackets > 0 && entry.rxPackets > 0) {
   9046                             final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
   9047                                     / totalRxPackets;
   9048                             activityCounter.getRxTimeCounter().addCountLocked(rxMs);
   9049                         }
   9050 
   9051                         if (totalTxPackets > 0 && entry.txPackets > 0) {
   9052                             for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
   9053                                 long txMs = entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
   9054                                 txMs /= totalTxPackets;
   9055                                 activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
   9056                             }
   9057                         }
   9058                     }
   9059                 }
   9060             }
   9061 
   9062             if (radioTime > 0) {
   9063                 // Whoops, there is some radio time we can't blame on an app!
   9064                 mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
   9065                 mMobileRadioActiveUnknownCount.addCountLocked(1);
   9066             }
   9067         }
   9068 
   9069         if (activityInfo != null) {
   9070             mHasModemReporting = true;
   9071             mModemActivity.getIdleTimeCounter().addCountLocked(activityInfo.getIdleTimeMillis());
   9072             mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
   9073             for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
   9074                 mModemActivity.getTxTimeCounters()[lvl]
   9075                         .addCountLocked(activityInfo.getTxTimeMillis()[lvl]);
   9076             }
   9077 
   9078             // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
   9079             final double opVolt = mPowerProfile.getAveragePower(
   9080                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
   9081             if (opVolt != 0) {
   9082                 // We store the power drain as mAms.
   9083                 mModemActivity.getPowerCounter().addCountLocked(
   9084                         (long) (activityInfo.getEnergyUsed() / opVolt));
   9085             }
   9086         }
   9087     }
   9088 
   9089     /**
   9090      * Distribute Bluetooth energy info and network traffic to apps.
   9091      * @param info The energy information from the bluetooth controller.
   9092      */
   9093     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
   9094         if (DEBUG_ENERGY) {
   9095             Slog.d(TAG, "Updating bluetooth stats: " + info);
   9096         }
   9097 
   9098         if (info == null || !mOnBatteryInternal) {
   9099             return;
   9100         }
   9101 
   9102         mHasBluetoothReporting = true;
   9103 
   9104         final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
   9105         final long rxTimeMs = info.getControllerRxTimeMillis();
   9106         final long txTimeMs = info.getControllerTxTimeMillis();
   9107 
   9108         if (DEBUG_ENERGY) {
   9109             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
   9110             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
   9111             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
   9112             Slog.d(TAG, "  Idle Time:  " + info.getControllerIdleTimeMillis() + " ms");
   9113         }
   9114 
   9115         long totalScanTimeMs = 0;
   9116 
   9117         final int uidCount = mUidStats.size();
   9118         for (int i = 0; i < uidCount; i++) {
   9119             final Uid u = mUidStats.valueAt(i);
   9120             if (u.mBluetoothScanTimer == null) {
   9121                 continue;
   9122             }
   9123 
   9124             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
   9125                     elapsedRealtimeMs * 1000) / 1000;
   9126         }
   9127 
   9128         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
   9129         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
   9130 
   9131         if (DEBUG_ENERGY) {
   9132             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
   9133                     + " TX=" + normalizeScanTxTime);
   9134         }
   9135 
   9136         long leftOverRxTimeMs = rxTimeMs;
   9137         long leftOverTxTimeMs = txTimeMs;
   9138 
   9139         for (int i = 0; i < uidCount; i++) {
   9140             final Uid u = mUidStats.valueAt(i);
   9141             if (u.mBluetoothScanTimer == null) {
   9142                 continue;
   9143             }
   9144 
   9145             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
   9146                     elapsedRealtimeMs * 1000) / 1000;
   9147             if (scanTimeSinceMarkMs > 0) {
   9148                 // Set the new mark so that next time we get new data since this point.
   9149                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
   9150 
   9151                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
   9152                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
   9153 
   9154                 if (normalizeScanRxTime) {
   9155                     // Scan time is longer than the total rx time in the controller,
   9156                     // so distribute the scan time proportionately. This means regular traffic
   9157                     // will not blamed, but scans are more expensive anyways.
   9158                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
   9159                 }
   9160 
   9161                 if (normalizeScanTxTime) {
   9162                     // Scan time is longer than the total tx time in the controller,
   9163                     // so distribute the scan time proportionately. This means regular traffic
   9164                     // will not blamed, but scans are more expensive anyways.
   9165                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
   9166                 }
   9167 
   9168                 final ControllerActivityCounterImpl counter =
   9169                         u.getOrCreateBluetoothControllerActivityLocked();
   9170                 counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
   9171                 counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
   9172 
   9173                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
   9174                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
   9175             }
   9176         }
   9177 
   9178         if (DEBUG_ENERGY) {
   9179             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs
   9180                     + " TX=" + leftOverTxTimeMs);
   9181         }
   9182 
   9183         //
   9184         // Now distribute blame to apps that did bluetooth traffic.
   9185         //
   9186 
   9187         long totalTxBytes = 0;
   9188         long totalRxBytes = 0;
   9189 
   9190         final UidTraffic[] uidTraffic = info.getUidTraffic();
   9191         final int numUids = uidTraffic != null ? uidTraffic.length : 0;
   9192         for (int i = 0; i < numUids; i++) {
   9193             final UidTraffic traffic = uidTraffic[i];
   9194 
   9195             // Add to the global counters.
   9196             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(
   9197                     traffic.getRxBytes());
   9198             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(
   9199                     traffic.getTxBytes());
   9200 
   9201             // Add to the UID counters.
   9202             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
   9203             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, traffic.getRxBytes(), 0);
   9204             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, traffic.getTxBytes(), 0);
   9205 
   9206             // Calculate the total traffic.
   9207             totalTxBytes += traffic.getTxBytes();
   9208             totalRxBytes += traffic.getRxBytes();
   9209         }
   9210 
   9211         if ((totalTxBytes != 0 || totalRxBytes != 0) &&
   9212                 (leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) {
   9213             for (int i = 0; i < numUids; i++) {
   9214                 final UidTraffic traffic = uidTraffic[i];
   9215 
   9216                 final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
   9217                 final ControllerActivityCounterImpl counter =
   9218                         u.getOrCreateBluetoothControllerActivityLocked();
   9219 
   9220                 if (totalRxBytes > 0 && traffic.getRxBytes() > 0) {
   9221                     final long timeRxMs = (leftOverRxTimeMs * traffic.getRxBytes()) / totalRxBytes;
   9222 
   9223                     if (DEBUG_ENERGY) {
   9224                         Slog.d(TAG, "UID=" + traffic.getUid() + " rx_bytes=" + traffic.getRxBytes()
   9225                                 + " rx_time=" + timeRxMs);
   9226                     }
   9227                     counter.getRxTimeCounter().addCountLocked(timeRxMs);
   9228                     leftOverRxTimeMs -= timeRxMs;
   9229                 }
   9230 
   9231                 if (totalTxBytes > 0 && traffic.getTxBytes() > 0) {
   9232                     final long timeTxMs = (leftOverTxTimeMs * traffic.getTxBytes()) / totalTxBytes;
   9233 
   9234                     if (DEBUG_ENERGY) {
   9235                         Slog.d(TAG, "UID=" + traffic.getUid() + " tx_bytes=" + traffic.getTxBytes()
   9236                                 + " tx_time=" + timeTxMs);
   9237                     }
   9238 
   9239                     counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
   9240                     leftOverTxTimeMs -= timeTxMs;
   9241                 }
   9242             }
   9243         }
   9244 
   9245         mBluetoothActivity.getRxTimeCounter().addCountLocked(
   9246                 info.getControllerRxTimeMillis());
   9247         mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(
   9248                 info.getControllerTxTimeMillis());
   9249         mBluetoothActivity.getIdleTimeCounter().addCountLocked(
   9250                 info.getControllerIdleTimeMillis());
   9251 
   9252         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
   9253         final double opVolt = mPowerProfile.getAveragePower(
   9254                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
   9255         if (opVolt != 0) {
   9256             // We store the power drain as mAms.
   9257             mBluetoothActivity.getPowerCounter().addCountLocked(
   9258                     (long) (info.getControllerEnergyUsed() / opVolt));
   9259         }
   9260     }
   9261 
   9262     /**
   9263      * Read and distribute kernel wake lock use across apps.
   9264      */
   9265     public void updateKernelWakelocksLocked() {
   9266         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
   9267                 mTmpWakelockStats);
   9268         if (wakelockStats == null) {
   9269             // Not crashing might make board bringup easier.
   9270             Slog.w(TAG, "Couldn't get kernel wake lock stats");
   9271             return;
   9272         }
   9273 
   9274         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
   9275             String name = ent.getKey();
   9276             KernelWakelockStats.Entry kws = ent.getValue();
   9277 
   9278             SamplingTimer kwlt = mKernelWakelockStats.get(name);
   9279             if (kwlt == null) {
   9280                 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
   9281                 mKernelWakelockStats.put(name, kwlt);
   9282             }
   9283 
   9284             kwlt.update(kws.mTotalTime, kws.mCount);
   9285             kwlt.setUpdateVersion(kws.mVersion);
   9286         }
   9287 
   9288         int numWakelocksSetStale = 0;
   9289         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
   9290         // this time.
   9291         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
   9292             SamplingTimer st = ent.getValue();
   9293             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
   9294                 st.endSample();
   9295                 numWakelocksSetStale++;
   9296             }
   9297         }
   9298 
   9299         // Record whether we've seen a non-zero time (for debugging b/22716723).
   9300         if (wakelockStats.isEmpty()) {
   9301             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
   9302         }
   9303 
   9304         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
   9305             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
   9306                     wakelockStats.kernelWakelockVersion);
   9307         }
   9308     }
   9309 
   9310     // We use an anonymous class to access these variables,
   9311     // so they can't live on the stack or they'd have to be
   9312     // final MutableLong objects (more allocations).
   9313     // Used in updateCpuTimeLocked().
   9314     long mTempTotalCpuUserTimeUs;
   9315     long mTempTotalCpuSystemTimeUs;
   9316 
   9317     /**
   9318      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
   9319      * and we are on battery with screen off, we give more of the cpu time to those apps holding
   9320      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
   9321      */
   9322     public void updateCpuTimeLocked() {
   9323         if (mPowerProfile == null) {
   9324             return;
   9325         }
   9326 
   9327         if (DEBUG_ENERGY_CPU) {
   9328             Slog.d(TAG, "!Cpu updating!");
   9329         }
   9330 
   9331         // Holding a wakelock costs more than just using the cpu.
   9332         // Currently, we assign only half the cpu time to an app that is running but
   9333         // not holding a wakelock. The apps holding wakelocks get the rest of the blame.
   9334         // If no app is holding a wakelock, then the distribution is normal.
   9335         final int wakelockWeight = 50;
   9336 
   9337         // Read the time spent for each cluster at various cpu frequencies.
   9338         final long[][] clusterSpeeds = new long[mKernelCpuSpeedReaders.length][];
   9339         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
   9340             clusterSpeeds[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
   9341         }
   9342 
   9343         int numWakelocks = 0;
   9344 
   9345         // Calculate how many wakelocks we have to distribute amongst. The system is excluded.
   9346         // Only distribute cpu power to wakelocks if the screen is off and we're on battery.
   9347         final int numPartialTimers = mPartialTimers.size();
   9348         if (mOnBatteryScreenOffTimeBase.isRunning()) {
   9349             for (int i = 0; i < numPartialTimers; i++) {
   9350                 final StopwatchTimer timer = mPartialTimers.get(i);
   9351                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
   9352                     // Since the collection and blaming of wakelocks can be scheduled to run after
   9353                     // some delay, the mPartialTimers list may have new entries. We can't blame
   9354                     // the newly added timer for past cpu time, so we only consider timers that
   9355                     // were present for one round of collection. Once a timer has gone through
   9356                     // a round of collection, its mInList field is set to true.
   9357                     numWakelocks++;
   9358                 }
   9359             }
   9360         }
   9361 
   9362         final int numWakelocksF = numWakelocks;
   9363         mTempTotalCpuUserTimeUs = 0;
   9364         mTempTotalCpuSystemTimeUs = 0;
   9365 
   9366         // Read the CPU data for each UID. This will internally generate a snapshot so next time
   9367         // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
   9368         // we just ignore the data.
   9369         final long startTimeMs = mClocks.elapsedRealtime();
   9370         mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
   9371                 new KernelUidCpuTimeReader.Callback() {
   9372                     @Override
   9373                     public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs,
   9374                                              long powerMaUs) {
   9375                         final Uid u = getUidStatsLocked(mapUid(uid));
   9376 
   9377                         // Accumulate the total system and user time.
   9378                         mTempTotalCpuUserTimeUs += userTimeUs;
   9379                         mTempTotalCpuSystemTimeUs += systemTimeUs;
   9380 
   9381                         StringBuilder sb = null;
   9382                         if (DEBUG_ENERGY_CPU) {
   9383                             sb = new StringBuilder();
   9384                             sb.append("  got time for uid=").append(u.mUid).append(": u=");
   9385                             TimeUtils.formatDuration(userTimeUs / 1000, sb);
   9386                             sb.append(" s=");
   9387                             TimeUtils.formatDuration(systemTimeUs / 1000, sb);
   9388                             sb.append(" p=").append(powerMaUs / 1000).append("mAms\n");
   9389                         }
   9390 
   9391                         if (numWakelocksF > 0) {
   9392                             // We have wakelocks being held, so only give a portion of the
   9393                             // time to the process. The rest will be distributed among wakelock
   9394                             // holders.
   9395                             userTimeUs = (userTimeUs * wakelockWeight) / 100;
   9396                             systemTimeUs = (systemTimeUs * wakelockWeight) / 100;
   9397                         }
   9398 
   9399                         if (sb != null) {
   9400                             sb.append("  adding to uid=").append(u.mUid).append(": u=");
   9401                             TimeUtils.formatDuration(userTimeUs / 1000, sb);
   9402                             sb.append(" s=");
   9403                             TimeUtils.formatDuration(systemTimeUs / 1000, sb);
   9404                             sb.append(" p=").append(powerMaUs / 1000).append("mAms");
   9405                             Slog.d(TAG, sb.toString());
   9406                         }
   9407 
   9408                         u.mUserCpuTime.addCountLocked(userTimeUs);
   9409                         u.mSystemCpuTime.addCountLocked(systemTimeUs);
   9410                         u.mCpuPower.addCountLocked(powerMaUs);
   9411 
   9412                         // Add the cpu speeds to this UID. These are used as a ratio
   9413                         // for computing the power this UID used.
   9414                         final int numClusters = mPowerProfile.getNumCpuClusters();
   9415                         if (u.mCpuClusterSpeed == null || u.mCpuClusterSpeed.length !=
   9416                                 numClusters) {
   9417                             u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
   9418                         }
   9419 
   9420                         for (int cluster = 0; cluster < clusterSpeeds.length; cluster++) {
   9421                             final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(
   9422                                     cluster);
   9423                             if (u.mCpuClusterSpeed[cluster] == null || speedsInCluster !=
   9424                                     u.mCpuClusterSpeed[cluster].length) {
   9425                                 u.mCpuClusterSpeed[cluster] =
   9426                                         new LongSamplingCounter[speedsInCluster];
   9427                             }
   9428 
   9429                             final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeed[cluster];
   9430                             for (int speed = 0; speed < clusterSpeeds[cluster].length; speed++) {
   9431                                 if (cpuSpeeds[speed] == null) {
   9432                                     cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
   9433                                 }
   9434                                 cpuSpeeds[speed].addCountLocked(clusterSpeeds[cluster][speed]);
   9435                             }
   9436                         }
   9437                     }
   9438                 });
   9439 
   9440         if (DEBUG_ENERGY_CPU) {
   9441             Slog.d(TAG, "Reading cpu stats took " + (mClocks.elapsedRealtime() - startTimeMs) +
   9442                     " ms");
   9443         }
   9444 
   9445         if (mOnBatteryInternal && numWakelocks > 0) {
   9446             // Distribute a portion of the total cpu time to wakelock holders.
   9447             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100;
   9448             mTempTotalCpuSystemTimeUs =
   9449                     (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100;
   9450 
   9451             for (int i = 0; i < numPartialTimers; i++) {
   9452                 final StopwatchTimer timer = mPartialTimers.get(i);
   9453 
   9454                 // The system does not share any blame, as it is usually holding the wakelock
   9455                 // on behalf of an app.
   9456                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
   9457                     int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks);
   9458                     int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks);
   9459 
   9460                     if (DEBUG_ENERGY_CPU) {
   9461                         StringBuilder sb = new StringBuilder();
   9462                         sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
   9463                                 .append(": u=");
   9464                         TimeUtils.formatDuration(userTimeUs / 1000, sb);
   9465                         sb.append(" s=");
   9466                         TimeUtils.formatDuration(systemTimeUs / 1000, sb);
   9467                         Slog.d(TAG, sb.toString());
   9468                     }
   9469 
   9470                     timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
   9471                     timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
   9472 
   9473                     final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
   9474                     proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000);
   9475 
   9476                     mTempTotalCpuUserTimeUs -= userTimeUs;
   9477                     mTempTotalCpuSystemTimeUs -= systemTimeUs;
   9478                     numWakelocks--;
   9479                 }
   9480             }
   9481 
   9482             if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) {
   9483                 // Anything left over is given to the system.
   9484                 if (DEBUG_ENERGY_CPU) {
   9485                     StringBuilder sb = new StringBuilder();
   9486                     sb.append("  Distributing lost time to system: u=");
   9487                     TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb);
   9488                     sb.append(" s=");
   9489                     TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb);
   9490                     Slog.d(TAG, sb.toString());
   9491                 }
   9492 
   9493                 final Uid u = getUidStatsLocked(Process.SYSTEM_UID);
   9494                 u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs);
   9495                 u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs);
   9496 
   9497                 final Uid.Proc proc = u.getProcessStatsLocked("*lost*");
   9498                 proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs / 1000,
   9499                         (int) mTempTotalCpuSystemTimeUs / 1000);
   9500             }
   9501         }
   9502 
   9503         // See if there is a difference in wakelocks between this collection and the last
   9504         // collection.
   9505         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
   9506             // No difference, so each timer is now considered for the next collection.
   9507             for (int i = 0; i < numPartialTimers; i++) {
   9508                 mPartialTimers.get(i).mInList = true;
   9509             }
   9510         } else {
   9511             // The lists are different, meaning we added (or removed a timer) since the last
   9512             // collection.
   9513             final int numLastPartialTimers = mLastPartialTimers.size();
   9514             for (int i = 0; i < numLastPartialTimers; i++) {
   9515                 mLastPartialTimers.get(i).mInList = false;
   9516             }
   9517             mLastPartialTimers.clear();
   9518 
   9519             // Mark the current timers as gone through a collection.
   9520             for (int i = 0; i < numPartialTimers; i++) {
   9521                 final StopwatchTimer timer = mPartialTimers.get(i);
   9522                 timer.mInList = true;
   9523                 mLastPartialTimers.add(timer);
   9524             }
   9525         }
   9526     }
   9527 
   9528     boolean setChargingLocked(boolean charging) {
   9529         if (mCharging != charging) {
   9530             mCharging = charging;
   9531             if (charging) {
   9532                 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
   9533             } else {
   9534                 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
   9535             }
   9536             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
   9537             return true;
   9538         }
   9539         return false;
   9540     }
   9541 
   9542     void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
   9543             final int oldStatus, final int level, final int chargeUAh) {
   9544         boolean doWrite = false;
   9545         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
   9546         m.arg1 = onBattery ? 1 : 0;
   9547         mHandler.sendMessage(m);
   9548 
   9549         final long uptime = mSecUptime * 1000;
   9550         final long realtime = mSecRealtime * 1000;
   9551         final boolean screenOn = mScreenState == Display.STATE_ON;
   9552         if (onBattery) {
   9553             // We will reset our status if we are unplugging after the
   9554             // battery was last full, or the level is at 100, or
   9555             // we have gone through a significant charge (from a very low
   9556             // level to a now very high level).
   9557             boolean reset = false;
   9558             if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
   9559                     || level >= 90
   9560                     || (mDischargeCurrentLevel < 20 && level >= 80)
   9561                     || (getHighDischargeAmountSinceCharge() >= 200
   9562                             && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
   9563                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
   9564                         + " dischargeLevel=" + mDischargeCurrentLevel
   9565                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
   9566                         + " highAmount=" + getHighDischargeAmountSinceCharge());
   9567                 // Before we write, collect a snapshot of the final aggregated
   9568                 // stats to be reported in the next checkin.  Only do this if we have
   9569                 // a sufficient amount of data to make it interesting.
   9570                 if (getLowDischargeAmountSinceCharge() >= 20) {
   9571                     final Parcel parcel = Parcel.obtain();
   9572                     writeSummaryToParcel(parcel, true);
   9573                     BackgroundThread.getHandler().post(new Runnable() {
   9574                         @Override public void run() {
   9575                             synchronized (mCheckinFile) {
   9576                                 FileOutputStream stream = null;
   9577                                 try {
   9578                                     stream = mCheckinFile.startWrite();
   9579                                     stream.write(parcel.marshall());
   9580                                     stream.flush();
   9581                                     FileUtils.sync(stream);
   9582                                     stream.close();
   9583                                     mCheckinFile.finishWrite(stream);
   9584                                 } catch (IOException e) {
   9585                                     Slog.w("BatteryStats",
   9586                                             "Error writing checkin battery statistics", e);
   9587                                     mCheckinFile.failWrite(stream);
   9588                                 } finally {
   9589                                     parcel.recycle();
   9590                                 }
   9591                             }
   9592                         }
   9593                     });
   9594                 }
   9595                 doWrite = true;
   9596                 resetAllStatsLocked();
   9597                 if (chargeUAh > 0) {
   9598                     // Only use the reported coulomb charge value if it is supported and reported.
   9599                     mEstimatedBatteryCapacity = (int) ((level / 100.0) * (chargeUAh / 1000));
   9600                 }
   9601                 mDischargeStartLevel = level;
   9602                 reset = true;
   9603                 mDischargeStepTracker.init();
   9604             }
   9605             if (mCharging) {
   9606                 setChargingLocked(false);
   9607             }
   9608             mLastChargingStateLevel = level;
   9609             mOnBattery = mOnBatteryInternal = true;
   9610             mLastDischargeStepLevel = level;
   9611             mMinDischargeStepLevel = level;
   9612             mDischargeStepTracker.clearTime();
   9613             mDailyDischargeStepTracker.clearTime();
   9614             mInitStepMode = mCurStepMode;
   9615             mModStepMode = 0;
   9616             pullPendingStateUpdatesLocked();
   9617             mHistoryCur.batteryLevel = (byte)level;
   9618             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   9619             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
   9620                     + Integer.toHexString(mHistoryCur.states));
   9621             if (reset) {
   9622                 mRecordingHistory = true;
   9623                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
   9624             }
   9625             addHistoryRecordLocked(mSecRealtime, mSecUptime);
   9626             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
   9627             if (screenOn) {
   9628                 mDischargeScreenOnUnplugLevel = level;
   9629                 mDischargeScreenOffUnplugLevel = 0;
   9630             } else {
   9631                 mDischargeScreenOnUnplugLevel = 0;
   9632                 mDischargeScreenOffUnplugLevel = level;
   9633             }
   9634             mDischargeAmountScreenOn = 0;
   9635             mDischargeAmountScreenOff = 0;
   9636             updateTimeBasesLocked(true, !screenOn, uptime, realtime);
   9637         } else {
   9638             mLastChargingStateLevel = level;
   9639             mOnBattery = mOnBatteryInternal = false;
   9640             pullPendingStateUpdatesLocked();
   9641             mHistoryCur.batteryLevel = (byte)level;
   9642             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   9643             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
   9644                     + Integer.toHexString(mHistoryCur.states));
   9645             addHistoryRecordLocked(mSecRealtime, mSecUptime);
   9646             mDischargeCurrentLevel = mDischargePlugLevel = level;
   9647             if (level < mDischargeUnplugLevel) {
   9648                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
   9649                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
   9650             }
   9651             updateDischargeScreenLevelsLocked(screenOn, screenOn);
   9652             updateTimeBasesLocked(false, !screenOn, uptime, realtime);
   9653             mChargeStepTracker.init();
   9654             mLastChargeStepLevel = level;
   9655             mMaxChargeStepLevel = level;
   9656             mInitStepMode = mCurStepMode;
   9657             mModStepMode = 0;
   9658         }
   9659         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
   9660             if (mFile != null) {
   9661                 writeAsyncLocked();
   9662             }
   9663         }
   9664     }
   9665 
   9666     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
   9667             boolean reset) {
   9668         mRecordingHistory = true;
   9669         mHistoryCur.currentTime = System.currentTimeMillis();
   9670         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
   9671                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
   9672                 mHistoryCur);
   9673         mHistoryCur.currentTime = 0;
   9674         if (reset) {
   9675             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
   9676         }
   9677     }
   9678 
   9679     private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
   9680             final long uptimeMs) {
   9681         if (mRecordingHistory) {
   9682             mHistoryCur.currentTime = currentTime;
   9683             addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
   9684                     mHistoryCur);
   9685             mHistoryCur.currentTime = 0;
   9686         }
   9687     }
   9688 
   9689     private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
   9690         if (mRecordingHistory) {
   9691             mHistoryCur.currentTime = System.currentTimeMillis();
   9692             addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_SHUTDOWN,
   9693                     mHistoryCur);
   9694             mHistoryCur.currentTime = 0;
   9695         }
   9696     }
   9697 
   9698     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
   9699         if (mExternalSync != null) {
   9700             mExternalSync.scheduleSync(reason, updateFlags);
   9701         }
   9702     }
   9703 
   9704     // This should probably be exposed in the API, though it's not critical
   9705     public static final int BATTERY_PLUGGED_NONE = 0;
   9706 
   9707     public void setBatteryStateLocked(int status, int health, int plugType, int level,
   9708             int temp, int volt, int chargeUAh) {
   9709         final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
   9710         final long uptime = mClocks.uptimeMillis();
   9711         final long elapsedRealtime = mClocks.elapsedRealtime();
   9712         if (!mHaveBatteryLevel) {
   9713             mHaveBatteryLevel = true;
   9714             // We start out assuming that the device is plugged in (not
   9715             // on battery).  If our first report is now that we are indeed
   9716             // plugged in, then twiddle our state to correctly reflect that
   9717             // since we won't be going through the full setOnBattery().
   9718             if (onBattery == mOnBattery) {
   9719                 if (onBattery) {
   9720                     mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   9721                 } else {
   9722                     mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   9723                 }
   9724             }
   9725             // Always start out assuming charging, that will be updated later.
   9726             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
   9727             mHistoryCur.batteryStatus = (byte)status;
   9728             mHistoryCur.batteryLevel = (byte)level;
   9729             mHistoryCur.batteryChargeUAh = chargeUAh;
   9730             mMaxChargeStepLevel = mMinDischargeStepLevel =
   9731                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
   9732             mLastChargingStateLevel = level;
   9733         } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
   9734             recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
   9735         }
   9736         int oldStatus = mHistoryCur.batteryStatus;
   9737         if (onBattery) {
   9738             mDischargeCurrentLevel = level;
   9739             if (!mRecordingHistory) {
   9740                 mRecordingHistory = true;
   9741                 startRecordingHistory(elapsedRealtime, uptime, true);
   9742             }
   9743         } else if (level < 96) {
   9744             if (!mRecordingHistory) {
   9745                 mRecordingHistory = true;
   9746                 startRecordingHistory(elapsedRealtime, uptime, true);
   9747             }
   9748         }
   9749         mCurrentBatteryLevel = level;
   9750         if (mDischargePlugLevel < 0) {
   9751             mDischargePlugLevel = level;
   9752         }
   9753 
   9754         if (onBattery != mOnBattery) {
   9755             mHistoryCur.batteryLevel = (byte)level;
   9756             mHistoryCur.batteryStatus = (byte)status;
   9757             mHistoryCur.batteryHealth = (byte)health;
   9758             mHistoryCur.batteryPlugType = (byte)plugType;
   9759             mHistoryCur.batteryTemperature = (short)temp;
   9760             mHistoryCur.batteryVoltage = (char)volt;
   9761             if (chargeUAh < mHistoryCur.batteryChargeUAh) {
   9762                 // Only record discharges
   9763                 final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
   9764                 mDischargeCounter.addCountLocked(chargeDiff);
   9765                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
   9766             }
   9767             mHistoryCur.batteryChargeUAh = chargeUAh;
   9768             setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
   9769         } else {
   9770             boolean changed = false;
   9771             if (mHistoryCur.batteryLevel != level) {
   9772                 mHistoryCur.batteryLevel = (byte)level;
   9773                 changed = true;
   9774 
   9775                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
   9776                 // which will pull external stats.
   9777                 scheduleSyncExternalStatsLocked("battery-level", ExternalStatsSync.UPDATE_ALL);
   9778             }
   9779             if (mHistoryCur.batteryStatus != status) {
   9780                 mHistoryCur.batteryStatus = (byte)status;
   9781                 changed = true;
   9782             }
   9783             if (mHistoryCur.batteryHealth != health) {
   9784                 mHistoryCur.batteryHealth = (byte)health;
   9785                 changed = true;
   9786             }
   9787             if (mHistoryCur.batteryPlugType != plugType) {
   9788                 mHistoryCur.batteryPlugType = (byte)plugType;
   9789                 changed = true;
   9790             }
   9791             if (temp >= (mHistoryCur.batteryTemperature+10)
   9792                     || temp <= (mHistoryCur.batteryTemperature-10)) {
   9793                 mHistoryCur.batteryTemperature = (short)temp;
   9794                 changed = true;
   9795             }
   9796             if (volt > (mHistoryCur.batteryVoltage+20)
   9797                     || volt < (mHistoryCur.batteryVoltage-20)) {
   9798                 mHistoryCur.batteryVoltage = (char)volt;
   9799                 changed = true;
   9800             }
   9801             if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
   9802                     || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
   9803                 if (chargeUAh < mHistoryCur.batteryChargeUAh) {
   9804                     // Only record discharges
   9805                     final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
   9806                     mDischargeCounter.addCountLocked(chargeDiff);
   9807                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
   9808                 }
   9809                 mHistoryCur.batteryChargeUAh = chargeUAh;
   9810                 changed = true;
   9811             }
   9812             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
   9813                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
   9814                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
   9815             if (onBattery) {
   9816                 changed |= setChargingLocked(false);
   9817                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
   9818                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
   9819                             modeBits, elapsedRealtime);
   9820                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
   9821                             modeBits, elapsedRealtime);
   9822                     mLastDischargeStepLevel = level;
   9823                     mMinDischargeStepLevel = level;
   9824                     mInitStepMode = mCurStepMode;
   9825                     mModStepMode = 0;
   9826                 }
   9827             } else {
   9828                 if (level >= 90) {
   9829                     // If the battery level is at least 90%, always consider the device to be
   9830                     // charging even if it happens to go down a level.
   9831                     changed |= setChargingLocked(true);
   9832                     mLastChargeStepLevel = level;
   9833                 } if (!mCharging) {
   9834                     if (mLastChargeStepLevel < level) {
   9835                         // We have not reporting that we are charging, but the level has now
   9836                         // gone up, so consider the state to be charging.
   9837                         changed |= setChargingLocked(true);
   9838                         mLastChargeStepLevel = level;
   9839                     }
   9840                 } else {
   9841                     if (mLastChargeStepLevel > level) {
   9842                         // We had reported that the device was charging, but here we are with
   9843                         // power connected and the level going down.  Looks like the current
   9844                         // power supplied isn't enough, so consider the device to now be
   9845                         // discharging.
   9846                         changed |= setChargingLocked(false);
   9847                         mLastChargeStepLevel = level;
   9848                     }
   9849                 }
   9850                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
   9851                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
   9852                             modeBits, elapsedRealtime);
   9853                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
   9854                             modeBits, elapsedRealtime);
   9855                     mLastChargeStepLevel = level;
   9856                     mMaxChargeStepLevel = level;
   9857                     mInitStepMode = mCurStepMode;
   9858                     mModStepMode = 0;
   9859                 }
   9860             }
   9861             if (changed) {
   9862                 addHistoryRecordLocked(elapsedRealtime, uptime);
   9863             }
   9864         }
   9865         if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
   9866             // We don't record history while we are plugged in and fully charged.
   9867             // The next time we are unplugged, history will be cleared.
   9868             mRecordingHistory = DEBUG;
   9869         }
   9870     }
   9871 
   9872     public long getAwakeTimeBattery() {
   9873         return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
   9874     }
   9875 
   9876     public long getAwakeTimePlugged() {
   9877         return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
   9878     }
   9879 
   9880     @Override
   9881     public long computeUptime(long curTime, int which) {
   9882         switch (which) {
   9883             case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
   9884             case STATS_CURRENT: return (curTime-mUptimeStart);
   9885             case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
   9886         }
   9887         return 0;
   9888     }
   9889 
   9890     @Override
   9891     public long computeRealtime(long curTime, int which) {
   9892         switch (which) {
   9893             case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
   9894             case STATS_CURRENT: return (curTime-mRealtimeStart);
   9895             case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
   9896         }
   9897         return 0;
   9898     }
   9899 
   9900     @Override
   9901     public long computeBatteryUptime(long curTime, int which) {
   9902         return mOnBatteryTimeBase.computeUptime(curTime, which);
   9903     }
   9904 
   9905     @Override
   9906     public long computeBatteryRealtime(long curTime, int which) {
   9907         return mOnBatteryTimeBase.computeRealtime(curTime, which);
   9908     }
   9909 
   9910     @Override
   9911     public long computeBatteryScreenOffUptime(long curTime, int which) {
   9912         return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
   9913     }
   9914 
   9915     @Override
   9916     public long computeBatteryScreenOffRealtime(long curTime, int which) {
   9917         return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
   9918     }
   9919 
   9920     private long computeTimePerLevel(long[] steps, int numSteps) {
   9921         // For now we'll do a simple average across all steps.
   9922         if (numSteps <= 0) {
   9923             return -1;
   9924         }
   9925         long total = 0;
   9926         for (int i=0; i<numSteps; i++) {
   9927             total += steps[i] & STEP_LEVEL_TIME_MASK;
   9928         }
   9929         return total / numSteps;
   9930         /*
   9931         long[] buckets = new long[numSteps];
   9932         int numBuckets = 0;
   9933         int numToAverage = 4;
   9934         int i = 0;
   9935         while (i < numSteps) {
   9936             long totalTime = 0;
   9937             int num = 0;
   9938             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
   9939                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
   9940                 num++;
   9941             }
   9942             buckets[numBuckets] = totalTime / num;
   9943             numBuckets++;
   9944             numToAverage *= 2;
   9945             i += num;
   9946         }
   9947         if (numBuckets < 1) {
   9948             return -1;
   9949         }
   9950         long averageTime = buckets[numBuckets-1];
   9951         for (i=numBuckets-2; i>=0; i--) {
   9952             averageTime = (averageTime + buckets[i]) / 2;
   9953         }
   9954         return averageTime;
   9955         */
   9956     }
   9957 
   9958     @Override
   9959     public long computeBatteryTimeRemaining(long curTime) {
   9960         if (!mOnBattery) {
   9961             return -1;
   9962         }
   9963         /* Simple implementation just looks at the average discharge per level across the
   9964            entire sample period.
   9965         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
   9966         if (discharge < 2) {
   9967             return -1;
   9968         }
   9969         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
   9970         if (duration < 1000*1000) {
   9971             return -1;
   9972         }
   9973         long usPerLevel = duration/discharge;
   9974         return usPerLevel * mCurrentBatteryLevel;
   9975         */
   9976         if (mDischargeStepTracker.mNumStepDurations < 1) {
   9977             return -1;
   9978         }
   9979         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
   9980         if (msPerLevel <= 0) {
   9981             return -1;
   9982         }
   9983         return (msPerLevel * mCurrentBatteryLevel) * 1000;
   9984     }
   9985 
   9986     @Override
   9987     public LevelStepTracker getDischargeLevelStepTracker() {
   9988         return mDischargeStepTracker;
   9989     }
   9990 
   9991     @Override
   9992     public LevelStepTracker getDailyDischargeLevelStepTracker() {
   9993         return mDailyDischargeStepTracker;
   9994     }
   9995 
   9996     @Override
   9997     public long computeChargeTimeRemaining(long curTime) {
   9998         if (mOnBattery) {
   9999             // Not yet working.
   10000             return -1;
   10001         }
   10002         /* Broken
   10003         int curLevel = mCurrentBatteryLevel;
   10004         int plugLevel = mDischargePlugLevel;
   10005         if (plugLevel < 0 || curLevel < (plugLevel+1)) {
   10006             return -1;
   10007         }
   10008         long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
   10009         if (duration < 1000*1000) {
   10010             return -1;
   10011         }
   10012         long usPerLevel = duration/(curLevel-plugLevel);
   10013         return usPerLevel * (100-curLevel);
   10014         */
   10015         if (mChargeStepTracker.mNumStepDurations < 1) {
   10016             return -1;
   10017         }
   10018         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
   10019         if (msPerLevel <= 0) {
   10020             return -1;
   10021         }
   10022         return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
   10023     }
   10024 
   10025     @Override
   10026     public LevelStepTracker getChargeLevelStepTracker() {
   10027         return mChargeStepTracker;
   10028     }
   10029 
   10030     @Override
   10031     public LevelStepTracker getDailyChargeLevelStepTracker() {
   10032         return mDailyChargeStepTracker;
   10033     }
   10034 
   10035     @Override
   10036     public ArrayList<PackageChange> getDailyPackageChanges() {
   10037         return mDailyPackageChanges;
   10038     }
   10039 
   10040     protected long getBatteryUptimeLocked() {
   10041         return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
   10042     }
   10043 
   10044     @Override
   10045     public long getBatteryUptime(long curTime) {
   10046         return mOnBatteryTimeBase.getUptime(curTime);
   10047     }
   10048 
   10049     @Override
   10050     public long getBatteryRealtime(long curTime) {
   10051         return mOnBatteryTimeBase.getRealtime(curTime);
   10052     }
   10053 
   10054     @Override
   10055     public int getDischargeStartLevel() {
   10056         synchronized(this) {
   10057             return getDischargeStartLevelLocked();
   10058         }
   10059     }
   10060 
   10061     public int getDischargeStartLevelLocked() {
   10062             return mDischargeUnplugLevel;
   10063     }
   10064 
   10065     @Override
   10066     public int getDischargeCurrentLevel() {
   10067         synchronized(this) {
   10068             return getDischargeCurrentLevelLocked();
   10069         }
   10070     }
   10071 
   10072     public int getDischargeCurrentLevelLocked() {
   10073         return mDischargeCurrentLevel;
   10074     }
   10075 
   10076     @Override
   10077     public int getLowDischargeAmountSinceCharge() {
   10078         synchronized(this) {
   10079             int val = mLowDischargeAmountSinceCharge;
   10080             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
   10081                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
   10082             }
   10083             return val;
   10084         }
   10085     }
   10086 
   10087     @Override
   10088     public int getHighDischargeAmountSinceCharge() {
   10089         synchronized(this) {
   10090             int val = mHighDischargeAmountSinceCharge;
   10091             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
   10092                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
   10093             }
   10094             return val;
   10095         }
   10096     }
   10097 
   10098     @Override
   10099     public int getDischargeAmount(int which) {
   10100         int dischargeAmount = which == STATS_SINCE_CHARGED
   10101                 ? getHighDischargeAmountSinceCharge()
   10102                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
   10103         if (dischargeAmount < 0) {
   10104             dischargeAmount = 0;
   10105         }
   10106         return dischargeAmount;
   10107     }
   10108 
   10109     public int getDischargeAmountScreenOn() {
   10110         synchronized(this) {
   10111             int val = mDischargeAmountScreenOn;
   10112             if (mOnBattery && mScreenState == Display.STATE_ON
   10113                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
   10114                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
   10115             }
   10116             return val;
   10117         }
   10118     }
   10119 
   10120     public int getDischargeAmountScreenOnSinceCharge() {
   10121         synchronized(this) {
   10122             int val = mDischargeAmountScreenOnSinceCharge;
   10123             if (mOnBattery && mScreenState == Display.STATE_ON
   10124                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
   10125                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
   10126             }
   10127             return val;
   10128         }
   10129     }
   10130 
   10131     public int getDischargeAmountScreenOff() {
   10132         synchronized(this) {
   10133             int val = mDischargeAmountScreenOff;
   10134             if (mOnBattery && mScreenState != Display.STATE_ON
   10135                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
   10136                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
   10137             }
   10138             return val;
   10139         }
   10140     }
   10141 
   10142     public int getDischargeAmountScreenOffSinceCharge() {
   10143         synchronized(this) {
   10144             int val = mDischargeAmountScreenOffSinceCharge;
   10145             if (mOnBattery && mScreenState != Display.STATE_ON
   10146                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
   10147                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
   10148             }
   10149             return val;
   10150         }
   10151     }
   10152 
   10153     /**
   10154      * Retrieve the statistics object for a particular uid, creating if needed.
   10155      */
   10156     public Uid getUidStatsLocked(int uid) {
   10157         Uid u = mUidStats.get(uid);
   10158         if (u == null) {
   10159             u = new Uid(this, uid);
   10160             mUidStats.put(uid, u);
   10161         }
   10162         return u;
   10163     }
   10164 
   10165     /**
   10166      * Remove the statistics object for a particular uid.
   10167      */
   10168     public void removeUidStatsLocked(int uid) {
   10169         mKernelUidCpuTimeReader.removeUid(uid);
   10170         mUidStats.remove(uid);
   10171     }
   10172 
   10173     /**
   10174      * Retrieve the statistics object for a particular process, creating
   10175      * if needed.
   10176      */
   10177     public Uid.Proc getProcessStatsLocked(int uid, String name) {
   10178         uid = mapUid(uid);
   10179         Uid u = getUidStatsLocked(uid);
   10180         return u.getProcessStatsLocked(name);
   10181     }
   10182 
   10183     /**
   10184      * Retrieve the statistics object for a particular process, creating
   10185      * if needed.
   10186      */
   10187     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
   10188         uid = mapUid(uid);
   10189         Uid u = getUidStatsLocked(uid);
   10190         return u.getPackageStatsLocked(pkg);
   10191     }
   10192 
   10193     /**
   10194      * Retrieve the statistics object for a particular service, creating
   10195      * if needed.
   10196      */
   10197     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
   10198         uid = mapUid(uid);
   10199         Uid u = getUidStatsLocked(uid);
   10200         return u.getServiceStatsLocked(pkg, name);
   10201     }
   10202 
   10203     public void shutdownLocked() {
   10204         recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
   10205         writeSyncLocked();
   10206         mShuttingDown = true;
   10207     }
   10208 
   10209     Parcel mPendingWrite = null;
   10210     final ReentrantLock mWriteLock = new ReentrantLock();
   10211 
   10212     public void writeAsyncLocked() {
   10213         writeLocked(false);
   10214     }
   10215 
   10216     public void writeSyncLocked() {
   10217         writeLocked(true);
   10218     }
   10219 
   10220     void writeLocked(boolean sync) {
   10221         if (mFile == null) {
   10222             Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
   10223             return;
   10224         }
   10225 
   10226         if (mShuttingDown) {
   10227             return;
   10228         }
   10229 
   10230         Parcel out = Parcel.obtain();
   10231         writeSummaryToParcel(out, true);
   10232         mLastWriteTime = mClocks.elapsedRealtime();
   10233 
   10234         if (mPendingWrite != null) {
   10235             mPendingWrite.recycle();
   10236         }
   10237         mPendingWrite = out;
   10238 
   10239         if (sync) {
   10240             commitPendingDataToDisk();
   10241         } else {
   10242             BackgroundThread.getHandler().post(new Runnable() {
   10243                 @Override public void run() {
   10244                     commitPendingDataToDisk();
   10245                 }
   10246             });
   10247         }
   10248     }
   10249 
   10250     public void commitPendingDataToDisk() {
   10251         final Parcel next;
   10252         synchronized (this) {
   10253             next = mPendingWrite;
   10254             mPendingWrite = null;
   10255             if (next == null) {
   10256                 return;
   10257             }
   10258 
   10259             mWriteLock.lock();
   10260         }
   10261 
   10262         try {
   10263             FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
   10264             stream.write(next.marshall());
   10265             stream.flush();
   10266             FileUtils.sync(stream);
   10267             stream.close();
   10268             mFile.commit();
   10269         } catch (IOException e) {
   10270             Slog.w("BatteryStats", "Error writing battery statistics", e);
   10271             mFile.rollback();
   10272         } finally {
   10273             next.recycle();
   10274             mWriteLock.unlock();
   10275         }
   10276     }
   10277 
   10278     public void readLocked() {
   10279         if (mDailyFile != null) {
   10280             readDailyStatsLocked();
   10281         }
   10282 
   10283         if (mFile == null) {
   10284             Slog.w("BatteryStats", "readLocked: no file associated with this instance");
   10285             return;
   10286         }
   10287 
   10288         mUidStats.clear();
   10289 
   10290         try {
   10291             File file = mFile.chooseForRead();
   10292             if (!file.exists()) {
   10293                 return;
   10294             }
   10295             FileInputStream stream = new FileInputStream(file);
   10296 
   10297             byte[] raw = BatteryStatsHelper.readFully(stream);
   10298             Parcel in = Parcel.obtain();
   10299             in.unmarshall(raw, 0, raw.length);
   10300             in.setDataPosition(0);
   10301             stream.close();
   10302 
   10303             readSummaryFromParcel(in);
   10304         } catch(Exception e) {
   10305             Slog.e("BatteryStats", "Error reading battery statistics", e);
   10306             resetAllStatsLocked();
   10307         }
   10308 
   10309         mEndPlatformVersion = Build.ID;
   10310 
   10311         if (mHistoryBuffer.dataPosition() > 0) {
   10312             mRecordingHistory = true;
   10313             final long elapsedRealtime = mClocks.elapsedRealtime();
   10314             final long uptime = mClocks.uptimeMillis();
   10315             if (USE_OLD_HISTORY) {
   10316                 addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
   10317             }
   10318             addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
   10319             startRecordingHistory(elapsedRealtime, uptime, false);
   10320         }
   10321 
   10322         recordDailyStatsIfNeededLocked(false);
   10323     }
   10324 
   10325     public int describeContents() {
   10326         return 0;
   10327     }
   10328 
   10329     void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
   10330         final long historyBaseTime = in.readLong();
   10331 
   10332         mHistoryBuffer.setDataSize(0);
   10333         mHistoryBuffer.setDataPosition(0);
   10334         mHistoryTagPool.clear();
   10335         mNextHistoryTagIdx = 0;
   10336         mNumHistoryTagChars = 0;
   10337 
   10338         int numTags = in.readInt();
   10339         for (int i=0; i<numTags; i++) {
   10340             int idx = in.readInt();
   10341             String str = in.readString();
   10342             if (str == null) {
   10343                 throw new ParcelFormatException("null history tag string");
   10344             }
   10345             int uid = in.readInt();
   10346             HistoryTag tag = new HistoryTag();
   10347             tag.string = str;
   10348             tag.uid = uid;
   10349             tag.poolIdx = idx;
   10350             mHistoryTagPool.put(tag, idx);
   10351             if (idx >= mNextHistoryTagIdx) {
   10352                 mNextHistoryTagIdx = idx+1;
   10353             }
   10354             mNumHistoryTagChars += tag.string.length() + 1;
   10355         }
   10356 
   10357         int bufSize = in.readInt();
   10358         int curPos = in.dataPosition();
   10359         if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
   10360             throw new ParcelFormatException("File corrupt: history data buffer too large " +
   10361                     bufSize);
   10362         } else if ((bufSize&~3) != bufSize) {
   10363             throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
   10364                     bufSize);
   10365         } else {
   10366             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
   10367                     + " bytes at " + curPos);
   10368             mHistoryBuffer.appendFrom(in, curPos, bufSize);
   10369             in.setDataPosition(curPos + bufSize);
   10370         }
   10371 
   10372         if (andOldHistory) {
   10373             readOldHistory(in);
   10374         }
   10375 
   10376         if (DEBUG_HISTORY) {
   10377             StringBuilder sb = new StringBuilder(128);
   10378             sb.append("****************** OLD mHistoryBaseTime: ");
   10379             TimeUtils.formatDuration(mHistoryBaseTime, sb);
   10380             Slog.i(TAG, sb.toString());
   10381         }
   10382         mHistoryBaseTime = historyBaseTime;
   10383         if (DEBUG_HISTORY) {
   10384             StringBuilder sb = new StringBuilder(128);
   10385             sb.append("****************** NEW mHistoryBaseTime: ");
   10386             TimeUtils.formatDuration(mHistoryBaseTime, sb);
   10387             Slog.i(TAG, sb.toString());
   10388         }
   10389 
   10390         // We are just arbitrarily going to insert 1 minute from the sample of
   10391         // the last run until samples in this run.
   10392         if (mHistoryBaseTime > 0) {
   10393             long oldnow = mClocks.elapsedRealtime();
   10394             mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
   10395             if (DEBUG_HISTORY) {
   10396                 StringBuilder sb = new StringBuilder(128);
   10397                 sb.append("****************** ADJUSTED mHistoryBaseTime: ");
   10398                 TimeUtils.formatDuration(mHistoryBaseTime, sb);
   10399                 Slog.i(TAG, sb.toString());
   10400             }
   10401         }
   10402     }
   10403 
   10404     void readOldHistory(Parcel in) {
   10405         if (!USE_OLD_HISTORY) {
   10406             return;
   10407         }
   10408         mHistory = mHistoryEnd = mHistoryCache = null;
   10409         long time;
   10410         while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
   10411             HistoryItem rec = new HistoryItem(time, in);
   10412             addHistoryRecordLocked(rec);
   10413         }
   10414     }
   10415 
   10416     void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
   10417         if (DEBUG_HISTORY) {
   10418             StringBuilder sb = new StringBuilder(128);
   10419             sb.append("****************** WRITING mHistoryBaseTime: ");
   10420             TimeUtils.formatDuration(mHistoryBaseTime, sb);
   10421             sb.append(" mLastHistoryElapsedRealtime: ");
   10422             TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
   10423             Slog.i(TAG, sb.toString());
   10424         }
   10425         out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
   10426         if (!inclData) {
   10427             out.writeInt(0);
   10428             out.writeInt(0);
   10429             return;
   10430         }
   10431         out.writeInt(mHistoryTagPool.size());
   10432         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
   10433             HistoryTag tag = ent.getKey();
   10434             out.writeInt(ent.getValue());
   10435             out.writeString(tag.string);
   10436             out.writeInt(tag.uid);
   10437         }
   10438         out.writeInt(mHistoryBuffer.dataSize());
   10439         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
   10440                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
   10441         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
   10442 
   10443         if (andOldHistory) {
   10444             writeOldHistory(out);
   10445         }
   10446     }
   10447 
   10448     void writeOldHistory(Parcel out) {
   10449         if (!USE_OLD_HISTORY) {
   10450             return;
   10451         }
   10452         HistoryItem rec = mHistory;
   10453         while (rec != null) {
   10454             if (rec.time >= 0) rec.writeToParcel(out, 0);
   10455             rec = rec.next;
   10456         }
   10457         out.writeLong(-1);
   10458     }
   10459 
   10460     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
   10461         final int version = in.readInt();
   10462         if (version != VERSION) {
   10463             Slog.w("BatteryStats", "readFromParcel: version got " + version
   10464                 + ", expected " + VERSION + "; erasing old stats");
   10465             return;
   10466         }
   10467 
   10468         readHistory(in, true);
   10469 
   10470         mStartCount = in.readInt();
   10471         mUptime = in.readLong();
   10472         mRealtime = in.readLong();
   10473         mStartClockTime = in.readLong();
   10474         mStartPlatformVersion = in.readString();
   10475         mEndPlatformVersion = in.readString();
   10476         mOnBatteryTimeBase.readSummaryFromParcel(in);
   10477         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
   10478         mDischargeUnplugLevel = in.readInt();
   10479         mDischargePlugLevel = in.readInt();
   10480         mDischargeCurrentLevel = in.readInt();
   10481         mCurrentBatteryLevel = in.readInt();
   10482         mEstimatedBatteryCapacity = in.readInt();
   10483         mLowDischargeAmountSinceCharge = in.readInt();
   10484         mHighDischargeAmountSinceCharge = in.readInt();
   10485         mDischargeAmountScreenOnSinceCharge = in.readInt();
   10486         mDischargeAmountScreenOffSinceCharge = in.readInt();
   10487         mDischargeStepTracker.readFromParcel(in);
   10488         mChargeStepTracker.readFromParcel(in);
   10489         mDailyDischargeStepTracker.readFromParcel(in);
   10490         mDailyChargeStepTracker.readFromParcel(in);
   10491         mDischargeCounter.readSummaryFromParcelLocked(in);
   10492         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
   10493         int NPKG = in.readInt();
   10494         if (NPKG > 0) {
   10495             mDailyPackageChanges = new ArrayList<>(NPKG);
   10496             while (NPKG > 0) {
   10497                 NPKG--;
   10498                 PackageChange pc = new PackageChange();
   10499                 pc.mPackageName = in.readString();
   10500                 pc.mUpdate = in.readInt() != 0;
   10501                 pc.mVersionCode = in.readInt();
   10502                 mDailyPackageChanges.add(pc);
   10503             }
   10504         } else {
   10505             mDailyPackageChanges = null;
   10506         }
   10507         mDailyStartTime = in.readLong();
   10508         mNextMinDailyDeadline = in.readLong();
   10509         mNextMaxDailyDeadline = in.readLong();
   10510 
   10511         mStartCount++;
   10512 
   10513         mScreenState = Display.STATE_UNKNOWN;
   10514         mScreenOnTimer.readSummaryFromParcelLocked(in);
   10515         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   10516             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
   10517         }
   10518         mInteractive = false;
   10519         mInteractiveTimer.readSummaryFromParcelLocked(in);
   10520         mPhoneOn = false;
   10521         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
   10522         mLongestLightIdleTime = in.readLong();
   10523         mLongestFullIdleTime = in.readLong();
   10524         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
   10525         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
   10526         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
   10527         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
   10528         mPhoneOnTimer.readSummaryFromParcelLocked(in);
   10529         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   10530             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
   10531         }
   10532         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
   10533         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   10534             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
   10535         }
   10536         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   10537             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
   10538             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
   10539         }
   10540         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
   10541         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
   10542         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
   10543         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
   10544         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
   10545         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
   10546         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
   10547         mWifiOn = false;
   10548         mWifiOnTimer.readSummaryFromParcelLocked(in);
   10549         mGlobalWifiRunning = false;
   10550         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
   10551         for (int i=0; i<NUM_WIFI_STATES; i++) {
   10552             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
   10553         }
   10554         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   10555             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
   10556         }
   10557         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   10558             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
   10559         }
   10560         mWifiActivity.readSummaryFromParcel(in);
   10561         mBluetoothActivity.readSummaryFromParcel(in);
   10562         mModemActivity.readSummaryFromParcel(in);
   10563         mHasWifiReporting = in.readInt() != 0;
   10564         mHasBluetoothReporting = in.readInt() != 0;
   10565         mHasModemReporting = in.readInt() != 0;
   10566 
   10567         mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
   10568         mFlashlightOnNesting = 0;
   10569         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
   10570         mCameraOnNesting = 0;
   10571         mCameraOnTimer.readSummaryFromParcelLocked(in);
   10572         mBluetoothScanNesting = 0;
   10573         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
   10574 
   10575         int NKW = in.readInt();
   10576         if (NKW > 10000) {
   10577             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
   10578         }
   10579         for (int ikw = 0; ikw < NKW; ikw++) {
   10580             if (in.readInt() != 0) {
   10581                 String kwltName = in.readString();
   10582                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
   10583             }
   10584         }
   10585 
   10586         int NWR = in.readInt();
   10587         if (NWR > 10000) {
   10588             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
   10589         }
   10590         for (int iwr = 0; iwr < NWR; iwr++) {
   10591             if (in.readInt() != 0) {
   10592                 String reasonName = in.readString();
   10593                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
   10594             }
   10595         }
   10596 
   10597         final int NU = in.readInt();
   10598         if (NU > 10000) {
   10599             throw new ParcelFormatException("File corrupt: too many uids " + NU);
   10600         }
   10601         for (int iu = 0; iu < NU; iu++) {
   10602             int uid = in.readInt();
   10603             Uid u = new Uid(this, uid);
   10604             mUidStats.put(uid, u);
   10605 
   10606             u.mWifiRunning = false;
   10607             if (in.readInt() != 0) {
   10608                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
   10609             }
   10610             u.mFullWifiLockOut = false;
   10611             if (in.readInt() != 0) {
   10612                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
   10613             }
   10614             u.mWifiScanStarted = false;
   10615             if (in.readInt() != 0) {
   10616                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
   10617             }
   10618             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
   10619             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   10620                 if (in.readInt() != 0) {
   10621                     u.makeWifiBatchedScanBin(i, null);
   10622                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
   10623                 }
   10624             }
   10625             u.mWifiMulticastEnabled = false;
   10626             if (in.readInt() != 0) {
   10627                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
   10628             }
   10629             if (in.readInt() != 0) {
   10630                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
   10631             }
   10632             if (in.readInt() != 0) {
   10633                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
   10634             }
   10635             if (in.readInt() != 0) {
   10636                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
   10637             }
   10638             if (in.readInt() != 0) {
   10639                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
   10640             }
   10641             if (in.readInt() != 0) {
   10642                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
   10643             }
   10644             if (in.readInt() != 0) {
   10645                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
   10646             }
   10647             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
   10648             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
   10649                 if (in.readInt() != 0) {
   10650                     u.makeProcessState(i, null);
   10651                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
   10652                 }
   10653             }
   10654             if (in.readInt() != 0) {
   10655                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
   10656             }
   10657 
   10658             if (in.readInt() != 0) {
   10659                 if (u.mUserActivityCounters == null) {
   10660                     u.initUserActivityLocked();
   10661                 }
   10662                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
   10663                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
   10664                 }
   10665             }
   10666 
   10667             if (in.readInt() != 0) {
   10668                 if (u.mNetworkByteActivityCounters == null) {
   10669                     u.initNetworkActivityLocked();
   10670                 }
   10671                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   10672                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
   10673                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
   10674                 }
   10675                 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
   10676                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
   10677             }
   10678 
   10679             u.mUserCpuTime.readSummaryFromParcelLocked(in);
   10680             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
   10681             u.mCpuPower.readSummaryFromParcelLocked(in);
   10682 
   10683             if (in.readInt() != 0) {
   10684                 final int numClusters = in.readInt();
   10685                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
   10686                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
   10687                 }
   10688 
   10689                 u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
   10690                 for (int cluster = 0; cluster < numClusters; cluster++) {
   10691                     if (in.readInt() != 0) {
   10692                         final int NSB = in.readInt();
   10693                         if (mPowerProfile != null &&
   10694                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
   10695                             throw new ParcelFormatException("File corrupt: too many speed bins " +
   10696                                     NSB);
   10697                         }
   10698 
   10699                         u.mCpuClusterSpeed[cluster] = new LongSamplingCounter[NSB];
   10700                         for (int speed = 0; speed < NSB; speed++) {
   10701                             if (in.readInt() != 0) {
   10702                                 u.mCpuClusterSpeed[cluster][speed] = new LongSamplingCounter(
   10703                                         mOnBatteryTimeBase);
   10704                                 u.mCpuClusterSpeed[cluster][speed].readSummaryFromParcelLocked(in);
   10705                             }
   10706                         }
   10707                     } else {
   10708                         u.mCpuClusterSpeed[cluster] = null;
   10709                     }
   10710                 }
   10711             } else {
   10712                 u.mCpuClusterSpeed = null;
   10713             }
   10714 
   10715             if (in.readInt() != 0) {
   10716                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
   10717                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
   10718             } else {
   10719                 u.mMobileRadioApWakeupCount = null;
   10720             }
   10721 
   10722             if (in.readInt() != 0) {
   10723                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
   10724                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
   10725             } else {
   10726                 u.mWifiRadioApWakeupCount = null;
   10727             }
   10728 
   10729             int NW = in.readInt();
   10730             if (NW > 100) {
   10731                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
   10732             }
   10733             for (int iw = 0; iw < NW; iw++) {
   10734                 String wlName = in.readString();
   10735                 u.readWakeSummaryFromParcelLocked(wlName, in);
   10736             }
   10737 
   10738             int NS = in.readInt();
   10739             if (NS > 100) {
   10740                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
   10741             }
   10742             for (int is = 0; is < NS; is++) {
   10743                 String name = in.readString();
   10744                 u.readSyncSummaryFromParcelLocked(name, in);
   10745             }
   10746 
   10747             int NJ = in.readInt();
   10748             if (NJ > 100) {
   10749                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
   10750             }
   10751             for (int ij = 0; ij < NJ; ij++) {
   10752                 String name = in.readString();
   10753                 u.readJobSummaryFromParcelLocked(name, in);
   10754             }
   10755 
   10756             int NP = in.readInt();
   10757             if (NP > 1000) {
   10758                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
   10759             }
   10760             for (int is = 0; is < NP; is++) {
   10761                 int seNumber = in.readInt();
   10762                 if (in.readInt() != 0) {
   10763                     u.getSensorTimerLocked(seNumber, true)
   10764                             .readSummaryFromParcelLocked(in);
   10765                 }
   10766             }
   10767 
   10768             NP = in.readInt();
   10769             if (NP > 1000) {
   10770                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
   10771             }
   10772             for (int ip = 0; ip < NP; ip++) {
   10773                 String procName = in.readString();
   10774                 Uid.Proc p = u.getProcessStatsLocked(procName);
   10775                 p.mUserTime = p.mLoadedUserTime = in.readLong();
   10776                 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
   10777                 p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
   10778                 p.mStarts = p.mLoadedStarts = in.readInt();
   10779                 p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
   10780                 p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
   10781                 p.readExcessivePowerFromParcelLocked(in);
   10782             }
   10783 
   10784             NP = in.readInt();
   10785             if (NP > 10000) {
   10786                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
   10787             }
   10788             for (int ip = 0; ip < NP; ip++) {
   10789                 String pkgName = in.readString();
   10790                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
   10791                 final int NWA = in.readInt();
   10792                 if (NWA > 1000) {
   10793                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
   10794                 }
   10795                 p.mWakeupAlarms.clear();
   10796                 for (int iwa=0; iwa<NWA; iwa++) {
   10797                     String tag = in.readString();
   10798                     Counter c = new Counter(mOnBatteryTimeBase);
   10799                     c.readSummaryFromParcelLocked(in);
   10800                     p.mWakeupAlarms.put(tag, c);
   10801                 }
   10802                 NS = in.readInt();
   10803                 if (NS > 1000) {
   10804                     throw new ParcelFormatException("File corrupt: too many services " + NS);
   10805                 }
   10806                 for (int is = 0; is < NS; is++) {
   10807                     String servName = in.readString();
   10808                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
   10809                     s.mStartTime = s.mLoadedStartTime = in.readLong();
   10810                     s.mStarts = s.mLoadedStarts = in.readInt();
   10811                     s.mLaunches = s.mLoadedLaunches = in.readInt();
   10812                 }
   10813             }
   10814         }
   10815     }
   10816 
   10817     /**
   10818      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
   10819      * disk.  This format does not allow a lossless round-trip.
   10820      *
   10821      * @param out the Parcel to be written to.
   10822      */
   10823     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
   10824         pullPendingStateUpdatesLocked();
   10825 
   10826         // Pull the clock time.  This may update the time and make a new history entry
   10827         // if we had originally pulled a time before the RTC was set.
   10828         long startClockTime = getStartClockTime();
   10829 
   10830         final long NOW_SYS = mClocks.uptimeMillis() * 1000;
   10831         final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
   10832 
   10833         out.writeInt(VERSION);
   10834 
   10835         writeHistory(out, inclHistory, true);
   10836 
   10837         out.writeInt(mStartCount);
   10838         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
   10839         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
   10840         out.writeLong(startClockTime);
   10841         out.writeString(mStartPlatformVersion);
   10842         out.writeString(mEndPlatformVersion);
   10843         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
   10844         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
   10845         out.writeInt(mDischargeUnplugLevel);
   10846         out.writeInt(mDischargePlugLevel);
   10847         out.writeInt(mDischargeCurrentLevel);
   10848         out.writeInt(mCurrentBatteryLevel);
   10849         out.writeInt(mEstimatedBatteryCapacity);
   10850         out.writeInt(getLowDischargeAmountSinceCharge());
   10851         out.writeInt(getHighDischargeAmountSinceCharge());
   10852         out.writeInt(getDischargeAmountScreenOnSinceCharge());
   10853         out.writeInt(getDischargeAmountScreenOffSinceCharge());
   10854         mDischargeStepTracker.writeToParcel(out);
   10855         mChargeStepTracker.writeToParcel(out);
   10856         mDailyDischargeStepTracker.writeToParcel(out);
   10857         mDailyChargeStepTracker.writeToParcel(out);
   10858         mDischargeCounter.writeSummaryFromParcelLocked(out);
   10859         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
   10860         if (mDailyPackageChanges != null) {
   10861             final int NPKG = mDailyPackageChanges.size();
   10862             out.writeInt(NPKG);
   10863             for (int i=0; i<NPKG; i++) {
   10864                 PackageChange pc = mDailyPackageChanges.get(i);
   10865                 out.writeString(pc.mPackageName);
   10866                 out.writeInt(pc.mUpdate ? 1 : 0);
   10867                 out.writeInt(pc.mVersionCode);
   10868             }
   10869         } else {
   10870             out.writeInt(0);
   10871         }
   10872         out.writeLong(mDailyStartTime);
   10873         out.writeLong(mNextMinDailyDeadline);
   10874         out.writeLong(mNextMaxDailyDeadline);
   10875 
   10876         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10877         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   10878             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10879         }
   10880         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10881         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10882         out.writeLong(mLongestLightIdleTime);
   10883         out.writeLong(mLongestFullIdleTime);
   10884         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10885         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10886         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10887         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10888         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10889         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   10890             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10891         }
   10892         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10893         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   10894             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10895         }
   10896         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   10897             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
   10898             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
   10899         }
   10900         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10901         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10902         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
   10903         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
   10904         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
   10905         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10906         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10907         for (int i=0; i<NUM_WIFI_STATES; i++) {
   10908             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10909         }
   10910         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   10911             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10912         }
   10913         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   10914             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10915         }
   10916         mWifiActivity.writeSummaryToParcel(out);
   10917         mBluetoothActivity.writeSummaryToParcel(out);
   10918         mModemActivity.writeSummaryToParcel(out);
   10919         out.writeInt(mHasWifiReporting ? 1 : 0);
   10920         out.writeInt(mHasBluetoothReporting ? 1 : 0);
   10921         out.writeInt(mHasModemReporting ? 1 : 0);
   10922 
   10923         out.writeInt(mNumConnectivityChange);
   10924         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10925         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10926         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10927 
   10928         out.writeInt(mKernelWakelockStats.size());
   10929         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
   10930             Timer kwlt = ent.getValue();
   10931             if (kwlt != null) {
   10932                 out.writeInt(1);
   10933                 out.writeString(ent.getKey());
   10934                 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10935             } else {
   10936                 out.writeInt(0);
   10937             }
   10938         }
   10939 
   10940         out.writeInt(mWakeupReasonStats.size());
   10941         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
   10942             SamplingTimer timer = ent.getValue();
   10943             if (timer != null) {
   10944                 out.writeInt(1);
   10945                 out.writeString(ent.getKey());
   10946                 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10947             } else {
   10948                 out.writeInt(0);
   10949             }
   10950         }
   10951 
   10952         final int NU = mUidStats.size();
   10953         out.writeInt(NU);
   10954         for (int iu = 0; iu < NU; iu++) {
   10955             out.writeInt(mUidStats.keyAt(iu));
   10956             Uid u = mUidStats.valueAt(iu);
   10957 
   10958             if (u.mWifiRunningTimer != null) {
   10959                 out.writeInt(1);
   10960                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10961             } else {
   10962                 out.writeInt(0);
   10963             }
   10964             if (u.mFullWifiLockTimer != null) {
   10965                 out.writeInt(1);
   10966                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10967             } else {
   10968                 out.writeInt(0);
   10969             }
   10970             if (u.mWifiScanTimer != null) {
   10971                 out.writeInt(1);
   10972                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10973             } else {
   10974                 out.writeInt(0);
   10975             }
   10976             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   10977                 if (u.mWifiBatchedScanTimer[i] != null) {
   10978                     out.writeInt(1);
   10979                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10980                 } else {
   10981                     out.writeInt(0);
   10982                 }
   10983             }
   10984             if (u.mWifiMulticastTimer != null) {
   10985                 out.writeInt(1);
   10986                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10987             } else {
   10988                 out.writeInt(0);
   10989             }
   10990             if (u.mAudioTurnedOnTimer != null) {
   10991                 out.writeInt(1);
   10992                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10993             } else {
   10994                 out.writeInt(0);
   10995             }
   10996             if (u.mVideoTurnedOnTimer != null) {
   10997                 out.writeInt(1);
   10998                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   10999             } else {
   11000                 out.writeInt(0);
   11001             }
   11002             if (u.mFlashlightTurnedOnTimer != null) {
   11003                 out.writeInt(1);
   11004                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11005             } else {
   11006                 out.writeInt(0);
   11007             }
   11008             if (u.mCameraTurnedOnTimer != null) {
   11009                 out.writeInt(1);
   11010                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11011             } else {
   11012                 out.writeInt(0);
   11013             }
   11014             if (u.mForegroundActivityTimer != null) {
   11015                 out.writeInt(1);
   11016                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11017             } else {
   11018                 out.writeInt(0);
   11019             }
   11020             if (u.mBluetoothScanTimer != null) {
   11021                 out.writeInt(1);
   11022                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11023             } else {
   11024                 out.writeInt(0);
   11025             }
   11026             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
   11027                 if (u.mProcessStateTimer[i] != null) {
   11028                     out.writeInt(1);
   11029                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11030                 } else {
   11031                     out.writeInt(0);
   11032                 }
   11033             }
   11034             if (u.mVibratorOnTimer != null) {
   11035                 out.writeInt(1);
   11036                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11037             } else {
   11038                 out.writeInt(0);
   11039             }
   11040 
   11041             if (u.mUserActivityCounters == null) {
   11042                 out.writeInt(0);
   11043             } else {
   11044                 out.writeInt(1);
   11045                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
   11046                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
   11047                 }
   11048             }
   11049 
   11050             if (u.mNetworkByteActivityCounters == null) {
   11051                 out.writeInt(0);
   11052             } else {
   11053                 out.writeInt(1);
   11054                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   11055                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
   11056                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
   11057                 }
   11058                 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
   11059                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
   11060             }
   11061 
   11062             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
   11063             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
   11064             u.mCpuPower.writeSummaryFromParcelLocked(out);
   11065 
   11066             if (u.mCpuClusterSpeed != null) {
   11067                 out.writeInt(1);
   11068                 out.writeInt(u.mCpuClusterSpeed.length);
   11069                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeed) {
   11070                     if (cpuSpeeds != null) {
   11071                         out.writeInt(1);
   11072                         out.writeInt(cpuSpeeds.length);
   11073                         for (LongSamplingCounter c : cpuSpeeds) {
   11074                             if (c != null) {
   11075                                 out.writeInt(1);
   11076                                 c.writeSummaryFromParcelLocked(out);
   11077                             } else {
   11078                                 out.writeInt(0);
   11079                             }
   11080                         }
   11081                     } else {
   11082                         out.writeInt(0);
   11083                     }
   11084                 }
   11085             } else {
   11086                 out.writeInt(0);
   11087             }
   11088 
   11089             if (u.mMobileRadioApWakeupCount != null) {
   11090                 out.writeInt(1);
   11091                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
   11092             } else {
   11093                 out.writeInt(0);
   11094             }
   11095 
   11096             if (u.mWifiRadioApWakeupCount != null) {
   11097                 out.writeInt(1);
   11098                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
   11099             } else {
   11100                 out.writeInt(0);
   11101             }
   11102 
   11103             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
   11104             int NW = wakeStats.size();
   11105             out.writeInt(NW);
   11106             for (int iw=0; iw<NW; iw++) {
   11107                 out.writeString(wakeStats.keyAt(iw));
   11108                 Uid.Wakelock wl = wakeStats.valueAt(iw);
   11109                 if (wl.mTimerFull != null) {
   11110                     out.writeInt(1);
   11111                     wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11112                 } else {
   11113                     out.writeInt(0);
   11114                 }
   11115                 if (wl.mTimerPartial != null) {
   11116                     out.writeInt(1);
   11117                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11118                 } else {
   11119                     out.writeInt(0);
   11120                 }
   11121                 if (wl.mTimerWindow != null) {
   11122                     out.writeInt(1);
   11123                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11124                 } else {
   11125                     out.writeInt(0);
   11126                 }
   11127                 if (wl.mTimerDraw != null) {
   11128                     out.writeInt(1);
   11129                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11130                 } else {
   11131                     out.writeInt(0);
   11132                 }
   11133             }
   11134 
   11135             final ArrayMap<String, StopwatchTimer> syncStats = u.mSyncStats.getMap();
   11136             int NS = syncStats.size();
   11137             out.writeInt(NS);
   11138             for (int is=0; is<NS; is++) {
   11139                 out.writeString(syncStats.keyAt(is));
   11140                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11141             }
   11142 
   11143             final ArrayMap<String, StopwatchTimer> jobStats = u.mJobStats.getMap();
   11144             int NJ = jobStats.size();
   11145             out.writeInt(NJ);
   11146             for (int ij=0; ij<NJ; ij++) {
   11147                 out.writeString(jobStats.keyAt(ij));
   11148                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11149             }
   11150 
   11151             int NSE = u.mSensorStats.size();
   11152             out.writeInt(NSE);
   11153             for (int ise=0; ise<NSE; ise++) {
   11154                 out.writeInt(u.mSensorStats.keyAt(ise));
   11155                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
   11156                 if (se.mTimer != null) {
   11157                     out.writeInt(1);
   11158                     se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   11159                 } else {
   11160                     out.writeInt(0);
   11161                 }
   11162             }
   11163 
   11164             int NP = u.mProcessStats.size();
   11165             out.writeInt(NP);
   11166             for (int ip=0; ip<NP; ip++) {
   11167                 out.writeString(u.mProcessStats.keyAt(ip));
   11168                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
   11169                 out.writeLong(ps.mUserTime);
   11170                 out.writeLong(ps.mSystemTime);
   11171                 out.writeLong(ps.mForegroundTime);
   11172                 out.writeInt(ps.mStarts);
   11173                 out.writeInt(ps.mNumCrashes);
   11174                 out.writeInt(ps.mNumAnrs);
   11175                 ps.writeExcessivePowerToParcelLocked(out);
   11176             }
   11177 
   11178             NP = u.mPackageStats.size();
   11179             out.writeInt(NP);
   11180             if (NP > 0) {
   11181                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
   11182                     : u.mPackageStats.entrySet()) {
   11183                     out.writeString(ent.getKey());
   11184                     Uid.Pkg ps = ent.getValue();
   11185                     final int NWA = ps.mWakeupAlarms.size();
   11186                     out.writeInt(NWA);
   11187                     for (int iwa=0; iwa<NWA; iwa++) {
   11188                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
   11189                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
   11190                     }
   11191                     NS = ps.mServiceStats.size();
   11192                     out.writeInt(NS);
   11193                     for (int is=0; is<NS; is++) {
   11194                         out.writeString(ps.mServiceStats.keyAt(is));
   11195                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
   11196                         long time = ss.getStartTimeToNowLocked(
   11197                                 mOnBatteryTimeBase.getUptime(NOW_SYS));
   11198                         out.writeLong(time);
   11199                         out.writeInt(ss.mStarts);
   11200                         out.writeInt(ss.mLaunches);
   11201                     }
   11202                 }
   11203             }
   11204         }
   11205     }
   11206 
   11207     public void readFromParcel(Parcel in) {
   11208         readFromParcelLocked(in);
   11209     }
   11210 
   11211     void readFromParcelLocked(Parcel in) {
   11212         int magic = in.readInt();
   11213         if (magic != MAGIC) {
   11214             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
   11215         }
   11216 
   11217         readHistory(in, false);
   11218 
   11219         mStartCount = in.readInt();
   11220         mStartClockTime = in.readLong();
   11221         mStartPlatformVersion = in.readString();
   11222         mEndPlatformVersion = in.readString();
   11223         mUptime = in.readLong();
   11224         mUptimeStart = in.readLong();
   11225         mRealtime = in.readLong();
   11226         mRealtimeStart = in.readLong();
   11227         mOnBattery = in.readInt() != 0;
   11228         mEstimatedBatteryCapacity = in.readInt();
   11229         mOnBatteryInternal = false; // we are no longer really running.
   11230         mOnBatteryTimeBase.readFromParcel(in);
   11231         mOnBatteryScreenOffTimeBase.readFromParcel(in);
   11232 
   11233         mScreenState = Display.STATE_UNKNOWN;
   11234         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
   11235         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   11236             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
   11237                     mOnBatteryTimeBase, in);
   11238         }
   11239         mInteractive = false;
   11240         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
   11241         mPhoneOn = false;
   11242         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
   11243                 mOnBatteryTimeBase, in);
   11244         mLongestLightIdleTime = in.readLong();
   11245         mLongestFullIdleTime = in.readLong();
   11246         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
   11247                 mOnBatteryTimeBase, in);
   11248         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
   11249                 mOnBatteryTimeBase, in);
   11250         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
   11251                 mOnBatteryTimeBase, in);
   11252         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
   11253         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
   11254         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   11255             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
   11256                     null, mOnBatteryTimeBase, in);
   11257         }
   11258         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
   11259                 mOnBatteryTimeBase, in);
   11260         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   11261             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
   11262                     null, mOnBatteryTimeBase, in);
   11263         }
   11264         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   11265             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
   11266             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
   11267         }
   11268         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
   11269         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
   11270                 mOnBatteryTimeBase, in);
   11271         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
   11272                 mOnBatteryTimeBase, in);
   11273         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
   11274         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
   11275         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
   11276         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
   11277         mWifiOn = false;
   11278         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
   11279         mGlobalWifiRunning = false;
   11280         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
   11281                 mOnBatteryTimeBase, in);
   11282         for (int i=0; i<NUM_WIFI_STATES; i++) {
   11283             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
   11284                     null, mOnBatteryTimeBase, in);
   11285         }
   11286         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   11287             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
   11288                     null, mOnBatteryTimeBase, in);
   11289         }
   11290         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   11291             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
   11292                     null, mOnBatteryTimeBase, in);
   11293         }
   11294 
   11295         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
   11296                 NUM_WIFI_TX_LEVELS, in);
   11297         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
   11298                 NUM_BT_TX_LEVELS, in);
   11299         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
   11300                 ModemActivityInfo.TX_POWER_LEVELS, in);
   11301         mHasWifiReporting = in.readInt() != 0;
   11302         mHasBluetoothReporting = in.readInt() != 0;
   11303         mHasModemReporting = in.readInt() != 0;
   11304 
   11305         mNumConnectivityChange = in.readInt();
   11306         mLoadedNumConnectivityChange = in.readInt();
   11307         mUnpluggedNumConnectivityChange = in.readInt();
   11308         mAudioOnNesting = 0;
   11309         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
   11310         mVideoOnNesting = 0;
   11311         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
   11312         mFlashlightOnNesting = 0;
   11313         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
   11314         mCameraOnNesting = 0;
   11315         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
   11316         mBluetoothScanNesting = 0;
   11317         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
   11318         mDischargeUnplugLevel = in.readInt();
   11319         mDischargePlugLevel = in.readInt();
   11320         mDischargeCurrentLevel = in.readInt();
   11321         mCurrentBatteryLevel = in.readInt();
   11322         mLowDischargeAmountSinceCharge = in.readInt();
   11323         mHighDischargeAmountSinceCharge = in.readInt();
   11324         mDischargeAmountScreenOn = in.readInt();
   11325         mDischargeAmountScreenOnSinceCharge = in.readInt();
   11326         mDischargeAmountScreenOff = in.readInt();
   11327         mDischargeAmountScreenOffSinceCharge = in.readInt();
   11328         mDischargeStepTracker.readFromParcel(in);
   11329         mChargeStepTracker.readFromParcel(in);
   11330         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
   11331         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
   11332         mLastWriteTime = in.readLong();
   11333 
   11334         mKernelWakelockStats.clear();
   11335         int NKW = in.readInt();
   11336         for (int ikw = 0; ikw < NKW; ikw++) {
   11337             if (in.readInt() != 0) {
   11338                 String wakelockName = in.readString();
   11339                 SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
   11340                 mKernelWakelockStats.put(wakelockName, kwlt);
   11341             }
   11342         }
   11343 
   11344         mWakeupReasonStats.clear();
   11345         int NWR = in.readInt();
   11346         for (int iwr = 0; iwr < NWR; iwr++) {
   11347             if (in.readInt() != 0) {
   11348                 String reasonName = in.readString();
   11349                 SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
   11350                 mWakeupReasonStats.put(reasonName, timer);
   11351             }
   11352         }
   11353 
   11354         mPartialTimers.clear();
   11355         mFullTimers.clear();
   11356         mWindowTimers.clear();
   11357         mWifiRunningTimers.clear();
   11358         mFullWifiLockTimers.clear();
   11359         mWifiScanTimers.clear();
   11360         mWifiBatchedScanTimers.clear();
   11361         mWifiMulticastTimers.clear();
   11362         mAudioTurnedOnTimers.clear();
   11363         mVideoTurnedOnTimers.clear();
   11364         mFlashlightTurnedOnTimers.clear();
   11365         mCameraTurnedOnTimers.clear();
   11366 
   11367         int numUids = in.readInt();
   11368         mUidStats.clear();
   11369         for (int i = 0; i < numUids; i++) {
   11370             int uid = in.readInt();
   11371             Uid u = new Uid(this, uid);
   11372             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
   11373             mUidStats.append(uid, u);
   11374         }
   11375     }
   11376 
   11377     public void writeToParcel(Parcel out, int flags) {
   11378         writeToParcelLocked(out, true, flags);
   11379     }
   11380 
   11381     public void writeToParcelWithoutUids(Parcel out, int flags) {
   11382         writeToParcelLocked(out, false, flags);
   11383     }
   11384 
   11385     @SuppressWarnings("unused")
   11386     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
   11387         // Need to update with current kernel wake lock counts.
   11388         pullPendingStateUpdatesLocked();
   11389 
   11390         // Pull the clock time.  This may update the time and make a new history entry
   11391         // if we had originally pulled a time before the RTC was set.
   11392         long startClockTime = getStartClockTime();
   11393 
   11394         final long uSecUptime = mClocks.uptimeMillis() * 1000;
   11395         final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
   11396         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
   11397         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
   11398 
   11399         out.writeInt(MAGIC);
   11400 
   11401         writeHistory(out, true, false);
   11402 
   11403         out.writeInt(mStartCount);
   11404         out.writeLong(startClockTime);
   11405         out.writeString(mStartPlatformVersion);
   11406         out.writeString(mEndPlatformVersion);
   11407         out.writeLong(mUptime);
   11408         out.writeLong(mUptimeStart);
   11409         out.writeLong(mRealtime);
   11410         out.writeLong(mRealtimeStart);
   11411         out.writeInt(mOnBattery ? 1 : 0);
   11412         out.writeInt(mEstimatedBatteryCapacity);
   11413         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
   11414         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
   11415 
   11416         mScreenOnTimer.writeToParcel(out, uSecRealtime);
   11417         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   11418             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
   11419         }
   11420         mInteractiveTimer.writeToParcel(out, uSecRealtime);
   11421         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
   11422         out.writeLong(mLongestLightIdleTime);
   11423         out.writeLong(mLongestFullIdleTime);
   11424         mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
   11425         mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
   11426         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
   11427         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
   11428         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
   11429         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   11430             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
   11431         }
   11432         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
   11433         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   11434             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
   11435         }
   11436         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   11437             mNetworkByteActivityCounters[i].writeToParcel(out);
   11438             mNetworkPacketActivityCounters[i].writeToParcel(out);
   11439         }
   11440         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
   11441         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
   11442         mMobileRadioActiveAdjustedTime.writeToParcel(out);
   11443         mMobileRadioActiveUnknownTime.writeToParcel(out);
   11444         mMobileRadioActiveUnknownCount.writeToParcel(out);
   11445         mWifiOnTimer.writeToParcel(out, uSecRealtime);
   11446         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
   11447         for (int i=0; i<NUM_WIFI_STATES; i++) {
   11448             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
   11449         }
   11450         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   11451             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
   11452         }
   11453         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   11454             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
   11455         }
   11456         mWifiActivity.writeToParcel(out, 0);
   11457         mBluetoothActivity.writeToParcel(out, 0);
   11458         mModemActivity.writeToParcel(out, 0);
   11459         out.writeInt(mHasWifiReporting ? 1 : 0);
   11460         out.writeInt(mHasBluetoothReporting ? 1 : 0);
   11461         out.writeInt(mHasModemReporting ? 1 : 0);
   11462 
   11463         out.writeInt(mNumConnectivityChange);
   11464         out.writeInt(mLoadedNumConnectivityChange);
   11465         out.writeInt(mUnpluggedNumConnectivityChange);
   11466         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
   11467         mCameraOnTimer.writeToParcel(out, uSecRealtime);
   11468         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
   11469         out.writeInt(mDischargeUnplugLevel);
   11470         out.writeInt(mDischargePlugLevel);
   11471         out.writeInt(mDischargeCurrentLevel);
   11472         out.writeInt(mCurrentBatteryLevel);
   11473         out.writeInt(mLowDischargeAmountSinceCharge);
   11474         out.writeInt(mHighDischargeAmountSinceCharge);
   11475         out.writeInt(mDischargeAmountScreenOn);
   11476         out.writeInt(mDischargeAmountScreenOnSinceCharge);
   11477         out.writeInt(mDischargeAmountScreenOff);
   11478         out.writeInt(mDischargeAmountScreenOffSinceCharge);
   11479         mDischargeStepTracker.writeToParcel(out);
   11480         mChargeStepTracker.writeToParcel(out);
   11481         mDischargeCounter.writeToParcel(out);
   11482         mDischargeScreenOffCounter.writeToParcel(out);
   11483         out.writeLong(mLastWriteTime);
   11484 
   11485         if (inclUids) {
   11486             out.writeInt(mKernelWakelockStats.size());
   11487             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
   11488                 SamplingTimer kwlt = ent.getValue();
   11489                 if (kwlt != null) {
   11490                     out.writeInt(1);
   11491                     out.writeString(ent.getKey());
   11492                     kwlt.writeToParcel(out, uSecRealtime);
   11493                 } else {
   11494                     out.writeInt(0);
   11495                 }
   11496             }
   11497             out.writeInt(mWakeupReasonStats.size());
   11498             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
   11499                 SamplingTimer timer = ent.getValue();
   11500                 if (timer != null) {
   11501                     out.writeInt(1);
   11502                     out.writeString(ent.getKey());
   11503                     timer.writeToParcel(out, uSecRealtime);
   11504                 } else {
   11505                     out.writeInt(0);
   11506                 }
   11507             }
   11508         } else {
   11509             out.writeInt(0);
   11510         }
   11511 
   11512         if (inclUids) {
   11513             int size = mUidStats.size();
   11514             out.writeInt(size);
   11515             for (int i = 0; i < size; i++) {
   11516                 out.writeInt(mUidStats.keyAt(i));
   11517                 Uid uid = mUidStats.valueAt(i);
   11518 
   11519                 uid.writeToParcelLocked(out, uSecRealtime);
   11520             }
   11521         } else {
   11522             out.writeInt(0);
   11523         }
   11524     }
   11525 
   11526     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
   11527         new Parcelable.Creator<BatteryStatsImpl>() {
   11528         public BatteryStatsImpl createFromParcel(Parcel in) {
   11529             return new BatteryStatsImpl(in);
   11530         }
   11531 
   11532         public BatteryStatsImpl[] newArray(int size) {
   11533             return new BatteryStatsImpl[size];
   11534         }
   11535     };
   11536 
   11537     public void prepareForDumpLocked() {
   11538         // Need to retrieve current kernel wake lock stats before printing.
   11539         pullPendingStateUpdatesLocked();
   11540 
   11541         // Pull the clock time.  This may update the time and make a new history entry
   11542         // if we had originally pulled a time before the RTC was set.
   11543         getStartClockTime();
   11544     }
   11545 
   11546     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
   11547         if (DEBUG) {
   11548             pw.println("mOnBatteryTimeBase:");
   11549             mOnBatteryTimeBase.dump(pw, "  ");
   11550             pw.println("mOnBatteryScreenOffTimeBase:");
   11551             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
   11552             Printer pr = new PrintWriterPrinter(pw);
   11553             pr.println("*** Screen timer:");
   11554             mScreenOnTimer.logState(pr, "  ");
   11555             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   11556                 pr.println("*** Screen brightness #" + i + ":");
   11557                 mScreenBrightnessTimer[i].logState(pr, "  ");
   11558             }
   11559             pr.println("*** Interactive timer:");
   11560             mInteractiveTimer.logState(pr, "  ");
   11561             pr.println("*** Power save mode timer:");
   11562             mPowerSaveModeEnabledTimer.logState(pr, "  ");
   11563             pr.println("*** Device idle mode light timer:");
   11564             mDeviceIdleModeLightTimer.logState(pr, "  ");
   11565             pr.println("*** Device idle mode full timer:");
   11566             mDeviceIdleModeFullTimer.logState(pr, "  ");
   11567             pr.println("*** Device light idling timer:");
   11568             mDeviceLightIdlingTimer.logState(pr, "  ");
   11569             pr.println("*** Device idling timer:");
   11570             mDeviceIdlingTimer.logState(pr, "  ");
   11571             pr.println("*** Phone timer:");
   11572             mPhoneOnTimer.logState(pr, "  ");
   11573             for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   11574                 pr.println("*** Phone signal strength #" + i + ":");
   11575                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
   11576             }
   11577             pr.println("*** Signal scanning :");
   11578             mPhoneSignalScanningTimer.logState(pr, "  ");
   11579             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   11580                 pr.println("*** Data connection type #" + i + ":");
   11581                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
   11582             }
   11583             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
   11584             pr.println("*** Mobile network active timer:");
   11585             mMobileRadioActiveTimer.logState(pr, "  ");
   11586             pr.println("*** Mobile network active adjusted timer:");
   11587             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
   11588             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
   11589             pr.println("*** Wifi timer:");
   11590             mWifiOnTimer.logState(pr, "  ");
   11591             pr.println("*** WifiRunning timer:");
   11592             mGlobalWifiRunningTimer.logState(pr, "  ");
   11593             for (int i=0; i<NUM_WIFI_STATES; i++) {
   11594                 pr.println("*** Wifi state #" + i + ":");
   11595                 mWifiStateTimer[i].logState(pr, "  ");
   11596             }
   11597             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   11598                 pr.println("*** Wifi suppl state #" + i + ":");
   11599                 mWifiSupplStateTimer[i].logState(pr, "  ");
   11600             }
   11601             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   11602                 pr.println("*** Wifi signal strength #" + i + ":");
   11603                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
   11604             }
   11605             pr.println("*** Flashlight timer:");
   11606             mFlashlightOnTimer.logState(pr, "  ");
   11607             pr.println("*** Camera timer:");
   11608             mCameraOnTimer.logState(pr, "  ");
   11609         }
   11610         super.dumpLocked(context, pw, flags, reqUid, histStart);
   11611     }
   11612 }
   11613