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