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