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