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