Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2006-2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.os;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 import android.app.ActivityManager;
     22 import android.bluetooth.BluetoothActivityEnergyInfo;
     23 import android.bluetooth.UidTraffic;
     24 import android.content.BroadcastReceiver;
     25 import android.content.ContentResolver;
     26 import android.content.Context;
     27 import android.content.Intent;
     28 import android.content.IntentFilter;
     29 import android.database.ContentObserver;
     30 import android.hardware.usb.UsbManager;
     31 import android.net.ConnectivityManager;
     32 import android.net.NetworkStats;
     33 import android.net.Uri;
     34 import android.net.wifi.WifiActivityEnergyInfo;
     35 import android.net.wifi.WifiManager;
     36 import android.os.BatteryManager;
     37 import android.os.BatteryStats;
     38 import android.os.Build;
     39 import android.os.FileUtils;
     40 import android.os.Handler;
     41 import android.os.IBatteryPropertiesRegistrar;
     42 import android.os.Looper;
     43 import android.os.Message;
     44 import android.os.OsProtoEnums;
     45 import android.os.Parcel;
     46 import android.os.ParcelFormatException;
     47 import android.os.Parcelable;
     48 import android.os.PowerManager;
     49 import android.os.Process;
     50 import android.os.RemoteException;
     51 import android.os.ServiceManager;
     52 import android.os.SystemClock;
     53 import android.os.UserHandle;
     54 import android.os.WorkSource;
     55 import android.os.WorkSource.WorkChain;
     56 import android.os.connectivity.CellularBatteryStats;
     57 import android.os.connectivity.GpsBatteryStats;
     58 import android.os.connectivity.WifiBatteryStats;
     59 import android.provider.Settings;
     60 import android.telephony.DataConnectionRealTimeInfo;
     61 import android.telephony.ModemActivityInfo;
     62 import android.telephony.ServiceState;
     63 import android.telephony.SignalStrength;
     64 import android.telephony.TelephonyManager;
     65 import android.text.TextUtils;
     66 import android.util.ArrayMap;
     67 import android.util.IntArray;
     68 import android.util.KeyValueListParser;
     69 import android.util.Log;
     70 import android.util.LogWriter;
     71 import android.util.LongSparseArray;
     72 import android.util.LongSparseLongArray;
     73 import android.util.MutableInt;
     74 import android.util.Pools;
     75 import android.util.PrintWriterPrinter;
     76 import android.util.Printer;
     77 import android.util.Slog;
     78 import android.util.SparseArray;
     79 import android.util.SparseIntArray;
     80 import android.util.SparseLongArray;
     81 import android.util.StatsLog;
     82 import android.util.TimeUtils;
     83 import android.util.Xml;
     84 import android.view.Display;
     85 
     86 import com.android.internal.annotations.GuardedBy;
     87 import com.android.internal.annotations.VisibleForTesting;
     88 import com.android.internal.location.gnssmetrics.GnssMetrics;
     89 import com.android.internal.net.NetworkStatsFactory;
     90 import com.android.internal.util.ArrayUtils;
     91 import com.android.internal.util.FastPrintWriter;
     92 import com.android.internal.util.FastXmlSerializer;
     93 import com.android.internal.util.JournaledFile;
     94 import com.android.internal.util.XmlUtils;
     95 
     96 import libcore.util.EmptyArray;
     97 
     98 import org.xmlpull.v1.XmlPullParser;
     99 import org.xmlpull.v1.XmlPullParserException;
    100 import org.xmlpull.v1.XmlSerializer;
    101 
    102 import java.io.ByteArrayOutputStream;
    103 import java.io.File;
    104 import java.io.FileInputStream;
    105 import java.io.FileNotFoundException;
    106 import java.io.FileOutputStream;
    107 import java.io.IOException;
    108 import java.io.PrintWriter;
    109 import java.nio.charset.StandardCharsets;
    110 import java.util.ArrayList;
    111 import java.util.Arrays;
    112 import java.util.Calendar;
    113 import java.util.HashMap;
    114 import java.util.Iterator;
    115 import java.util.LinkedList;
    116 import java.util.List;
    117 import java.util.Map;
    118 import java.util.Queue;
    119 import java.util.concurrent.Future;
    120 import java.util.concurrent.atomic.AtomicInteger;
    121 import java.util.concurrent.locks.ReentrantLock;
    122 
    123 /**
    124  * All information we are collecting about things that can happen that impact
    125  * battery life.  All times are represented in microseconds except where indicated
    126  * otherwise.
    127  */
    128 public class BatteryStatsImpl extends BatteryStats {
    129     private static final String TAG = "BatteryStatsImpl";
    130     private static final boolean DEBUG = false;
    131     public static final boolean DEBUG_ENERGY = false;
    132     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
    133     private static final boolean DEBUG_MEMORY = false;
    134     private static final boolean DEBUG_HISTORY = false;
    135     private static final boolean USE_OLD_HISTORY = false;   // for debugging.
    136 
    137     // TODO: remove "tcp" from network methods, since we measure total stats.
    138 
    139     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
    140     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
    141 
    142     // Current on-disk Parcel version
    143     private static final int VERSION = 177 + (USE_OLD_HISTORY ? 1000 : 0);
    144 
    145     // Maximum number of items we will record in the history.
    146     private static final int MAX_HISTORY_ITEMS;
    147 
    148     // No, really, THIS is the maximum number of items we will record in the history.
    149     private static final int MAX_MAX_HISTORY_ITEMS;
    150 
    151     // The maximum number of names wakelocks we will keep track of
    152     // per uid; once the limit is reached, we batch the remaining wakelocks
    153     // in to one common name.
    154     private static final int MAX_WAKELOCKS_PER_UID;
    155 
    156     static final int MAX_HISTORY_BUFFER; // 256KB
    157     static final int MAX_MAX_HISTORY_BUFFER; // 320KB
    158 
    159     static {
    160         if (ActivityManager.isLowRamDeviceStatic()) {
    161             MAX_HISTORY_ITEMS = 800;
    162             MAX_MAX_HISTORY_ITEMS = 1200;
    163             MAX_WAKELOCKS_PER_UID = 40;
    164             MAX_HISTORY_BUFFER = 96*1024;  // 96KB
    165             MAX_MAX_HISTORY_BUFFER = 128*1024; // 128KB
    166         } else {
    167             MAX_HISTORY_ITEMS = 4000;
    168             MAX_MAX_HISTORY_ITEMS = 6000;
    169             MAX_WAKELOCKS_PER_UID = 200;
    170             MAX_HISTORY_BUFFER = 512*1024;  // 512KB
    171             MAX_MAX_HISTORY_BUFFER = 640*1024;  // 640KB
    172         }
    173     }
    174 
    175     // Number of transmit power states the Wifi controller can be in.
    176     private static final int NUM_WIFI_TX_LEVELS = 1;
    177 
    178     // Number of transmit power states the Bluetooth controller can be in.
    179     private static final int NUM_BT_TX_LEVELS = 1;
    180 
    181     /**
    182      * Holding a wakelock costs more than just using the cpu.
    183      * Currently, we assign only half the cpu time to an app that is running but
    184      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
    185      * If no app is holding a wakelock, then the distribution is normal.
    186      */
    187     @VisibleForTesting
    188     public static final int WAKE_LOCK_WEIGHT = 50;
    189 
    190     protected Clocks mClocks;
    191 
    192     private final JournaledFile mFile;
    193     public final AtomicFile mCheckinFile;
    194     public final AtomicFile mDailyFile;
    195 
    196     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
    197     static final int MSG_REPORT_POWER_CHANGE = 2;
    198     static final int MSG_REPORT_CHARGING = 3;
    199     static final int MSG_REPORT_RESET_STATS = 4;
    200     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
    201 
    202     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
    203     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
    204 
    205     @VisibleForTesting
    206     protected KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
    207     @VisibleForTesting
    208     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
    209     @VisibleForTesting
    210     protected KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
    211             new KernelUidCpuFreqTimeReader();
    212     @VisibleForTesting
    213     protected KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader =
    214             new KernelUidCpuActiveTimeReader();
    215     @VisibleForTesting
    216     protected KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
    217             new KernelUidCpuClusterTimeReader();
    218     @VisibleForTesting
    219     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
    220 
    221     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
    222             = new KernelMemoryBandwidthStats();
    223     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
    224     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
    225         return mKernelMemoryStats;
    226     }
    227 
    228     @GuardedBy("this")
    229     public boolean mPerProcStateCpuTimesAvailable = true;
    230 
    231     /**
    232      * Uids for which per-procstate cpu times need to be updated.
    233      *
    234      * Contains uid -> procState mappings.
    235      */
    236     @GuardedBy("this")
    237     @VisibleForTesting
    238     protected final SparseIntArray mPendingUids = new SparseIntArray();
    239 
    240     @GuardedBy("this")
    241     private long mNumSingleUidCpuTimeReads;
    242     @GuardedBy("this")
    243     private long mNumBatchedSingleUidCpuTimeReads;
    244     @GuardedBy("this")
    245     private long mCpuTimeReadsTrackingStartTime = SystemClock.uptimeMillis();
    246     @GuardedBy("this")
    247     private int mNumUidsRemoved;
    248     @GuardedBy("this")
    249     private int mNumAllUidCpuTimeReads;
    250 
    251     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
    252     private final RpmStats mTmpRpmStats = new RpmStats();
    253     /** The soonest the RPM stats can be updated after it was last updated. */
    254     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
    255     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
    256     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
    257     /**
    258      * Use a queue to delay removing UIDs from {@link KernelUidCpuTimeReader},
    259      * {@link KernelUidCpuActiveTimeReader}, {@link KernelUidCpuClusterTimeReader},
    260      * {@link KernelUidCpuFreqTimeReader} and from the Kernel.
    261      *
    262      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
    263      * Batterystats both need to access UID cpu time. To resolve this race condition, only
    264      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
    265      * implemented so that STATSD can capture those UID times before they are deleted.
    266      */
    267     @GuardedBy("this")
    268     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    269     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
    270 
    271     @VisibleForTesting
    272     public final class UidToRemove {
    273         int startUid;
    274         int endUid;
    275         long timeAddedInQueue;
    276 
    277         /** Remove just one UID */
    278         public UidToRemove(int uid, long timestamp) {
    279             this(uid, uid, timestamp);
    280         }
    281 
    282         /** Remove a range of UIDs, startUid must be smaller than endUid. */
    283         public UidToRemove(int startUid, int endUid, long timestamp) {
    284             this.startUid = startUid;
    285             this.endUid = endUid;
    286             timeAddedInQueue = timestamp;
    287         }
    288 
    289         void remove() {
    290             if (startUid == endUid) {
    291                 mKernelUidCpuTimeReader.removeUid(startUid);
    292                 mKernelUidCpuFreqTimeReader.removeUid(startUid);
    293                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
    294                     mKernelUidCpuActiveTimeReader.removeUid(startUid);
    295                     mKernelUidCpuClusterTimeReader.removeUid(startUid);
    296                 }
    297                 if (mKernelSingleUidTimeReader != null) {
    298                     mKernelSingleUidTimeReader.removeUid(startUid);
    299                 }
    300                 mNumUidsRemoved++;
    301             } else if (startUid < endUid) {
    302                 mKernelUidCpuFreqTimeReader.removeUidsInRange(startUid, endUid);
    303                 mKernelUidCpuTimeReader.removeUidsInRange(startUid, endUid);
    304                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
    305                     mKernelUidCpuActiveTimeReader.removeUidsInRange(startUid, endUid);
    306                     mKernelUidCpuClusterTimeReader.removeUidsInRange(startUid, endUid);
    307                 }
    308                 if (mKernelSingleUidTimeReader != null) {
    309                     mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
    310                 }
    311                 // Treat as one. We don't know how many uids there are in between.
    312                 mNumUidsRemoved++;
    313             } else {
    314                 Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
    315             }
    316         }
    317     }
    318 
    319     public interface BatteryCallback {
    320         public void batteryNeedsCpuUpdate();
    321         public void batteryPowerChanged(boolean onBattery);
    322         public void batterySendBroadcast(Intent intent);
    323         public void batteryStatsReset();
    324     }
    325 
    326     public interface PlatformIdleStateCallback {
    327         public void fillLowPowerStats(RpmStats rpmStats);
    328         public String getPlatformLowPowerStats();
    329         public String getSubsystemLowPowerStats();
    330     }
    331 
    332     public static abstract class UserInfoProvider {
    333         private int[] userIds;
    334         protected abstract @Nullable int[] getUserIds();
    335         @VisibleForTesting
    336         public final void refreshUserIds() {
    337             userIds = getUserIds();
    338         }
    339         @VisibleForTesting
    340         public boolean exists(int userId) {
    341             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
    342         }
    343     }
    344 
    345     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
    346 
    347     final class MyHandler extends Handler {
    348         public MyHandler(Looper looper) {
    349             super(looper, null, true);
    350         }
    351 
    352         @Override
    353         public void handleMessage(Message msg) {
    354             BatteryCallback cb = mCallback;
    355             switch (msg.what) {
    356                 case MSG_REPORT_CPU_UPDATE_NEEDED:
    357                     if (cb != null) {
    358                         cb.batteryNeedsCpuUpdate();
    359                     }
    360                     break;
    361                 case MSG_REPORT_POWER_CHANGE:
    362                     if (cb != null) {
    363                         cb.batteryPowerChanged(msg.arg1 != 0);
    364                     }
    365                     break;
    366                 case MSG_REPORT_CHARGING:
    367                     if (cb != null) {
    368                         final String action;
    369                         synchronized (BatteryStatsImpl.this) {
    370                             action = mCharging ? BatteryManager.ACTION_CHARGING
    371                                     : BatteryManager.ACTION_DISCHARGING;
    372                         }
    373                         Intent intent = new Intent(action);
    374                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
    375                         cb.batterySendBroadcast(intent);
    376                     }
    377                     break;
    378                 case MSG_REPORT_RESET_STATS:
    379                     if (cb != null) {
    380                         cb.batteryStatsReset();
    381                     }
    382                 }
    383         }
    384     }
    385 
    386     public void postBatteryNeedsCpuUpdateMsg() {
    387         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
    388     }
    389 
    390     /**
    391      * Update per-freq cpu times for all the uids in {@link #mPendingUids}.
    392      */
    393     public void updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
    394         final SparseIntArray uidStates;
    395         synchronized (BatteryStatsImpl.this) {
    396             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
    397                 return;
    398             }
    399             if(!initKernelSingleUidTimeReaderLocked()) {
    400                 return;
    401             }
    402             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
    403             // compute deltas since it might result in mis-attributing cpu times to wrong states.
    404             if (mKernelSingleUidTimeReader.hasStaleData()) {
    405                 mPendingUids.clear();
    406                 return;
    407             }
    408 
    409             if (mPendingUids.size() == 0) {
    410                 return;
    411             }
    412             uidStates = mPendingUids.clone();
    413             mPendingUids.clear();
    414         }
    415         for (int i = uidStates.size() - 1; i >= 0; --i) {
    416             final int uid = uidStates.keyAt(i);
    417             final int procState = uidStates.valueAt(i);
    418             final int[] isolatedUids;
    419             final Uid u;
    420             synchronized (BatteryStatsImpl.this) {
    421                 // It's possible that uid no longer exists and any internal references have
    422                 // already been deleted, so using {@link #getAvailableUidStatsLocked} to avoid
    423                 // creating an UidStats object if it doesn't already exist.
    424                 u = getAvailableUidStatsLocked(uid);
    425                 if (u == null) {
    426                     continue;
    427                 }
    428                 if (u.mChildUids == null) {
    429                     isolatedUids = null;
    430                 } else {
    431                     isolatedUids = u.mChildUids.toArray();
    432                     for (int j = isolatedUids.length - 1; j >= 0; --j) {
    433                         isolatedUids[j] = u.mChildUids.get(j);
    434                     }
    435                 }
    436             }
    437             long[] cpuTimesMs = mKernelSingleUidTimeReader.readDeltaMs(uid);
    438             if (isolatedUids != null) {
    439                 for (int j = isolatedUids.length - 1; j >= 0; --j) {
    440                     cpuTimesMs = addCpuTimes(cpuTimesMs,
    441                             mKernelSingleUidTimeReader.readDeltaMs(isolatedUids[j]));
    442                 }
    443             }
    444             if (onBattery && cpuTimesMs != null) {
    445                 synchronized (BatteryStatsImpl.this) {
    446                     u.addProcStateTimesMs(procState, cpuTimesMs, onBattery);
    447                     u.addProcStateScreenOffTimesMs(procState, cpuTimesMs, onBatteryScreenOff);
    448                 }
    449             }
    450         }
    451     }
    452 
    453     public void clearPendingRemovedUids() {
    454         long cutOffTime = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
    455         while (!mPendingRemovedUids.isEmpty()
    456                 && mPendingRemovedUids.peek().timeAddedInQueue < cutOffTime) {
    457             mPendingRemovedUids.poll().remove();
    458         }
    459     }
    460 
    461     public void copyFromAllUidsCpuTimes() {
    462         synchronized (BatteryStatsImpl.this) {
    463             copyFromAllUidsCpuTimes(
    464                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
    465         }
    466     }
    467 
    468     /**
    469      * When the battery/screen state changes, we don't attribute the cpu times to any process
    470      * but we still need to snapshots of all uids to get correct deltas later on. Since we
    471      * already read this data for updating per-freq cpu times, we can use the same data for
    472      * per-procstate cpu times.
    473      */
    474     public void copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
    475         synchronized (BatteryStatsImpl.this) {
    476             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
    477                 return;
    478             }
    479             if(!initKernelSingleUidTimeReaderLocked()) {
    480                 return;
    481             }
    482 
    483             final SparseArray<long[]> allUidCpuFreqTimesMs =
    484                     mKernelUidCpuFreqTimeReader.getAllUidCpuFreqTimeMs();
    485             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
    486             // compute deltas since it might result in mis-attributing cpu times to wrong states.
    487             if (mKernelSingleUidTimeReader.hasStaleData()) {
    488                 mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
    489                 mKernelSingleUidTimeReader.markDataAsStale(false);
    490                 mPendingUids.clear();
    491                 return;
    492             }
    493             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
    494                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
    495                 final Uid u = getAvailableUidStatsLocked(mapUid(uid));
    496                 if (u == null) {
    497                     continue;
    498                 }
    499                 final long[] cpuTimesMs = allUidCpuFreqTimesMs.valueAt(i);
    500                 if (cpuTimesMs == null) {
    501                     continue;
    502                 }
    503                 final long[] deltaTimesMs = mKernelSingleUidTimeReader.computeDelta(
    504                         uid, cpuTimesMs.clone());
    505                 if (onBattery && deltaTimesMs != null) {
    506                     final int procState;
    507                     final int idx = mPendingUids.indexOfKey(uid);
    508                     if (idx >= 0) {
    509                         procState = mPendingUids.valueAt(idx);
    510                         mPendingUids.removeAt(idx);
    511                     } else {
    512                         procState = u.mProcessState;
    513                     }
    514                     if (procState >= 0 && procState < Uid.NUM_PROCESS_STATE) {
    515                         u.addProcStateTimesMs(procState, deltaTimesMs, onBattery);
    516                         u.addProcStateScreenOffTimesMs(procState, deltaTimesMs, onBatteryScreenOff);
    517                     }
    518                 }
    519             }
    520         }
    521     }
    522 
    523     @VisibleForTesting
    524     public long[] addCpuTimes(long[] timesA, long[] timesB) {
    525         if (timesA != null && timesB != null) {
    526             for (int i = timesA.length - 1; i >= 0; --i) {
    527                 timesA[i] += timesB[i];
    528             }
    529             return timesA;
    530         }
    531         return timesA == null ? (timesB == null ? null : timesB) : timesA;
    532     }
    533 
    534     @GuardedBy("this")
    535     private boolean initKernelSingleUidTimeReaderLocked() {
    536         if (mKernelSingleUidTimeReader == null) {
    537             if (mPowerProfile == null) {
    538                 return false;
    539             }
    540             if (mCpuFreqs == null) {
    541                 mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
    542             }
    543             if (mCpuFreqs != null) {
    544                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
    545             } else {
    546                 mPerProcStateCpuTimesAvailable = mKernelUidCpuFreqTimeReader.allUidTimesAvailable();
    547                 return false;
    548             }
    549         }
    550         mPerProcStateCpuTimesAvailable = mKernelUidCpuFreqTimeReader.allUidTimesAvailable()
    551                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
    552         return true;
    553     }
    554 
    555     public interface Clocks {
    556         public long elapsedRealtime();
    557         public long uptimeMillis();
    558     }
    559 
    560     public static class SystemClocks implements Clocks {
    561         public long elapsedRealtime() {
    562             return SystemClock.elapsedRealtime();
    563         }
    564 
    565         public long uptimeMillis() {
    566             return SystemClock.uptimeMillis();
    567         }
    568     }
    569 
    570     public interface ExternalStatsSync {
    571         int UPDATE_CPU = 0x01;
    572         int UPDATE_WIFI = 0x02;
    573         int UPDATE_RADIO = 0x04;
    574         int UPDATE_BT = 0x08;
    575         int UPDATE_RPM = 0x10; // 16
    576         int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM;
    577 
    578         Future<?> scheduleSync(String reason, int flags);
    579         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
    580         Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff,
    581                 long delayMillis);
    582         Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
    583         Future<?> scheduleCpuSyncDueToSettingChange();
    584         Future<?> scheduleCpuSyncDueToScreenStateChange(boolean onBattery,
    585                 boolean onBatteryScreenOff);
    586         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
    587         void cancelCpuSyncDueToWakelockChange();
    588         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
    589     }
    590 
    591     public Handler mHandler;
    592     private ExternalStatsSync mExternalSync = null;
    593     @VisibleForTesting
    594     protected UserInfoProvider mUserInfoProvider = null;
    595 
    596     private BatteryCallback mCallback;
    597 
    598     /**
    599      * Mapping isolated uids to the actual owning app uid.
    600      */
    601     final SparseIntArray mIsolatedUids = new SparseIntArray();
    602 
    603     /**
    604      * The statistics we have collected organized by uids.
    605      */
    606     final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
    607 
    608     // A set of pools of currently active timers.  When a timer is queried, we will divide the
    609     // elapsed time by the number of active timers to arrive at that timer's share of the time.
    610     // In order to do this, we must refresh each timer whenever the number of active timers
    611     // changes.
    612     @VisibleForTesting
    613     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
    614     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
    615     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
    616     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
    617     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
    618     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
    619     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
    620     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
    621     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
    622     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
    623     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
    624     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
    625     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
    626     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
    627     final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
    628 
    629     // Last partial timers we use for distributing CPU usage.
    630     @VisibleForTesting
    631     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
    632 
    633     // These are the objects that will want to do something when the device
    634     // is unplugged from power.
    635     protected final TimeBase mOnBatteryTimeBase = new TimeBase();
    636 
    637     // These are the objects that will want to do something when the device
    638     // is unplugged from power *and* the screen is off or doze.
    639     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase();
    640 
    641     // Set to true when we want to distribute CPU across wakelocks for the next
    642     // CPU update, even if we aren't currently running wake locks.
    643     boolean mDistributeWakelockCpu;
    644 
    645     boolean mShuttingDown;
    646 
    647     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
    648 
    649     long mHistoryBaseTime;
    650     protected boolean mHaveBatteryLevel = false;
    651     protected boolean mRecordingHistory = false;
    652     int mNumHistoryItems;
    653 
    654     final Parcel mHistoryBuffer = Parcel.obtain();
    655     final HistoryItem mHistoryLastWritten = new HistoryItem();
    656     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
    657     final HistoryItem mHistoryReadTmp = new HistoryItem();
    658     final HistoryItem mHistoryAddTmp = new HistoryItem();
    659     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
    660     String[] mReadHistoryStrings;
    661     int[] mReadHistoryUids;
    662     int mReadHistoryChars;
    663     int mNextHistoryTagIdx = 0;
    664     int mNumHistoryTagChars = 0;
    665     int mHistoryBufferLastPos = -1;
    666     boolean mHistoryOverflow = false;
    667     int mActiveHistoryStates = 0xffffffff;
    668     int mActiveHistoryStates2 = 0xffffffff;
    669     long mLastHistoryElapsedRealtime = 0;
    670     long mTrackRunningHistoryElapsedRealtime = 0;
    671     long mTrackRunningHistoryUptime = 0;
    672 
    673     final HistoryItem mHistoryCur = new HistoryItem();
    674 
    675     HistoryItem mHistory;
    676     HistoryItem mHistoryEnd;
    677     HistoryItem mHistoryLastEnd;
    678     HistoryItem mHistoryCache;
    679 
    680     // Used by computeHistoryStepDetails
    681     HistoryStepDetails mLastHistoryStepDetails = null;
    682     byte mLastHistoryStepLevel = 0;
    683     final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
    684     final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
    685     final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
    686 
    687     /**
    688      * Total time (in milliseconds) spent executing in user code.
    689      */
    690     long mLastStepCpuUserTime;
    691     long mCurStepCpuUserTime;
    692     /**
    693      * Total time (in milliseconds) spent executing in kernel code.
    694      */
    695     long mLastStepCpuSystemTime;
    696     long mCurStepCpuSystemTime;
    697     /**
    698      * Times from /proc/stat (but measured in milliseconds).
    699      */
    700     long mLastStepStatUserTime;
    701     long mLastStepStatSystemTime;
    702     long mLastStepStatIOWaitTime;
    703     long mLastStepStatIrqTime;
    704     long mLastStepStatSoftIrqTime;
    705     long mLastStepStatIdleTime;
    706     long mCurStepStatUserTime;
    707     long mCurStepStatSystemTime;
    708     long mCurStepStatIOWaitTime;
    709     long mCurStepStatIrqTime;
    710     long mCurStepStatSoftIrqTime;
    711     long mCurStepStatIdleTime;
    712 
    713     private HistoryItem mHistoryIterator;
    714     private boolean mReadOverflow;
    715     private boolean mIteratingHistory;
    716 
    717     int mStartCount;
    718 
    719     long mStartClockTime;
    720     String mStartPlatformVersion;
    721     String mEndPlatformVersion;
    722 
    723     long mUptime;
    724     long mUptimeStart;
    725     long mRealtime;
    726     long mRealtimeStart;
    727 
    728     int mWakeLockNesting;
    729     boolean mWakeLockImportant;
    730     public boolean mRecordAllHistory;
    731     boolean mNoAutoReset;
    732 
    733     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    734     protected int mScreenState = Display.STATE_UNKNOWN;
    735     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    736     protected StopwatchTimer mScreenOnTimer;
    737     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    738     protected StopwatchTimer mScreenDozeTimer;
    739 
    740     int mScreenBrightnessBin = -1;
    741     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
    742 
    743     boolean mPretendScreenOff;
    744 
    745     boolean mInteractive;
    746     StopwatchTimer mInteractiveTimer;
    747 
    748     boolean mPowerSaveModeEnabled;
    749     StopwatchTimer mPowerSaveModeEnabledTimer;
    750 
    751     boolean mDeviceIdling;
    752     StopwatchTimer mDeviceIdlingTimer;
    753 
    754     boolean mDeviceLightIdling;
    755     StopwatchTimer mDeviceLightIdlingTimer;
    756 
    757     int mDeviceIdleMode;
    758     long mLastIdleTimeStart;
    759     long mLongestLightIdleTime;
    760     long mLongestFullIdleTime;
    761     StopwatchTimer mDeviceIdleModeLightTimer;
    762     StopwatchTimer mDeviceIdleModeFullTimer;
    763 
    764     boolean mPhoneOn;
    765     StopwatchTimer mPhoneOnTimer;
    766 
    767     int mAudioOnNesting;
    768     StopwatchTimer mAudioOnTimer;
    769 
    770     int mVideoOnNesting;
    771     StopwatchTimer mVideoOnTimer;
    772 
    773     int mFlashlightOnNesting;
    774     StopwatchTimer mFlashlightOnTimer;
    775 
    776     int mCameraOnNesting;
    777     StopwatchTimer mCameraOnTimer;
    778 
    779     private static final int USB_DATA_UNKNOWN = 0;
    780     private static final int USB_DATA_DISCONNECTED = 1;
    781     private static final int USB_DATA_CONNECTED = 2;
    782     int mUsbDataState = USB_DATA_UNKNOWN;
    783 
    784     int mGpsSignalQualityBin = -1;
    785     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    786     protected final StopwatchTimer[] mGpsSignalQualityTimer =
    787         new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
    788 
    789     int mPhoneSignalStrengthBin = -1;
    790     int mPhoneSignalStrengthBinRaw = -1;
    791     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
    792             new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
    793 
    794     StopwatchTimer mPhoneSignalScanningTimer;
    795 
    796     int mPhoneDataConnectionType = -1;
    797     final StopwatchTimer[] mPhoneDataConnectionsTimer =
    798             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
    799 
    800     final LongSamplingCounter[] mNetworkByteActivityCounters =
    801             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
    802     final LongSamplingCounter[] mNetworkPacketActivityCounters =
    803             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
    804 
    805     /**
    806      * The WiFi Overall wakelock timer
    807      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
    808      * since addition of per UID timers would not result in an accurate value due to overlapp of
    809      * per uid wakelock timers
    810      */
    811     StopwatchTimer mWifiMulticastWakelockTimer;
    812 
    813     /**
    814      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
    815      */
    816     ControllerActivityCounterImpl mWifiActivity;
    817 
    818     /**
    819      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
    820      */
    821     ControllerActivityCounterImpl mBluetoothActivity;
    822 
    823     /**
    824      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
    825      */
    826     ControllerActivityCounterImpl mModemActivity;
    827 
    828     /**
    829      * Whether the device supports WiFi controller energy reporting. This is set to true on
    830      * the first WiFi energy report. See {@link #mWifiActivity}.
    831      */
    832     boolean mHasWifiReporting = false;
    833 
    834     /**
    835      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
    836      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
    837      */
    838     boolean mHasBluetoothReporting = false;
    839 
    840     /**
    841      * Whether the device supports Modem controller energy reporting. This is set to true on
    842      * the first Modem energy report. See {@link #mModemActivity}.
    843      */
    844     boolean mHasModemReporting = false;
    845 
    846     boolean mWifiOn;
    847     StopwatchTimer mWifiOnTimer;
    848 
    849     boolean mGlobalWifiRunning;
    850     StopwatchTimer mGlobalWifiRunningTimer;
    851 
    852     int mWifiState = -1;
    853     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
    854 
    855     int mWifiSupplState = -1;
    856     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
    857 
    858     int mWifiSignalStrengthBin = -1;
    859     final StopwatchTimer[] mWifiSignalStrengthsTimer =
    860             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
    861 
    862     StopwatchTimer mWifiActiveTimer;
    863 
    864     int mBluetoothScanNesting;
    865     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    866     protected StopwatchTimer mBluetoothScanTimer;
    867 
    868     boolean mIsCellularTxPowerHigh = false;
    869 
    870     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
    871     long mMobileRadioActiveStartTime;
    872     StopwatchTimer mMobileRadioActiveTimer;
    873     StopwatchTimer mMobileRadioActivePerAppTimer;
    874     LongSamplingCounter mMobileRadioActiveAdjustedTime;
    875     LongSamplingCounter mMobileRadioActiveUnknownTime;
    876     LongSamplingCounter mMobileRadioActiveUnknownCount;
    877 
    878     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
    879 
    880     /**
    881      * These provide time bases that discount the time the device is plugged
    882      * in to power.
    883      */
    884     boolean mOnBattery;
    885     @VisibleForTesting
    886     protected boolean mOnBatteryInternal;
    887 
    888     /**
    889      * External reporting of whether the device is actually charging.
    890      */
    891     boolean mCharging = true;
    892     int mLastChargingStateLevel;
    893 
    894     /*
    895      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
    896      */
    897     int mDischargeStartLevel;
    898     int mDischargeUnplugLevel;
    899     int mDischargePlugLevel;
    900     int mDischargeCurrentLevel;
    901     int mCurrentBatteryLevel;
    902     int mLowDischargeAmountSinceCharge;
    903     int mHighDischargeAmountSinceCharge;
    904     int mDischargeScreenOnUnplugLevel;
    905     int mDischargeScreenOffUnplugLevel;
    906     int mDischargeScreenDozeUnplugLevel;
    907     int mDischargeAmountScreenOn;
    908     int mDischargeAmountScreenOnSinceCharge;
    909     int mDischargeAmountScreenOff;
    910     int mDischargeAmountScreenOffSinceCharge;
    911     int mDischargeAmountScreenDoze;
    912     int mDischargeAmountScreenDozeSinceCharge;
    913 
    914     private LongSamplingCounter mDischargeScreenOffCounter;
    915     private LongSamplingCounter mDischargeScreenDozeCounter;
    916     private LongSamplingCounter mDischargeCounter;
    917     private LongSamplingCounter mDischargeLightDozeCounter;
    918     private LongSamplingCounter mDischargeDeepDozeCounter;
    919 
    920     static final int MAX_LEVEL_STEPS = 200;
    921 
    922     int mInitStepMode = 0;
    923     int mCurStepMode = 0;
    924     int mModStepMode = 0;
    925 
    926     int mLastDischargeStepLevel;
    927     int mMinDischargeStepLevel;
    928     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
    929     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
    930     ArrayList<PackageChange> mDailyPackageChanges;
    931 
    932     int mLastChargeStepLevel;
    933     int mMaxChargeStepLevel;
    934     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
    935     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
    936 
    937     static final int MAX_DAILY_ITEMS = 10;
    938 
    939     long mDailyStartTime = 0;
    940     long mNextMinDailyDeadline = 0;
    941     long mNextMaxDailyDeadline = 0;
    942 
    943     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
    944 
    945     long mLastWriteTime = 0; // Milliseconds
    946 
    947     private int mPhoneServiceState = -1;
    948     private int mPhoneServiceStateRaw = -1;
    949     private int mPhoneSimStateRaw = -1;
    950 
    951     private int mNumConnectivityChange;
    952     private int mLoadedNumConnectivityChange;
    953     private int mUnpluggedNumConnectivityChange;
    954 
    955     private int mEstimatedBatteryCapacity = -1;
    956 
    957     private int mMinLearnedBatteryCapacity = -1;
    958     private int mMaxLearnedBatteryCapacity = -1;
    959 
    960     private long[] mCpuFreqs;
    961 
    962     @VisibleForTesting
    963     protected PowerProfile mPowerProfile;
    964 
    965     @GuardedBy("this")
    966     private final Constants mConstants;
    967 
    968     /*
    969      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
    970      * recording their times when on-battery (regardless of screen state).
    971      */
    972     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
    973     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
    974     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
    975 
    976     @Override
    977     public Map<String, ? extends Timer> getRpmStats() {
    978         return mRpmStats;
    979     }
    980 
    981     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
    982     @Override
    983     public Map<String, ? extends Timer> getScreenOffRpmStats() {
    984         return mScreenOffRpmStats;
    985     }
    986 
    987     /*
    988      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
    989      */
    990     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
    991 
    992     public Map<String, ? extends Timer> getKernelWakelockStats() {
    993         return mKernelWakelockStats;
    994     }
    995 
    996     String mLastWakeupReason = null;
    997     long mLastWakeupUptimeMs = 0;
    998     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
    999 
   1000     public Map<String, ? extends Timer> getWakeupReasonStats() {
   1001         return mWakeupReasonStats;
   1002     }
   1003 
   1004     @Override
   1005     public long getUahDischarge(int which) {
   1006         return mDischargeCounter.getCountLocked(which);
   1007     }
   1008 
   1009     @Override
   1010     public long getUahDischargeScreenOff(int which) {
   1011         return mDischargeScreenOffCounter.getCountLocked(which);
   1012     }
   1013 
   1014     @Override
   1015     public long getUahDischargeScreenDoze(int which) {
   1016         return mDischargeScreenDozeCounter.getCountLocked(which);
   1017     }
   1018 
   1019     @Override
   1020     public long getUahDischargeLightDoze(int which) {
   1021         return mDischargeLightDozeCounter.getCountLocked(which);
   1022     }
   1023 
   1024     @Override
   1025     public long getUahDischargeDeepDoze(int which) {
   1026         return mDischargeDeepDozeCounter.getCountLocked(which);
   1027     }
   1028 
   1029     @Override
   1030     public int getEstimatedBatteryCapacity() {
   1031         return mEstimatedBatteryCapacity;
   1032     }
   1033 
   1034     @Override
   1035     public int getMinLearnedBatteryCapacity() {
   1036         return mMinLearnedBatteryCapacity;
   1037     }
   1038 
   1039     @Override
   1040     public int getMaxLearnedBatteryCapacity() {
   1041         return mMaxLearnedBatteryCapacity;
   1042     }
   1043 
   1044     public BatteryStatsImpl() {
   1045         this(new SystemClocks());
   1046     }
   1047 
   1048     public BatteryStatsImpl(Clocks clocks) {
   1049         init(clocks);
   1050         mFile = null;
   1051         mCheckinFile = null;
   1052         mDailyFile = null;
   1053         mHandler = null;
   1054         mPlatformIdleStateCallback = null;
   1055         mUserInfoProvider = null;
   1056         mConstants = new Constants(mHandler);
   1057         clearHistoryLocked();
   1058     }
   1059 
   1060     private void init(Clocks clocks) {
   1061         mClocks = clocks;
   1062     }
   1063 
   1064     public interface TimeBaseObs {
   1065         void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
   1066         void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
   1067     }
   1068 
   1069     // methods are protected not private to be VisibleForTesting
   1070     public static class TimeBase {
   1071         protected final ArrayList<TimeBaseObs> mObservers = new ArrayList<>();
   1072 
   1073         protected long mUptime;
   1074         protected long mRealtime;
   1075 
   1076         protected boolean mRunning;
   1077 
   1078         protected long mPastUptime;
   1079         protected long mUptimeStart;
   1080         protected long mPastRealtime;
   1081         protected long mRealtimeStart;
   1082         protected long mUnpluggedUptime;
   1083         protected long mUnpluggedRealtime;
   1084 
   1085         public void dump(PrintWriter pw, String prefix) {
   1086             StringBuilder sb = new StringBuilder(128);
   1087             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
   1088             sb.setLength(0);
   1089             sb.append(prefix);
   1090                     sb.append("mUptime=");
   1091                     formatTimeMs(sb, mUptime / 1000);
   1092             pw.println(sb.toString());
   1093             sb.setLength(0);
   1094             sb.append(prefix);
   1095                     sb.append("mRealtime=");
   1096                     formatTimeMs(sb, mRealtime / 1000);
   1097             pw.println(sb.toString());
   1098             sb.setLength(0);
   1099             sb.append(prefix);
   1100                     sb.append("mPastUptime=");
   1101                     formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
   1102                     formatTimeMs(sb, mUptimeStart / 1000);
   1103                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
   1104             pw.println(sb.toString());
   1105             sb.setLength(0);
   1106             sb.append(prefix);
   1107                     sb.append("mPastRealtime=");
   1108                     formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
   1109                     formatTimeMs(sb, mRealtimeStart / 1000);
   1110                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
   1111             pw.println(sb.toString());
   1112         }
   1113 
   1114         public void add(TimeBaseObs observer) {
   1115             mObservers.add(observer);
   1116         }
   1117 
   1118         public void remove(TimeBaseObs observer) {
   1119             if (!mObservers.remove(observer)) {
   1120                 Slog.wtf(TAG, "Removed unknown observer: " + observer);
   1121             }
   1122         }
   1123 
   1124         public boolean hasObserver(TimeBaseObs observer) {
   1125             return mObservers.contains(observer);
   1126         }
   1127 
   1128         public void init(long uptime, long realtime) {
   1129             mRealtime = 0;
   1130             mUptime = 0;
   1131             mPastUptime = 0;
   1132             mPastRealtime = 0;
   1133             mUptimeStart = uptime;
   1134             mRealtimeStart = realtime;
   1135             mUnpluggedUptime = getUptime(mUptimeStart);
   1136             mUnpluggedRealtime = getRealtime(mRealtimeStart);
   1137         }
   1138 
   1139         public void reset(long uptime, long realtime) {
   1140             if (!mRunning) {
   1141                 mPastUptime = 0;
   1142                 mPastRealtime = 0;
   1143             } else {
   1144                 mUptimeStart = uptime;
   1145                 mRealtimeStart = realtime;
   1146                 // TODO: Since mUptimeStart was just reset and we are running, getUptime will
   1147                 // just return mPastUptime. Also, are we sure we don't want to reset that?
   1148                 mUnpluggedUptime = getUptime(uptime);
   1149                 // TODO: likewise.
   1150                 mUnpluggedRealtime = getRealtime(realtime);
   1151             }
   1152         }
   1153 
   1154         public long computeUptime(long curTime, int which) {
   1155             switch (which) {
   1156                 case STATS_SINCE_CHARGED:
   1157                     return mUptime + getUptime(curTime);
   1158                 case STATS_CURRENT:
   1159                     return getUptime(curTime);
   1160                 case STATS_SINCE_UNPLUGGED:
   1161                     return getUptime(curTime) - mUnpluggedUptime;
   1162             }
   1163             return 0;
   1164         }
   1165 
   1166         public long computeRealtime(long curTime, int which) {
   1167             switch (which) {
   1168                 case STATS_SINCE_CHARGED:
   1169                     return mRealtime + getRealtime(curTime);
   1170                 case STATS_CURRENT:
   1171                     return getRealtime(curTime);
   1172                 case STATS_SINCE_UNPLUGGED:
   1173                     return getRealtime(curTime) - mUnpluggedRealtime;
   1174             }
   1175             return 0;
   1176         }
   1177 
   1178         public long getUptime(long curTime) {
   1179             long time = mPastUptime;
   1180             if (mRunning) {
   1181                 time += curTime - mUptimeStart;
   1182             }
   1183             return time;
   1184         }
   1185 
   1186         public long getRealtime(long curTime) {
   1187             long time = mPastRealtime;
   1188             if (mRunning) {
   1189                 time += curTime - mRealtimeStart;
   1190             }
   1191             return time;
   1192         }
   1193 
   1194         public long getUptimeStart() {
   1195             return mUptimeStart;
   1196         }
   1197 
   1198         public long getRealtimeStart() {
   1199             return mRealtimeStart;
   1200         }
   1201 
   1202         public boolean isRunning() {
   1203             return mRunning;
   1204         }
   1205 
   1206         public boolean setRunning(boolean running, long uptime, long realtime) {
   1207             if (mRunning != running) {
   1208                 mRunning = running;
   1209                 if (running) {
   1210                     mUptimeStart = uptime;
   1211                     mRealtimeStart = realtime;
   1212                     long batteryUptime = mUnpluggedUptime = getUptime(uptime);
   1213                     long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
   1214 
   1215                     for (int i = mObservers.size() - 1; i >= 0; i--) {
   1216                         mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime);
   1217                     }
   1218                 } else {
   1219                     mPastUptime += uptime - mUptimeStart;
   1220                     mPastRealtime += realtime - mRealtimeStart;
   1221 
   1222                     long batteryUptime = getUptime(uptime);
   1223                     long batteryRealtime = getRealtime(realtime);
   1224 
   1225                     for (int i = mObservers.size() - 1; i >= 0; i--) {
   1226                         mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime);
   1227                     }
   1228                 }
   1229                 return true;
   1230             }
   1231             return false;
   1232         }
   1233 
   1234         public void readSummaryFromParcel(Parcel in) {
   1235             mUptime = in.readLong();
   1236             mRealtime = in.readLong();
   1237         }
   1238 
   1239         public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
   1240             out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
   1241             out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
   1242         }
   1243 
   1244         public void readFromParcel(Parcel in) {
   1245             mRunning = false;
   1246             mUptime = in.readLong();
   1247             mPastUptime = in.readLong();
   1248             mUptimeStart = in.readLong();
   1249             mRealtime = in.readLong();
   1250             mPastRealtime = in.readLong();
   1251             mRealtimeStart = in.readLong();
   1252             mUnpluggedUptime = in.readLong();
   1253             mUnpluggedRealtime = in.readLong();
   1254         }
   1255 
   1256         public void writeToParcel(Parcel out, long uptime, long realtime) {
   1257             final long runningUptime = getUptime(uptime);
   1258             final long runningRealtime = getRealtime(realtime);
   1259             out.writeLong(mUptime);
   1260             out.writeLong(runningUptime);
   1261             out.writeLong(mUptimeStart);
   1262             out.writeLong(mRealtime);
   1263             out.writeLong(runningRealtime);
   1264             out.writeLong(mRealtimeStart);
   1265             out.writeLong(mUnpluggedUptime);
   1266             out.writeLong(mUnpluggedRealtime);
   1267         }
   1268     }
   1269 
   1270     /**
   1271      * State for keeping track of counting information.
   1272      */
   1273     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
   1274         final AtomicInteger mCount = new AtomicInteger();
   1275         final TimeBase mTimeBase;
   1276         int mLoadedCount;
   1277         int mUnpluggedCount;
   1278         int mPluggedCount;
   1279 
   1280         public Counter(TimeBase timeBase, Parcel in) {
   1281             mTimeBase = timeBase;
   1282             mPluggedCount = in.readInt();
   1283             mCount.set(mPluggedCount);
   1284             mLoadedCount = in.readInt();
   1285             mUnpluggedCount = in.readInt();
   1286             timeBase.add(this);
   1287         }
   1288 
   1289         public Counter(TimeBase timeBase) {
   1290             mTimeBase = timeBase;
   1291             timeBase.add(this);
   1292         }
   1293 
   1294         public void writeToParcel(Parcel out) {
   1295             out.writeInt(mCount.get());
   1296             out.writeInt(mLoadedCount);
   1297             out.writeInt(mUnpluggedCount);
   1298         }
   1299 
   1300         @Override
   1301         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1302             mUnpluggedCount = mPluggedCount;
   1303         }
   1304 
   1305         @Override
   1306         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1307             mPluggedCount = mCount.get();
   1308         }
   1309 
   1310         /**
   1311          * Writes a possibly null Counter to a Parcel.
   1312          *
   1313          * @param out the Parcel to be written to.
   1314          * @param counter a Counter, or null.
   1315          */
   1316         public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
   1317             if (counter == null) {
   1318                 out.writeInt(0); // indicates null
   1319                 return;
   1320             }
   1321             out.writeInt(1); // indicates non-null
   1322 
   1323             counter.writeToParcel(out);
   1324         }
   1325 
   1326         /**
   1327          * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
   1328          * @param timeBase the timebase to assign to the Counter
   1329          * @param in the parcel to read from
   1330          * @return the Counter or null.
   1331          */
   1332         public static @Nullable Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
   1333             if (in.readInt() == 0) {
   1334                 return null;
   1335             }
   1336             return new Counter(timeBase, in);
   1337         }
   1338 
   1339         @Override
   1340         public int getCountLocked(int which) {
   1341             int val = mCount.get();
   1342             if (which == STATS_SINCE_UNPLUGGED) {
   1343                 val -= mUnpluggedCount;
   1344             } else if (which != STATS_SINCE_CHARGED) {
   1345                 val -= mLoadedCount;
   1346             }
   1347 
   1348             return val;
   1349         }
   1350 
   1351         public void logState(Printer pw, String prefix) {
   1352             pw.println(prefix + "mCount=" + mCount.get()
   1353                     + " mLoadedCount=" + mLoadedCount
   1354                     + " mUnpluggedCount=" + mUnpluggedCount
   1355                     + " mPluggedCount=" + mPluggedCount);
   1356         }
   1357 
   1358         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
   1359         public void stepAtomic() {
   1360             if (mTimeBase.isRunning()) {
   1361                 mCount.incrementAndGet();
   1362             }
   1363         }
   1364 
   1365         void addAtomic(int delta) {
   1366             if (mTimeBase.isRunning()) {
   1367                 mCount.addAndGet(delta);
   1368             }
   1369         }
   1370 
   1371         /**
   1372          * Clear state of this counter.
   1373          */
   1374         void reset(boolean detachIfReset) {
   1375             mCount.set(0);
   1376             mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
   1377             if (detachIfReset) {
   1378                 detach();
   1379             }
   1380         }
   1381 
   1382         void detach() {
   1383             mTimeBase.remove(this);
   1384         }
   1385 
   1386         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
   1387         public void writeSummaryFromParcelLocked(Parcel out) {
   1388             int count = mCount.get();
   1389             out.writeInt(count);
   1390         }
   1391 
   1392         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
   1393         public void readSummaryFromParcelLocked(Parcel in) {
   1394             mLoadedCount = in.readInt();
   1395             mCount.set(mLoadedCount);
   1396             mUnpluggedCount = mPluggedCount = mLoadedCount;
   1397         }
   1398     }
   1399 
   1400     @VisibleForTesting
   1401     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
   1402         final TimeBase mTimeBase;
   1403         public long[] mCounts;
   1404         public long[] mLoadedCounts;
   1405         public long[] mUnpluggedCounts;
   1406 
   1407         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
   1408             mTimeBase = timeBase;
   1409             mCounts = in.createLongArray();
   1410             mLoadedCounts = in.createLongArray();
   1411             mUnpluggedCounts = in.createLongArray();
   1412             timeBase.add(this);
   1413         }
   1414 
   1415         public LongSamplingCounterArray(TimeBase timeBase) {
   1416             mTimeBase = timeBase;
   1417             timeBase.add(this);
   1418         }
   1419 
   1420         private void writeToParcel(Parcel out) {
   1421             out.writeLongArray(mCounts);
   1422             out.writeLongArray(mLoadedCounts);
   1423             out.writeLongArray(mUnpluggedCounts);
   1424         }
   1425 
   1426         @Override
   1427         public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
   1428             mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
   1429         }
   1430 
   1431         @Override
   1432         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1433         }
   1434 
   1435         @Override
   1436         public long[] getCountsLocked(int which) {
   1437             long[] val = copyArray(mCounts, null);
   1438             if (which == STATS_SINCE_UNPLUGGED) {
   1439                 subtract(val, mUnpluggedCounts);
   1440             } else if (which != STATS_SINCE_CHARGED) {
   1441                 subtract(val, mLoadedCounts);
   1442             }
   1443             return val;
   1444         }
   1445 
   1446         @Override
   1447         public void logState(Printer pw, String prefix) {
   1448             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts)
   1449                     + " mLoadedCounts=" + Arrays.toString(mLoadedCounts)
   1450                     + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts));
   1451         }
   1452 
   1453         public void addCountLocked(long[] counts) {
   1454             addCountLocked(counts, mTimeBase.isRunning());
   1455         }
   1456 
   1457         public void addCountLocked(long[] counts, boolean isRunning) {
   1458             if (counts == null) {
   1459                 return;
   1460             }
   1461             if (isRunning) {
   1462                 if (mCounts == null) {
   1463                     mCounts = new long[counts.length];
   1464                 }
   1465                 for (int i = 0; i < counts.length; ++i) {
   1466                     mCounts[i] += counts[i];
   1467                 }
   1468             }
   1469         }
   1470 
   1471         public int getSize() {
   1472             return mCounts == null ? 0 : mCounts.length;
   1473         }
   1474 
   1475         /**
   1476          * Clear state of this counter.
   1477          */
   1478         public void reset(boolean detachIfReset) {
   1479             fillArray(mCounts, 0);
   1480             fillArray(mLoadedCounts, 0);
   1481             fillArray(mUnpluggedCounts, 0);
   1482             if (detachIfReset) {
   1483                 detach();
   1484             }
   1485         }
   1486 
   1487         public void detach() {
   1488             mTimeBase.remove(this);
   1489         }
   1490 
   1491         private void writeSummaryToParcelLocked(Parcel out) {
   1492             out.writeLongArray(mCounts);
   1493         }
   1494 
   1495         private void readSummaryFromParcelLocked(Parcel in) {
   1496             mCounts = in.createLongArray();
   1497             mLoadedCounts = copyArray(mCounts, mLoadedCounts);
   1498             mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
   1499         }
   1500 
   1501         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
   1502             if (counterArray != null) {
   1503                 out.writeInt(1);
   1504                 counterArray.writeToParcel(out);
   1505             } else {
   1506                 out.writeInt(0);
   1507             }
   1508         }
   1509 
   1510         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
   1511             if (in.readInt() != 0) {
   1512                 return new LongSamplingCounterArray(timeBase, in);
   1513             } else {
   1514                 return null;
   1515             }
   1516         }
   1517 
   1518         public static void writeSummaryToParcelLocked(Parcel out,
   1519                 LongSamplingCounterArray counterArray) {
   1520             if (counterArray != null) {
   1521                 out.writeInt(1);
   1522                 counterArray.writeSummaryToParcelLocked(out);
   1523             } else {
   1524                 out.writeInt(0);
   1525             }
   1526         }
   1527 
   1528         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
   1529                 TimeBase timeBase) {
   1530             if (in.readInt() != 0) {
   1531                 final LongSamplingCounterArray counterArray
   1532                         = new LongSamplingCounterArray(timeBase);
   1533                 counterArray.readSummaryFromParcelLocked(in);
   1534                 return counterArray;
   1535             } else {
   1536                 return null;
   1537             }
   1538         }
   1539 
   1540         private static void fillArray(long[] a, long val) {
   1541             if (a != null) {
   1542                 Arrays.fill(a, val);
   1543             }
   1544         }
   1545 
   1546         private static void subtract(@NonNull long[] val, long[] toSubtract) {
   1547             if (toSubtract == null) {
   1548                 return;
   1549             }
   1550             for (int i = 0; i < val.length; i++) {
   1551                 val[i] -= toSubtract[i];
   1552             }
   1553         }
   1554 
   1555         private static long[] copyArray(long[] src, long[] dest) {
   1556             if (src == null) {
   1557                 return null;
   1558             } else {
   1559                 if (dest == null) {
   1560                     dest = new long[src.length];
   1561                 }
   1562                 System.arraycopy(src, 0, dest, 0, src.length);
   1563                 return dest;
   1564             }
   1565         }
   1566     }
   1567 
   1568     @VisibleForTesting
   1569     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
   1570         final TimeBase mTimeBase;
   1571         public long mCount;
   1572         public long mCurrentCount;
   1573         public long mLoadedCount;
   1574         public long mUnpluggedCount;
   1575 
   1576         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
   1577             mTimeBase = timeBase;
   1578             mCount = in.readLong();
   1579             mCurrentCount = in.readLong();
   1580             mLoadedCount = in.readLong();
   1581             mUnpluggedCount = in.readLong();
   1582             timeBase.add(this);
   1583         }
   1584 
   1585         public LongSamplingCounter(TimeBase timeBase) {
   1586             mTimeBase = timeBase;
   1587             timeBase.add(this);
   1588         }
   1589 
   1590         public void writeToParcel(Parcel out) {
   1591             out.writeLong(mCount);
   1592             out.writeLong(mCurrentCount);
   1593             out.writeLong(mLoadedCount);
   1594             out.writeLong(mUnpluggedCount);
   1595         }
   1596 
   1597         @Override
   1598         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1599             mUnpluggedCount = mCount;
   1600         }
   1601 
   1602         @Override
   1603         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1604         }
   1605 
   1606         public long getCountLocked(int which) {
   1607             long val = mCount;
   1608             if (which == STATS_SINCE_UNPLUGGED) {
   1609                 val -= mUnpluggedCount;
   1610             } else if (which != STATS_SINCE_CHARGED) {
   1611                 val -= mLoadedCount;
   1612             }
   1613             return val;
   1614         }
   1615 
   1616         @Override
   1617         public void logState(Printer pw, String prefix) {
   1618             pw.println(prefix + "mCount=" + mCount
   1619                     + " mCurrentCount=" + mCurrentCount
   1620                     + " mLoadedCount=" + mLoadedCount
   1621                     + " mUnpluggedCount=" + mUnpluggedCount);
   1622         }
   1623 
   1624         public void addCountLocked(long count) {
   1625             update(mCurrentCount + count, mTimeBase.isRunning());
   1626         }
   1627 
   1628         public void addCountLocked(long count, boolean isRunning) {
   1629             update(mCurrentCount + count, isRunning);
   1630         }
   1631 
   1632         public void update(long count) {
   1633             update(count, mTimeBase.isRunning());
   1634         }
   1635 
   1636         public void update(long count, boolean isRunning) {
   1637             if (count < mCurrentCount) {
   1638                 mCurrentCount = 0;
   1639             }
   1640             if (isRunning) {
   1641                 mCount += count - mCurrentCount;
   1642             }
   1643             mCurrentCount = count;
   1644         }
   1645 
   1646         /**
   1647          * Clear state of this counter.
   1648          */
   1649         public void reset(boolean detachIfReset) {
   1650             mCount = 0;
   1651             mLoadedCount = mUnpluggedCount = 0;
   1652             if (detachIfReset) {
   1653                 detach();
   1654             }
   1655         }
   1656 
   1657         public void detach() {
   1658             mTimeBase.remove(this);
   1659         }
   1660 
   1661         public void writeSummaryFromParcelLocked(Parcel out) {
   1662             out.writeLong(mCount);
   1663         }
   1664 
   1665         public void readSummaryFromParcelLocked(Parcel in) {
   1666             mCount = mUnpluggedCount= mLoadedCount = in.readLong();
   1667         }
   1668     }
   1669 
   1670     /**
   1671      * State for keeping track of timing information.
   1672      */
   1673     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
   1674         protected final Clocks mClocks;
   1675         protected final int mType;
   1676         protected final TimeBase mTimeBase;
   1677 
   1678         protected int mCount;
   1679         protected int mLoadedCount;
   1680         protected int mLastCount;
   1681         protected int mUnpluggedCount;
   1682 
   1683         // Times are in microseconds for better accuracy when dividing by the
   1684         // lock count, and are in "battery realtime" units.
   1685 
   1686         /**
   1687          * The total time we have accumulated since the start of the original
   1688          * boot, to the last time something interesting happened in the
   1689          * current run.
   1690          */
   1691         protected long mTotalTime;
   1692 
   1693         /**
   1694          * The total time we loaded for the previous runs.  Subtract this from
   1695          * mTotalTime to find the time for the current run of the system.
   1696          */
   1697         protected long mLoadedTime;
   1698 
   1699         /**
   1700          * The run time of the last run of the system, as loaded from the
   1701          * saved data.
   1702          */
   1703         protected long mLastTime;
   1704 
   1705         /**
   1706          * The value of mTotalTime when unplug() was last called.  Subtract
   1707          * this from mTotalTime to find the time since the last unplug from
   1708          * power.
   1709          */
   1710         protected long mUnpluggedTime;
   1711 
   1712         /**
   1713          * The total time this timer has been running until the latest mark has been set.
   1714          * Subtract this from mTotalTime to get the time spent running since the mark was set.
   1715          */
   1716         protected long mTimeBeforeMark;
   1717 
   1718         /**
   1719          * Constructs from a parcel.
   1720          * @param type
   1721          * @param timeBase
   1722          * @param in
   1723          */
   1724         public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
   1725             mClocks = clocks;
   1726             mType = type;
   1727             mTimeBase = timeBase;
   1728 
   1729             mCount = in.readInt();
   1730             mLoadedCount = in.readInt();
   1731             mLastCount = 0;
   1732             mUnpluggedCount = in.readInt();
   1733             mTotalTime = in.readLong();
   1734             mLoadedTime = in.readLong();
   1735             mLastTime = 0;
   1736             mUnpluggedTime = in.readLong();
   1737             mTimeBeforeMark = in.readLong();
   1738             timeBase.add(this);
   1739             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
   1740         }
   1741 
   1742         public Timer(Clocks clocks, int type, TimeBase timeBase) {
   1743             mClocks = clocks;
   1744             mType = type;
   1745             mTimeBase = timeBase;
   1746             timeBase.add(this);
   1747         }
   1748 
   1749         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
   1750 
   1751         protected abstract int computeCurrentCountLocked();
   1752 
   1753         /**
   1754          * Clear state of this timer.  Returns true if the timer is inactive
   1755          * so can be completely dropped.
   1756          */
   1757         public boolean reset(boolean detachIfReset) {
   1758             mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0;
   1759             mCount = mLoadedCount = mLastCount = 0;
   1760             if (detachIfReset) {
   1761                 detach();
   1762             }
   1763             return true;
   1764         }
   1765 
   1766         public void detach() {
   1767             mTimeBase.remove(this);
   1768         }
   1769 
   1770         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   1771             if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
   1772                     + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
   1773             out.writeInt(computeCurrentCountLocked());
   1774             out.writeInt(mLoadedCount);
   1775             out.writeInt(mUnpluggedCount);
   1776             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
   1777             out.writeLong(mLoadedTime);
   1778             out.writeLong(mUnpluggedTime);
   1779             out.writeLong(mTimeBeforeMark);
   1780         }
   1781 
   1782         @Override
   1783         public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
   1784             if (DEBUG && mType < 0) {
   1785                 Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime
   1786                         + " old mUnpluggedTime=" + mUnpluggedTime
   1787                         + " old mUnpluggedCount=" + mUnpluggedCount);
   1788             }
   1789             mUnpluggedTime = computeRunTimeLocked(baseRealtime);
   1790             mUnpluggedCount = computeCurrentCountLocked();
   1791             if (DEBUG && mType < 0) {
   1792                 Log.v(TAG, "unplug #" + mType
   1793                         + ": new mUnpluggedTime=" + mUnpluggedTime
   1794                         + " new mUnpluggedCount=" + mUnpluggedCount);
   1795             }
   1796         }
   1797 
   1798         @Override
   1799         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   1800             if (DEBUG && mType < 0) {
   1801                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
   1802                         + " old mTotalTime=" + mTotalTime);
   1803             }
   1804             mTotalTime = computeRunTimeLocked(baseRealtime);
   1805             mCount = computeCurrentCountLocked();
   1806             if (DEBUG && mType < 0) {
   1807                 Log.v(TAG, "plug #" + mType
   1808                         + ": new mTotalTime=" + mTotalTime);
   1809             }
   1810         }
   1811 
   1812         /**
   1813          * Writes a possibly null Timer to a Parcel.
   1814          *
   1815          * @param out the Parcel to be written to.
   1816          * @param timer a Timer, or null.
   1817          */
   1818         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
   1819             if (timer == null) {
   1820                 out.writeInt(0); // indicates null
   1821                 return;
   1822             }
   1823             out.writeInt(1); // indicates non-null
   1824 
   1825             timer.writeToParcel(out, elapsedRealtimeUs);
   1826         }
   1827 
   1828         @Override
   1829         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
   1830             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
   1831             if (which == STATS_SINCE_UNPLUGGED) {
   1832                 val -= mUnpluggedTime;
   1833             } else if (which != STATS_SINCE_CHARGED) {
   1834                 val -= mLoadedTime;
   1835             }
   1836 
   1837             return val;
   1838         }
   1839 
   1840         @Override
   1841         public int getCountLocked(int which) {
   1842             int val = computeCurrentCountLocked();
   1843             if (which == STATS_SINCE_UNPLUGGED) {
   1844                 val -= mUnpluggedCount;
   1845             } else if (which != STATS_SINCE_CHARGED) {
   1846                 val -= mLoadedCount;
   1847             }
   1848 
   1849             return val;
   1850         }
   1851 
   1852         @Override
   1853         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
   1854             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
   1855             return val - mTimeBeforeMark;
   1856         }
   1857 
   1858         @Override
   1859         public void logState(Printer pw, String prefix) {
   1860             pw.println(prefix + "mCount=" + mCount
   1861                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
   1862                     + " mUnpluggedCount=" + mUnpluggedCount);
   1863             pw.println(prefix + "mTotalTime=" + mTotalTime
   1864                     + " mLoadedTime=" + mLoadedTime);
   1865             pw.println(prefix + "mLastTime=" + mLastTime
   1866                     + " mUnpluggedTime=" + mUnpluggedTime);
   1867         }
   1868 
   1869 
   1870         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
   1871             long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
   1872             out.writeLong(runTime);
   1873             out.writeInt(computeCurrentCountLocked());
   1874         }
   1875 
   1876         public void readSummaryFromParcelLocked(Parcel in) {
   1877             // Multiply by 1000 for backwards compatibility
   1878             mTotalTime = mLoadedTime = in.readLong();
   1879             mLastTime = 0;
   1880             mUnpluggedTime = mTotalTime;
   1881             mCount = mLoadedCount = in.readInt();
   1882             mLastCount = 0;
   1883             mUnpluggedCount = mCount;
   1884 
   1885             // When reading the summary, we set the mark to be the latest information.
   1886             mTimeBeforeMark = mTotalTime;
   1887         }
   1888     }
   1889 
   1890     /**
   1891      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
   1892      * method. The state of the timer according to its {@link TimeBase} will determine how much
   1893      * of the value is recorded.
   1894      *
   1895      * If the value being recorded resets, {@link #endSample()} can be called in order to
   1896      * account for the change. If the value passed in to {@link #update(long, int)} decreased
   1897      * between calls, the {@link #endSample()} is automatically called and the new value is
   1898      * expected to increase monotonically from that point on.
   1899      */
   1900     public static class SamplingTimer extends Timer {
   1901 
   1902         /**
   1903          * The most recent reported count from /proc/wakelocks.
   1904          */
   1905         int mCurrentReportedCount;
   1906 
   1907         /**
   1908          * The reported count from /proc/wakelocks when unplug() was last
   1909          * called.
   1910          */
   1911         int mUnpluggedReportedCount;
   1912 
   1913         /**
   1914          * The most recent reported total_time from /proc/wakelocks.
   1915          */
   1916         long mCurrentReportedTotalTime;
   1917 
   1918 
   1919         /**
   1920          * The reported total_time from /proc/wakelocks when unplug() was last
   1921          * called.
   1922          */
   1923         long mUnpluggedReportedTotalTime;
   1924 
   1925         /**
   1926          * Whether we are currently in a discharge cycle.
   1927          */
   1928         boolean mTimeBaseRunning;
   1929 
   1930         /**
   1931          * Whether we are currently recording reported values.
   1932          */
   1933         boolean mTrackingReportedValues;
   1934 
   1935         /*
   1936          * A sequence counter, incremented once for each update of the stats.
   1937          */
   1938         int mUpdateVersion;
   1939 
   1940         @VisibleForTesting
   1941         public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
   1942             super(clocks, 0, timeBase, in);
   1943             mCurrentReportedCount = in.readInt();
   1944             mUnpluggedReportedCount = in.readInt();
   1945             mCurrentReportedTotalTime = in.readLong();
   1946             mUnpluggedReportedTotalTime = in.readLong();
   1947             mTrackingReportedValues = in.readInt() == 1;
   1948             mTimeBaseRunning = timeBase.isRunning();
   1949         }
   1950 
   1951         @VisibleForTesting
   1952         public SamplingTimer(Clocks clocks, TimeBase timeBase) {
   1953             super(clocks, 0, timeBase);
   1954             mTrackingReportedValues = false;
   1955             mTimeBaseRunning = timeBase.isRunning();
   1956         }
   1957 
   1958         /**
   1959          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
   1960          * be less than the values used for a previous invocation.
   1961          */
   1962         public void endSample() {
   1963             mTotalTime = computeRunTimeLocked(0 /* unused by us */);
   1964             mCount = computeCurrentCountLocked();
   1965             mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
   1966             mUnpluggedReportedCount = mCurrentReportedCount = 0;
   1967         }
   1968 
   1969         public void setUpdateVersion(int version) {
   1970             mUpdateVersion = version;
   1971         }
   1972 
   1973         public int getUpdateVersion() {
   1974             return mUpdateVersion;
   1975         }
   1976 
   1977         /**
   1978          * Updates the current recorded values. These are meant to be monotonically increasing
   1979          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
   1980          *
   1981          * If the values being recorded have been reset, the monotonically increasing requirement
   1982          * will be broken. In this case, {@link #endSample()} is automatically called and
   1983          * the total value of totalTime and count are recorded, starting a new monotonically
   1984          * increasing sample.
   1985          *
   1986          * @param totalTime total time of sample in microseconds.
   1987          * @param count total number of times the event being sampled occurred.
   1988          */
   1989         public void update(long totalTime, int count) {
   1990             if (mTimeBaseRunning && !mTrackingReportedValues) {
   1991                 // Updating the reported value for the first time.
   1992                 mUnpluggedReportedTotalTime = totalTime;
   1993                 mUnpluggedReportedCount = count;
   1994             }
   1995 
   1996             mTrackingReportedValues = true;
   1997 
   1998             if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) {
   1999                 endSample();
   2000             }
   2001 
   2002             mCurrentReportedTotalTime = totalTime;
   2003             mCurrentReportedCount = count;
   2004         }
   2005 
   2006         /**
   2007          * Adds deltaTime and deltaCount to the current sample.
   2008          *
   2009          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
   2010          * @param deltaCount additional number of times the event being sampled occurred.
   2011          */
   2012         public void add(long deltaTime, int deltaCount) {
   2013             update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount);
   2014         }
   2015 
   2016         @Override
   2017         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   2018             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
   2019             if (mTrackingReportedValues) {
   2020                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
   2021                 mUnpluggedReportedCount = mCurrentReportedCount;
   2022             }
   2023             mTimeBaseRunning = true;
   2024         }
   2025 
   2026         @Override
   2027         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   2028             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
   2029             mTimeBaseRunning = false;
   2030         }
   2031 
   2032         @Override
   2033         public void logState(Printer pw, String prefix) {
   2034             super.logState(pw, prefix);
   2035             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
   2036                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
   2037                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
   2038                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
   2039         }
   2040 
   2041         @Override
   2042         protected long computeRunTimeLocked(long curBatteryRealtime) {
   2043             return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
   2044                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
   2045         }
   2046 
   2047         @Override
   2048         protected int computeCurrentCountLocked() {
   2049             return mCount + (mTimeBaseRunning && mTrackingReportedValues
   2050                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
   2051         }
   2052 
   2053         @Override
   2054         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   2055             super.writeToParcel(out, elapsedRealtimeUs);
   2056             out.writeInt(mCurrentReportedCount);
   2057             out.writeInt(mUnpluggedReportedCount);
   2058             out.writeLong(mCurrentReportedTotalTime);
   2059             out.writeLong(mUnpluggedReportedTotalTime);
   2060             out.writeInt(mTrackingReportedValues ? 1 : 0);
   2061         }
   2062 
   2063         @Override
   2064         public boolean reset(boolean detachIfReset) {
   2065             super.reset(detachIfReset);
   2066             mTrackingReportedValues = false;
   2067             mUnpluggedReportedTotalTime = 0;
   2068             mUnpluggedReportedCount = 0;
   2069             return true;
   2070         }
   2071     }
   2072 
   2073     /**
   2074      * A timer that increments in batches.  It does not run for durations, but just jumps
   2075      * for a pre-determined amount.
   2076      */
   2077     public static class BatchTimer extends Timer {
   2078         final Uid mUid;
   2079 
   2080         /**
   2081          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
   2082          */
   2083         long mLastAddedTime;
   2084 
   2085         /**
   2086          * The last duration that we added to the timer.  This is in microseconds.
   2087          */
   2088         long mLastAddedDuration;
   2089 
   2090         /**
   2091          * Whether we are currently in a discharge cycle.
   2092          */
   2093         boolean mInDischarge;
   2094 
   2095         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
   2096             super(clocks, type, timeBase, in);
   2097             mUid = uid;
   2098             mLastAddedTime = in.readLong();
   2099             mLastAddedDuration = in.readLong();
   2100             mInDischarge = timeBase.isRunning();
   2101         }
   2102 
   2103         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
   2104             super(clocks, type, timeBase);
   2105             mUid = uid;
   2106             mInDischarge = timeBase.isRunning();
   2107         }
   2108 
   2109         @Override
   2110         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   2111             super.writeToParcel(out, elapsedRealtimeUs);
   2112             out.writeLong(mLastAddedTime);
   2113             out.writeLong(mLastAddedDuration);
   2114         }
   2115 
   2116         @Override
   2117         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   2118             recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
   2119             mInDischarge = false;
   2120             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
   2121         }
   2122 
   2123         @Override
   2124         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   2125             recomputeLastDuration(elapsedRealtime, false);
   2126             mInDischarge = true;
   2127             // If we are still within the last added duration, then re-added whatever remains.
   2128             if (mLastAddedTime == elapsedRealtime) {
   2129                 mTotalTime += mLastAddedDuration;
   2130             }
   2131             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
   2132         }
   2133 
   2134         @Override
   2135         public void logState(Printer pw, String prefix) {
   2136             super.logState(pw, prefix);
   2137             pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
   2138                     + " mLastAddedDuration=" + mLastAddedDuration);
   2139         }
   2140 
   2141         private long computeOverage(long curTime) {
   2142             if (mLastAddedTime > 0) {
   2143                 return mLastTime + mLastAddedDuration - curTime;
   2144             }
   2145             return 0;
   2146         }
   2147 
   2148         private void recomputeLastDuration(long curTime, boolean abort) {
   2149             final long overage = computeOverage(curTime);
   2150             if (overage > 0) {
   2151                 // Aborting before the duration ran out -- roll back the remaining
   2152                 // duration.  Only do this if currently discharging; otherwise we didn't
   2153                 // actually add the time.
   2154                 if (mInDischarge) {
   2155                     mTotalTime -= overage;
   2156                 }
   2157                 if (abort) {
   2158                     mLastAddedTime = 0;
   2159                 } else {
   2160                     mLastAddedTime = curTime;
   2161                     mLastAddedDuration -= overage;
   2162                 }
   2163             }
   2164         }
   2165 
   2166         public void addDuration(BatteryStatsImpl stats, long durationMillis) {
   2167             final long now = mClocks.elapsedRealtime() * 1000;
   2168             recomputeLastDuration(now, true);
   2169             mLastAddedTime = now;
   2170             mLastAddedDuration = durationMillis * 1000;
   2171             if (mInDischarge) {
   2172                 mTotalTime += mLastAddedDuration;
   2173                 mCount++;
   2174             }
   2175         }
   2176 
   2177         public void abortLastDuration(BatteryStatsImpl stats) {
   2178             final long now = mClocks.elapsedRealtime() * 1000;
   2179             recomputeLastDuration(now, true);
   2180         }
   2181 
   2182         @Override
   2183         protected int computeCurrentCountLocked() {
   2184             return mCount;
   2185         }
   2186 
   2187         @Override
   2188         protected long computeRunTimeLocked(long curBatteryRealtime) {
   2189             final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
   2190             if (overage > 0) {
   2191                 return mTotalTime = overage;
   2192             }
   2193             return mTotalTime;
   2194         }
   2195 
   2196         @Override
   2197         public boolean reset(boolean detachIfReset) {
   2198             final long now = mClocks.elapsedRealtime() * 1000;
   2199             recomputeLastDuration(now, true);
   2200             boolean stillActive = mLastAddedTime == now;
   2201             super.reset(!stillActive && detachIfReset);
   2202             return !stillActive;
   2203         }
   2204     }
   2205 
   2206 
   2207     /**
   2208      * A StopwatchTimer that also tracks the total and max individual
   2209      * time spent active according to the given timebase.  Whereas
   2210      * StopwatchTimer apportions the time amongst all in the pool,
   2211      * the total and max durations are not apportioned.
   2212      */
   2213     public static class DurationTimer extends StopwatchTimer {
   2214         /**
   2215          * The time (in ms) that the timer was last acquired or the time base
   2216          * last (re-)started. Increasing the nesting depth does not reset this time.
   2217          *
   2218          * -1 if the timer is currently not running or the time base is not running.
   2219          *
   2220          * If written to a parcel, the start time is reset, as is mNesting in the base class
   2221          * StopwatchTimer.
   2222          */
   2223         long mStartTimeMs = -1;
   2224 
   2225         /**
   2226          * The longest time period (in ms) that the timer has been active. Not pooled.
   2227          */
   2228         long mMaxDurationMs;
   2229 
   2230         /**
   2231          * The time (in ms) that that the timer has been active since most recent
   2232          * stopRunningLocked() or reset(). Not pooled.
   2233          */
   2234         long mCurrentDurationMs;
   2235 
   2236         /**
   2237          * The total time (in ms) that that the timer has been active since most recent reset()
   2238          * prior to the current startRunningLocked. This is the sum of all past currentDurations
   2239          * (but not including the present currentDuration) since reset. Not pooled.
   2240          */
   2241         long mTotalDurationMs;
   2242 
   2243         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   2244                 TimeBase timeBase, Parcel in) {
   2245             super(clocks, uid, type, timerPool, timeBase, in);
   2246             mMaxDurationMs = in.readLong();
   2247             mTotalDurationMs = in.readLong();
   2248             mCurrentDurationMs = in.readLong();
   2249         }
   2250 
   2251         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   2252                 TimeBase timeBase) {
   2253             super(clocks, uid, type, timerPool, timeBase);
   2254         }
   2255 
   2256         @Override
   2257         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   2258             super.writeToParcel(out, elapsedRealtimeUs);
   2259             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
   2260             out.writeLong(mTotalDurationMs);
   2261             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
   2262         }
   2263 
   2264         /**
   2265          * Write the summary to the parcel.
   2266          *
   2267          * Since the time base is probably meaningless after we come back, reading
   2268          * from this will have the effect of stopping the timer. So here all we write
   2269          * is the max and total durations.
   2270          */
   2271         @Override
   2272         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
   2273             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
   2274             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
   2275             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
   2276         }
   2277 
   2278         /**
   2279          * Read the summary parcel.
   2280          *
   2281          * Has the side effect of stopping the timer.
   2282          */
   2283         @Override
   2284         public void readSummaryFromParcelLocked(Parcel in) {
   2285             super.readSummaryFromParcelLocked(in);
   2286             mMaxDurationMs = in.readLong();
   2287             mTotalDurationMs = in.readLong();
   2288             mStartTimeMs = -1;
   2289             mCurrentDurationMs = 0;
   2290         }
   2291 
   2292         /**
   2293          * The TimeBase time started (again).
   2294          *
   2295          * If the timer is also running, store the start time.
   2296          */
   2297         public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
   2298             super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
   2299             if (mNesting > 0) {
   2300                 mStartTimeMs = baseRealtime / 1000;
   2301             }
   2302         }
   2303 
   2304         /**
   2305          * The TimeBase stopped running.
   2306          *
   2307          * If the timer is running, add the duration into mCurrentDurationMs.
   2308          */
   2309         @Override
   2310         public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) {
   2311             super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs);
   2312             if (mNesting > 0) {
   2313                 // baseRealtimeUs has already been converted to the timebase's realtime.
   2314                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
   2315             }
   2316             mStartTimeMs = -1;
   2317         }
   2318 
   2319         @Override
   2320         public void logState(Printer pw, String prefix) {
   2321             super.logState(pw, prefix);
   2322         }
   2323 
   2324         @Override
   2325         public void startRunningLocked(long elapsedRealtimeMs) {
   2326             super.startRunningLocked(elapsedRealtimeMs);
   2327             if (mNesting == 1 && mTimeBase.isRunning()) {
   2328                 // Just started
   2329                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
   2330             }
   2331         }
   2332 
   2333         /**
   2334          * Decrements the mNesting ref-count on this timer.
   2335          *
   2336          * If it actually stopped (mNesting went to 0), then possibly update
   2337          * mMaxDuration if the current duration was the longest ever.
   2338          */
   2339         @Override
   2340         public void stopRunningLocked(long elapsedRealtimeMs) {
   2341             if (mNesting == 1) {
   2342                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
   2343                 mTotalDurationMs += durationMs;
   2344                 if (durationMs > mMaxDurationMs) {
   2345                     mMaxDurationMs = durationMs;
   2346                 }
   2347                 mStartTimeMs = -1;
   2348                 mCurrentDurationMs = 0;
   2349             }
   2350             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
   2351             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
   2352             super.stopRunningLocked(elapsedRealtimeMs);
   2353         }
   2354 
   2355         @Override
   2356         public boolean reset(boolean detachIfReset) {
   2357             boolean result = super.reset(detachIfReset);
   2358             mMaxDurationMs = 0;
   2359             mTotalDurationMs = 0;
   2360             mCurrentDurationMs = 0;
   2361             if (mNesting > 0) {
   2362                 mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
   2363             } else {
   2364                 mStartTimeMs = -1;
   2365             }
   2366             return result;
   2367         }
   2368 
   2369         /**
   2370          * Returns the max duration that this timer has ever seen.
   2371          *
   2372          * Note that this time is NOT split between the timers in the timer group that
   2373          * this timer is attached to.  It is the TOTAL time.
   2374          */
   2375         @Override
   2376         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
   2377             if (mNesting > 0) {
   2378                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
   2379                 if (durationMs > mMaxDurationMs) {
   2380                     return durationMs;
   2381                 }
   2382             }
   2383             return mMaxDurationMs;
   2384         }
   2385 
   2386         /**
   2387          * Returns the time since the timer was started.
   2388          * Returns 0 if the timer is not currently running.
   2389          *
   2390          * Note that this time is NOT split between the timers in the timer group that
   2391          * this timer is attached to.  It is the TOTAL time.
   2392          *
   2393          * Note that if running timer is parceled and unparceled, this method will return
   2394          * current duration value at the time of parceling even though timer may not be
   2395          * currently running.
   2396          */
   2397         @Override
   2398         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
   2399             long durationMs = mCurrentDurationMs;
   2400             if (mNesting > 0 && mTimeBase.isRunning()) {
   2401                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000)
   2402                         - mStartTimeMs;
   2403             }
   2404             return durationMs;
   2405         }
   2406 
   2407         /**
   2408          * Returns the total cumulative duration that this timer has been on since reset().
   2409          * If mTimerPool == null, this should be the same
   2410          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
   2411          *
   2412          * Note that this time is NOT split between the timers in the timer group that
   2413          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
   2414          * the result will not be equivalent to getTotalTimeLocked.
   2415          */
   2416         @Override
   2417         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
   2418             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
   2419         }
   2420     }
   2421 
   2422     /**
   2423      * State for keeping track of timing information.
   2424      */
   2425     public static class StopwatchTimer extends Timer {
   2426         final Uid mUid;
   2427         final ArrayList<StopwatchTimer> mTimerPool;
   2428 
   2429         int mNesting;
   2430 
   2431         /**
   2432          * The last time at which we updated the timer.  If mNesting is > 0,
   2433          * subtract this from the current battery time to find the amount of
   2434          * time we have been running since we last computed an update.
   2435          */
   2436         long mUpdateTime;
   2437 
   2438         /**
   2439          * The total time at which the timer was acquired, to determine if it
   2440          * was actually held for an interesting duration. If time base was not running when timer
   2441          * was acquired, will be -1.
   2442          */
   2443         long mAcquireTime = -1;
   2444 
   2445         long mTimeout;
   2446 
   2447         /**
   2448          * For partial wake locks, keep track of whether we are in the list
   2449          * to consume CPU cycles.
   2450          */
   2451         @VisibleForTesting
   2452         public boolean mInList;
   2453 
   2454         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   2455                 TimeBase timeBase, Parcel in) {
   2456             super(clocks, type, timeBase, in);
   2457             mUid = uid;
   2458             mTimerPool = timerPool;
   2459             mUpdateTime = in.readLong();
   2460         }
   2461 
   2462         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   2463                 TimeBase timeBase) {
   2464             super(clocks, type, timeBase);
   2465             mUid = uid;
   2466             mTimerPool = timerPool;
   2467         }
   2468 
   2469         public void setTimeout(long timeout) {
   2470             mTimeout = timeout;
   2471         }
   2472 
   2473         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   2474             super.writeToParcel(out, elapsedRealtimeUs);
   2475             out.writeLong(mUpdateTime);
   2476         }
   2477 
   2478         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   2479             if (mNesting > 0) {
   2480                 if (DEBUG && mType < 0) {
   2481                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
   2482                 }
   2483                 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
   2484                 mUpdateTime = baseRealtime;
   2485                 if (DEBUG && mType < 0) {
   2486                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
   2487                 }
   2488             }
   2489         }
   2490 
   2491         public void logState(Printer pw, String prefix) {
   2492             super.logState(pw, prefix);
   2493             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
   2494                     + " mAcquireTime=" + mAcquireTime);
   2495         }
   2496 
   2497         public void startRunningLocked(long elapsedRealtimeMs) {
   2498             if (mNesting++ == 0) {
   2499                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
   2500                 mUpdateTime = batteryRealtime;
   2501                 if (mTimerPool != null) {
   2502                     // Accumulate time to all currently active timers before adding
   2503                     // this new one to the pool.
   2504                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
   2505                     // Add this timer to the active pool
   2506                     mTimerPool.add(this);
   2507                 }
   2508                 if (mTimeBase.isRunning()) {
   2509                     // Increment the count
   2510                     mCount++;
   2511                     mAcquireTime = mTotalTime;
   2512                 } else {
   2513                     mAcquireTime = -1;
   2514                 }
   2515                 if (DEBUG && mType < 0) {
   2516                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
   2517                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
   2518                             + " mAcquireTime=" + mAcquireTime);
   2519                 }
   2520             }
   2521         }
   2522 
   2523         public boolean isRunningLocked() {
   2524             return mNesting > 0;
   2525         }
   2526 
   2527         public void stopRunningLocked(long elapsedRealtimeMs) {
   2528             // Ignore attempt to stop a timer that isn't running
   2529             if (mNesting == 0) {
   2530                 return;
   2531             }
   2532             if (--mNesting == 0) {
   2533                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
   2534                 if (mTimerPool != null) {
   2535                     // Accumulate time to all active counters, scaled by the total
   2536                     // active in the pool, before taking this one out of the pool.
   2537                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
   2538                     // Remove this timer from the active pool
   2539                     mTimerPool.remove(this);
   2540                 } else {
   2541                     mNesting = 1;
   2542                     mTotalTime = computeRunTimeLocked(batteryRealtime);
   2543                     mNesting = 0;
   2544                 }
   2545 
   2546                 if (DEBUG && mType < 0) {
   2547                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
   2548                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
   2549                             + " mAcquireTime=" + mAcquireTime);
   2550                 }
   2551 
   2552                 if (mAcquireTime >= 0 && mTotalTime == mAcquireTime) {
   2553                     // If there was no change in the time, then discard this
   2554                     // count.  A somewhat cheezy strategy, but hey.
   2555                     mCount--;
   2556                 }
   2557             }
   2558         }
   2559 
   2560         public void stopAllRunningLocked(long elapsedRealtimeMs) {
   2561             if (mNesting > 0) {
   2562                 mNesting = 1;
   2563                 stopRunningLocked(elapsedRealtimeMs);
   2564             }
   2565         }
   2566 
   2567         // Update the total time for all other running Timers with the same type as this Timer
   2568         // due to a change in timer count
   2569         private static long refreshTimersLocked(long batteryRealtime,
   2570                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
   2571             long selfTime = 0;
   2572             final int N = pool.size();
   2573             for (int i=N-1; i>= 0; i--) {
   2574                 final StopwatchTimer t = pool.get(i);
   2575                 long heldTime = batteryRealtime - t.mUpdateTime;
   2576                 if (heldTime > 0) {
   2577                     final long myTime = heldTime / N;
   2578                     if (t == self) {
   2579                         selfTime = myTime;
   2580                     }
   2581                     t.mTotalTime += myTime;
   2582                 }
   2583                 t.mUpdateTime = batteryRealtime;
   2584             }
   2585             return selfTime;
   2586         }
   2587 
   2588         @Override
   2589         protected long computeRunTimeLocked(long curBatteryRealtime) {
   2590             if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
   2591                 curBatteryRealtime = mUpdateTime + mTimeout;
   2592             }
   2593             return mTotalTime + (mNesting > 0
   2594                     ? (curBatteryRealtime - mUpdateTime)
   2595                             / (mTimerPool != null ? mTimerPool.size() : 1)
   2596                     : 0);
   2597         }
   2598 
   2599         @Override
   2600         protected int computeCurrentCountLocked() {
   2601             return mCount;
   2602         }
   2603 
   2604         @Override
   2605         public boolean reset(boolean detachIfReset) {
   2606             boolean canDetach = mNesting <= 0;
   2607             super.reset(canDetach && detachIfReset);
   2608             if (mNesting > 0) {
   2609                 mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
   2610             }
   2611             mAcquireTime = -1; // to ensure mCount isn't decreased to -1 if timer is stopped later.
   2612             return canDetach;
   2613         }
   2614 
   2615         @Override
   2616         public void detach() {
   2617             super.detach();
   2618             if (mTimerPool != null) {
   2619                 mTimerPool.remove(this);
   2620             }
   2621         }
   2622 
   2623         @Override
   2624         public void readSummaryFromParcelLocked(Parcel in) {
   2625             super.readSummaryFromParcelLocked(in);
   2626             mNesting = 0;
   2627         }
   2628 
   2629         /**
   2630          * Set the mark so that we can query later for the total time the timer has
   2631          * accumulated since this point. The timer can be running or not.
   2632          *
   2633          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
   2634          */
   2635         public void setMark(long elapsedRealtimeMs) {
   2636             final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
   2637             if (mNesting > 0) {
   2638                 // We are running.
   2639                 if (mTimerPool != null) {
   2640                     refreshTimersLocked(batteryRealtime, mTimerPool, this);
   2641                 } else {
   2642                     mTotalTime += batteryRealtime - mUpdateTime;
   2643                     mUpdateTime = batteryRealtime;
   2644                 }
   2645             }
   2646             mTimeBeforeMark = mTotalTime;
   2647         }
   2648     }
   2649 
   2650     /**
   2651      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
   2652      * TimeBase is effectively a subset of the other.
   2653      */
   2654     public static class DualTimer extends DurationTimer {
   2655         // This class both is a DurationTimer and also holds a second DurationTimer.
   2656         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
   2657         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
   2658         // STATS_SINCE_CHARGED).
   2659         // mSubTimer typically tracks only part of the total time, such as background time, as
   2660         // determined by a subTimeBase. It is NOT pooled.
   2661         private final DurationTimer mSubTimer;
   2662 
   2663         /**
   2664          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
   2665          * The main timer (this) is based on the given timeBase and timerPool.
   2666          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
   2667          * the main timer is.
   2668          */
   2669         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   2670                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
   2671             super(clocks, uid, type, timerPool, timeBase, in);
   2672             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase, in);
   2673         }
   2674 
   2675         /**
   2676          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
   2677          * The main timer (this) is based on the given timeBase and timerPool.
   2678          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
   2679          * the main timer is.
   2680          */
   2681         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
   2682                 TimeBase timeBase, TimeBase subTimeBase) {
   2683             super(clocks, uid, type, timerPool, timeBase);
   2684             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase);
   2685         }
   2686 
   2687         /** Get the secondary timer. */
   2688         @Override
   2689         public DurationTimer getSubTimer() {
   2690             return mSubTimer;
   2691         }
   2692 
   2693         @Override
   2694         public void startRunningLocked(long elapsedRealtimeMs) {
   2695             super.startRunningLocked(elapsedRealtimeMs);
   2696             mSubTimer.startRunningLocked(elapsedRealtimeMs);
   2697         }
   2698 
   2699         @Override
   2700         public void stopRunningLocked(long elapsedRealtimeMs) {
   2701             super.stopRunningLocked(elapsedRealtimeMs);
   2702             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
   2703         }
   2704 
   2705         @Override
   2706         public void stopAllRunningLocked(long elapsedRealtimeMs) {
   2707             super.stopAllRunningLocked(elapsedRealtimeMs);
   2708             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
   2709         }
   2710 
   2711         @Override
   2712         public boolean reset(boolean detachIfReset) {
   2713             boolean active = false;
   2714             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
   2715             active |= !mSubTimer.reset(false);
   2716             active |= !super.reset(detachIfReset);
   2717             return !active;
   2718         }
   2719 
   2720         @Override
   2721         public void detach() {
   2722             mSubTimer.detach();
   2723             super.detach();
   2724         }
   2725 
   2726         @Override
   2727         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
   2728             super.writeToParcel(out, elapsedRealtimeUs);
   2729             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
   2730         }
   2731 
   2732         @Override
   2733         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
   2734             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
   2735             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
   2736         }
   2737 
   2738         @Override
   2739         public void readSummaryFromParcelLocked(Parcel in) {
   2740             super.readSummaryFromParcelLocked(in);
   2741             mSubTimer.readSummaryFromParcelLocked(in);
   2742         }
   2743     }
   2744 
   2745 
   2746     public abstract class OverflowArrayMap<T> {
   2747         private static final String OVERFLOW_NAME = "*overflow*";
   2748 
   2749         final int mUid;
   2750         final ArrayMap<String, T> mMap = new ArrayMap<>();
   2751         T mCurOverflow;
   2752         ArrayMap<String, MutableInt> mActiveOverflow;
   2753         long mLastOverflowTime;
   2754         long mLastOverflowFinishTime;
   2755         long mLastClearTime;
   2756         long mLastCleanupTime;
   2757 
   2758         public OverflowArrayMap(int uid) {
   2759             mUid = uid;
   2760         }
   2761 
   2762         public ArrayMap<String, T> getMap() {
   2763             return mMap;
   2764         }
   2765 
   2766         public void clear() {
   2767             mLastClearTime = SystemClock.elapsedRealtime();
   2768             mMap.clear();
   2769             mCurOverflow = null;
   2770             mActiveOverflow = null;
   2771         }
   2772 
   2773         public void add(String name, T obj) {
   2774             if (name == null) {
   2775                 name = "";
   2776             }
   2777             mMap.put(name, obj);
   2778             if (OVERFLOW_NAME.equals(name)) {
   2779                 mCurOverflow = obj;
   2780             }
   2781         }
   2782 
   2783         public void cleanup() {
   2784             mLastCleanupTime = SystemClock.elapsedRealtime();
   2785             if (mActiveOverflow != null) {
   2786                 if (mActiveOverflow.size() == 0) {
   2787                     mActiveOverflow = null;
   2788                 }
   2789             }
   2790             if (mActiveOverflow == null) {
   2791                 // There is no currently active overflow, so we should no longer have
   2792                 // an overflow entry.
   2793                 if (mMap.containsKey(OVERFLOW_NAME)) {
   2794                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
   2795                             + mMap.get(OVERFLOW_NAME));
   2796                     mMap.remove(OVERFLOW_NAME);
   2797                 }
   2798                 mCurOverflow = null;
   2799             } else {
   2800                 // There is currently active overflow, so we should still have an overflow entry.
   2801                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
   2802                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
   2803                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
   2804                 }
   2805             }
   2806         }
   2807 
   2808         public T startObject(String name) {
   2809             if (name == null) {
   2810                 name = "";
   2811             }
   2812             T obj = mMap.get(name);
   2813             if (obj != null) {
   2814                 return obj;
   2815             }
   2816 
   2817             // No object exists for the given name, but do we currently have it
   2818             // running as part of the overflow?
   2819             if (mActiveOverflow != null) {
   2820                 MutableInt over = mActiveOverflow.get(name);
   2821                 if (over != null) {
   2822                     // We are already actively counting this name in the overflow object.
   2823                     obj = mCurOverflow;
   2824                     if (obj == null) {
   2825                         // Shouldn't be here, but we'll try to recover.
   2826                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
   2827                         obj = mCurOverflow = instantiateObject();
   2828                         mMap.put(OVERFLOW_NAME, obj);
   2829                     }
   2830                     over.value++;
   2831                     return obj;
   2832                 }
   2833             }
   2834 
   2835             // No object exists for given name nor in the overflow; we need to make
   2836             // a new one.
   2837             final int N = mMap.size();
   2838             if (N >= MAX_WAKELOCKS_PER_UID) {
   2839                 // Went over the limit on number of objects to track; this one goes
   2840                 // in to the overflow.
   2841                 obj = mCurOverflow;
   2842                 if (obj == null) {
   2843                     // Need to start overflow now...
   2844                     obj = mCurOverflow = instantiateObject();
   2845                     mMap.put(OVERFLOW_NAME, obj);
   2846                 }
   2847                 if (mActiveOverflow == null) {
   2848                     mActiveOverflow = new ArrayMap<>();
   2849                 }
   2850                 mActiveOverflow.put(name, new MutableInt(1));
   2851                 mLastOverflowTime = SystemClock.elapsedRealtime();
   2852                 return obj;
   2853             }
   2854 
   2855             // Normal case where we just need to make a new object.
   2856             obj = instantiateObject();
   2857             mMap.put(name, obj);
   2858             return obj;
   2859         }
   2860 
   2861         public T stopObject(String name) {
   2862             if (name == null) {
   2863                 name = "";
   2864             }
   2865             T obj = mMap.get(name);
   2866             if (obj != null) {
   2867                 return obj;
   2868             }
   2869 
   2870             // No object exists for the given name, but do we currently have it
   2871             // running as part of the overflow?
   2872             if (mActiveOverflow != null) {
   2873                 MutableInt over = mActiveOverflow.get(name);
   2874                 if (over != null) {
   2875                     // We are already actively counting this name in the overflow object.
   2876                     obj = mCurOverflow;
   2877                     if (obj != null) {
   2878                         over.value--;
   2879                         if (over.value <= 0) {
   2880                             mActiveOverflow.remove(name);
   2881                             mLastOverflowFinishTime = SystemClock.elapsedRealtime();
   2882                         }
   2883                         return obj;
   2884                     }
   2885                 }
   2886             }
   2887 
   2888             // Huh, they are stopping an active operation but we can't find one!
   2889             // That's not good.
   2890             StringBuilder sb = new StringBuilder();
   2891             sb.append("Unable to find object for ");
   2892             sb.append(name);
   2893             sb.append(" in uid ");
   2894             sb.append(mUid);
   2895             sb.append(" mapsize=");
   2896             sb.append(mMap.size());
   2897             sb.append(" activeoverflow=");
   2898             sb.append(mActiveOverflow);
   2899             sb.append(" curoverflow=");
   2900             sb.append(mCurOverflow);
   2901             long now = SystemClock.elapsedRealtime();
   2902             if (mLastOverflowTime != 0) {
   2903                 sb.append(" lastOverflowTime=");
   2904                 TimeUtils.formatDuration(mLastOverflowTime-now, sb);
   2905             }
   2906             if (mLastOverflowFinishTime != 0) {
   2907                 sb.append(" lastOverflowFinishTime=");
   2908                 TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb);
   2909             }
   2910             if (mLastClearTime != 0) {
   2911                 sb.append(" lastClearTime=");
   2912                 TimeUtils.formatDuration(mLastClearTime-now, sb);
   2913             }
   2914             if (mLastCleanupTime != 0) {
   2915                 sb.append(" lastCleanupTime=");
   2916                 TimeUtils.formatDuration(mLastCleanupTime-now, sb);
   2917             }
   2918             Slog.wtf(TAG, sb.toString());
   2919             return null;
   2920         }
   2921 
   2922         public abstract T instantiateObject();
   2923     }
   2924 
   2925     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
   2926             implements Parcelable {
   2927         private final LongSamplingCounter mIdleTimeMillis;
   2928         private final LongSamplingCounter mScanTimeMillis;
   2929         private final LongSamplingCounter mSleepTimeMillis;
   2930         private final LongSamplingCounter mRxTimeMillis;
   2931         private final LongSamplingCounter[] mTxTimeMillis;
   2932         private final LongSamplingCounter mPowerDrainMaMs;
   2933 
   2934         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
   2935             mIdleTimeMillis = new LongSamplingCounter(timeBase);
   2936             mScanTimeMillis = new LongSamplingCounter(timeBase);
   2937             mSleepTimeMillis = new LongSamplingCounter(timeBase);
   2938             mRxTimeMillis = new LongSamplingCounter(timeBase);
   2939             mTxTimeMillis = new LongSamplingCounter[numTxStates];
   2940             for (int i = 0; i < numTxStates; i++) {
   2941                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
   2942             }
   2943             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
   2944         }
   2945 
   2946         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
   2947             mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
   2948             mScanTimeMillis = new LongSamplingCounter(timeBase, in);
   2949             mSleepTimeMillis = new LongSamplingCounter(timeBase, in);
   2950             mRxTimeMillis = new LongSamplingCounter(timeBase, in);
   2951             final int recordedTxStates = in.readInt();
   2952             if (recordedTxStates != numTxStates) {
   2953                 throw new ParcelFormatException("inconsistent tx state lengths");
   2954             }
   2955 
   2956             mTxTimeMillis = new LongSamplingCounter[numTxStates];
   2957             for (int i = 0; i < numTxStates; i++) {
   2958                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
   2959             }
   2960             mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
   2961         }
   2962 
   2963         public void readSummaryFromParcel(Parcel in) {
   2964             mIdleTimeMillis.readSummaryFromParcelLocked(in);
   2965             mScanTimeMillis.readSummaryFromParcelLocked(in);
   2966             mSleepTimeMillis.readSummaryFromParcelLocked(in);
   2967             mRxTimeMillis.readSummaryFromParcelLocked(in);
   2968             final int recordedTxStates = in.readInt();
   2969             if (recordedTxStates != mTxTimeMillis.length) {
   2970                 throw new ParcelFormatException("inconsistent tx state lengths");
   2971             }
   2972             for (LongSamplingCounter counter : mTxTimeMillis) {
   2973                 counter.readSummaryFromParcelLocked(in);
   2974             }
   2975             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
   2976         }
   2977 
   2978         @Override
   2979         public int describeContents() {
   2980             return 0;
   2981         }
   2982 
   2983         public void writeSummaryToParcel(Parcel dest) {
   2984             mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
   2985             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
   2986             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
   2987             mRxTimeMillis.writeSummaryFromParcelLocked(dest);
   2988             dest.writeInt(mTxTimeMillis.length);
   2989             for (LongSamplingCounter counter : mTxTimeMillis) {
   2990                 counter.writeSummaryFromParcelLocked(dest);
   2991             }
   2992             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
   2993         }
   2994 
   2995         @Override
   2996         public void writeToParcel(Parcel dest, int flags) {
   2997             mIdleTimeMillis.writeToParcel(dest);
   2998             mScanTimeMillis.writeToParcel(dest);
   2999             mSleepTimeMillis.writeToParcel(dest);
   3000             mRxTimeMillis.writeToParcel(dest);
   3001             dest.writeInt(mTxTimeMillis.length);
   3002             for (LongSamplingCounter counter : mTxTimeMillis) {
   3003                 counter.writeToParcel(dest);
   3004             }
   3005             mPowerDrainMaMs.writeToParcel(dest);
   3006         }
   3007 
   3008         public void reset(boolean detachIfReset) {
   3009             mIdleTimeMillis.reset(detachIfReset);
   3010             mScanTimeMillis.reset(detachIfReset);
   3011             mSleepTimeMillis.reset(detachIfReset);
   3012             mRxTimeMillis.reset(detachIfReset);
   3013             for (LongSamplingCounter counter : mTxTimeMillis) {
   3014                 counter.reset(detachIfReset);
   3015             }
   3016             mPowerDrainMaMs.reset(detachIfReset);
   3017         }
   3018 
   3019         public void detach() {
   3020             mIdleTimeMillis.detach();
   3021             mScanTimeMillis.detach();
   3022             mSleepTimeMillis.detach();
   3023             mRxTimeMillis.detach();
   3024             for (LongSamplingCounter counter : mTxTimeMillis) {
   3025                 counter.detach();
   3026             }
   3027             mPowerDrainMaMs.detach();
   3028         }
   3029 
   3030         /**
   3031          * @return a LongSamplingCounter, measuring time spent in the idle state in
   3032          * milliseconds.
   3033          */
   3034         @Override
   3035         public LongSamplingCounter getIdleTimeCounter() {
   3036             return mIdleTimeMillis;
   3037         }
   3038 
   3039         /**
   3040          * @return a LongSamplingCounter, measuring time spent in the scan state in
   3041          * milliseconds.
   3042          */
   3043         @Override
   3044         public LongSamplingCounter getScanTimeCounter() {
   3045             return mScanTimeMillis;
   3046         }
   3047 
   3048         /**
   3049          * @return a LongSamplingCounter, measuring time spent in the sleep state in
   3050          * milliseconds.
   3051          */
   3052         @Override
   3053         public LongSamplingCounter getSleepTimeCounter() {
   3054             return mSleepTimeMillis;
   3055         }
   3056 
   3057         /**
   3058          * @return a LongSamplingCounter, measuring time spent in the receive state in
   3059          * milliseconds.
   3060          */
   3061         @Override
   3062         public LongSamplingCounter getRxTimeCounter() {
   3063             return mRxTimeMillis;
   3064         }
   3065 
   3066         /**
   3067          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
   3068          * milliseconds.
   3069          */
   3070         @Override
   3071         public LongSamplingCounter[] getTxTimeCounters() {
   3072             return mTxTimeMillis;
   3073         }
   3074 
   3075         /**
   3076          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
   3077          */
   3078         @Override
   3079         public LongSamplingCounter getPowerCounter() {
   3080             return mPowerDrainMaMs;
   3081         }
   3082     }
   3083 
   3084     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
   3085     public SamplingTimer getRpmTimerLocked(String name) {
   3086         SamplingTimer rpmt = mRpmStats.get(name);
   3087         if (rpmt == null) {
   3088             rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
   3089             mRpmStats.put(name, rpmt);
   3090         }
   3091         return rpmt;
   3092     }
   3093 
   3094     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
   3095     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
   3096         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
   3097         if (rpmt == null) {
   3098             rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
   3099             mScreenOffRpmStats.put(name, rpmt);
   3100         }
   3101         return rpmt;
   3102     }
   3103 
   3104     /*
   3105      * Get the wakeup reason counter, and create a new one if one
   3106      * doesn't already exist.
   3107      */
   3108     public SamplingTimer getWakeupReasonTimerLocked(String name) {
   3109         SamplingTimer timer = mWakeupReasonStats.get(name);
   3110         if (timer == null) {
   3111             timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
   3112             mWakeupReasonStats.put(name, timer);
   3113         }
   3114         return timer;
   3115     }
   3116 
   3117     /*
   3118      * Get the KernelWakelockTimer associated with name, and create a new one if one
   3119      * doesn't already exist.
   3120      */
   3121     public SamplingTimer getKernelWakelockTimerLocked(String name) {
   3122         SamplingTimer kwlt = mKernelWakelockStats.get(name);
   3123         if (kwlt == null) {
   3124             kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
   3125             mKernelWakelockStats.put(name, kwlt);
   3126         }
   3127         return kwlt;
   3128     }
   3129 
   3130     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
   3131         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
   3132         if (kmt == null) {
   3133             kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
   3134             mKernelMemoryStats.put(bucket, kmt);
   3135         }
   3136         return kmt;
   3137     }
   3138 
   3139     private int writeHistoryTag(HistoryTag tag) {
   3140         Integer idxObj = mHistoryTagPool.get(tag);
   3141         int idx;
   3142         if (idxObj != null) {
   3143             idx = idxObj;
   3144         } else {
   3145             idx = mNextHistoryTagIdx;
   3146             HistoryTag key = new HistoryTag();
   3147             key.setTo(tag);
   3148             tag.poolIdx = idx;
   3149             mHistoryTagPool.put(key, idx);
   3150             mNextHistoryTagIdx++;
   3151             mNumHistoryTagChars += key.string.length() + 1;
   3152         }
   3153         return idx;
   3154     }
   3155 
   3156     private void readHistoryTag(int index, HistoryTag tag) {
   3157         tag.string = mReadHistoryStrings[index];
   3158         tag.uid = mReadHistoryUids[index];
   3159         tag.poolIdx = index;
   3160     }
   3161 
   3162     /*
   3163         The history delta format uses flags to denote further data in subsequent ints in the parcel.
   3164 
   3165         There is always the first token, which may contain the delta time, or an indicator of
   3166         the length of the time (int or long) following this token.
   3167 
   3168         First token: always present,
   3169         31              23              15               7             0
   3170         M|L|K|J|I|H|G|FE|D|C|B|A|T|T|TT|T|T|T|T|T|T|TT|T|T|T|T|T|T|T
   3171 
   3172         T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
   3173            follows containing the time, and 0x7ffff indicates a long immediately follows with the
   3174            delta time.
   3175         A: battery level changed and an int follows with battery data.
   3176         B: state changed and an int follows with state change data.
   3177         C: state2 has changed and an int follows with state2 change data.
   3178         D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
   3179         E: event data has changed and an event struct follows.
   3180         F: battery charge in coulombs has changed and an int with the charge follows.
   3181         G: state flag denoting that the mobile radio was active.
   3182         H: state flag denoting that the wifi radio was active.
   3183         I: state flag denoting that a wifi scan occurred.
   3184         J: state flag denoting that a wifi full lock was held.
   3185         K: state flag denoting that the gps was on.
   3186         L: state flag denoting that a wakelock was held.
   3187         M: state flag denoting that the cpu was running.
   3188 
   3189         Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
   3190         with the time delta.
   3191 
   3192         Battery level int: if A in the first token is set,
   3193         31              23              15               7             0
   3194         L|L|L|L|L|L|L|TT|T|T|T|T|T|T|TT|V|V|V|V|V|V|VV|V|V|V|V|V|V|D
   3195 
   3196         D: indicates that extra history details follow.
   3197         V: the battery voltage.
   3198         T: the battery temperature.
   3199         L: the battery level (out of 100).
   3200 
   3201         State change int: if B in the first token is set,
   3202         31              23              15               7             0
   3203         S|S|S|H|H|H|P|PF|E|D|C|B| | |A | | | | | | |  | | | | | | | 
   3204 
   3205         A: wifi multicast was on.
   3206         B: battery was plugged in.
   3207         C: screen was on.
   3208         D: phone was scanning for signal.
   3209         E: audio was on.
   3210         F: a sensor was active.
   3211 
   3212         State2 change int: if C in the first token is set,
   3213         31              23              15               7             0
   3214         M|L|K|J|I|H|H|GF|E|D|C| | | |  | | | | | | |  |B|B|B|A|A|A|A
   3215 
   3216         A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
   3217         B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
   3218         C: a bluetooth scan was active.
   3219         D: the camera was active.
   3220         E: bluetooth was on.
   3221         F: a phone call was active.
   3222         G: the device was charging.
   3223         H: 2 bits indicating the device-idle (doze) state: off, light, full
   3224         I: the flashlight was on.
   3225         J: wifi was on.
   3226         K: wifi was running.
   3227         L: video was playing.
   3228         M: power save mode was on.
   3229 
   3230         Wakelock/wakereason struct: if D in the first token is set,
   3231         TODO(adamlesinski): describe wakelock/wakereason struct.
   3232 
   3233         Event struct: if E in the first token is set,
   3234         TODO(adamlesinski): describe the event struct.
   3235 
   3236         History step details struct: if D in the battery level int is set,
   3237         TODO(adamlesinski): describe the history step details struct.
   3238 
   3239         Battery charge int: if F in the first token is set, an int representing the battery charge
   3240         in coulombs follows.
   3241      */
   3242 
   3243     // Part of initial delta int that specifies the time delta.
   3244     static final int DELTA_TIME_MASK = 0x7ffff;
   3245     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
   3246     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
   3247     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
   3248     // Flag in delta int: a new battery level int follows.
   3249     static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
   3250     // Flag in delta int: a new full state and battery status int follows.
   3251     static final int DELTA_STATE_FLAG                       = 0x00100000;
   3252     // Flag in delta int: a new full state2 int follows.
   3253     static final int DELTA_STATE2_FLAG                      = 0x00200000;
   3254     // Flag in delta int: contains a wakelock or wakeReason tag.
   3255     static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
   3256     // Flag in delta int: contains an event description.
   3257     static final int DELTA_EVENT_FLAG                       = 0x00800000;
   3258     // Flag in delta int: contains the battery charge count in uAh.
   3259     static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
   3260     // These upper bits are the frequently changing state bits.
   3261     static final int DELTA_STATE_MASK                       = 0xfe000000;
   3262 
   3263     // These are the pieces of battery state that are packed in to the upper bits of
   3264     // the state int that have been packed in to the first delta int.  They must fit
   3265     // in STATE_BATTERY_MASK.
   3266     static final int STATE_BATTERY_MASK         = 0xff000000;
   3267     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
   3268     static final int STATE_BATTERY_STATUS_SHIFT = 29;
   3269     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
   3270     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
   3271     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
   3272     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
   3273 
   3274     // We use the low bit of the battery state int to indicate that we have full details
   3275     // from a battery level change.
   3276     static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
   3277 
   3278     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
   3279         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
   3280             dest.writeInt(DELTA_TIME_ABS);
   3281             cur.writeToParcel(dest, 0);
   3282             return;
   3283         }
   3284 
   3285         final long deltaTime = cur.time - last.time;
   3286         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
   3287         final int lastStateInt = buildStateInt(last);
   3288 
   3289         int deltaTimeToken;
   3290         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
   3291             deltaTimeToken = DELTA_TIME_LONG;
   3292         } else if (deltaTime >= DELTA_TIME_ABS) {
   3293             deltaTimeToken = DELTA_TIME_INT;
   3294         } else {
   3295             deltaTimeToken = (int)deltaTime;
   3296         }
   3297         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
   3298         final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
   3299                 ? BATTERY_DELTA_LEVEL_FLAG : 0;
   3300         final boolean computeStepDetails = includeStepDetails != 0
   3301                 || mLastHistoryStepDetails == null;
   3302         final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
   3303         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
   3304         if (batteryLevelIntChanged) {
   3305             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
   3306         }
   3307         final int stateInt = buildStateInt(cur);
   3308         final boolean stateIntChanged = stateInt != lastStateInt;
   3309         if (stateIntChanged) {
   3310             firstToken |= DELTA_STATE_FLAG;
   3311         }
   3312         final boolean state2IntChanged = cur.states2 != last.states2;
   3313         if (state2IntChanged) {
   3314             firstToken |= DELTA_STATE2_FLAG;
   3315         }
   3316         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
   3317             firstToken |= DELTA_WAKELOCK_FLAG;
   3318         }
   3319         if (cur.eventCode != HistoryItem.EVENT_NONE) {
   3320             firstToken |= DELTA_EVENT_FLAG;
   3321         }
   3322 
   3323         final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
   3324         if (batteryChargeChanged) {
   3325             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
   3326         }
   3327         dest.writeInt(firstToken);
   3328         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
   3329                 + " deltaTime=" + deltaTime);
   3330 
   3331         if (deltaTimeToken >= DELTA_TIME_INT) {
   3332             if (deltaTimeToken == DELTA_TIME_INT) {
   3333                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
   3334                 dest.writeInt((int)deltaTime);
   3335             } else {
   3336                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
   3337                 dest.writeLong(deltaTime);
   3338             }
   3339         }
   3340         if (batteryLevelIntChanged) {
   3341             dest.writeInt(batteryLevelInt);
   3342             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
   3343                     + Integer.toHexString(batteryLevelInt)
   3344                     + " batteryLevel=" + cur.batteryLevel
   3345                     + " batteryTemp=" + cur.batteryTemperature
   3346                     + " batteryVolt=" + (int)cur.batteryVoltage);
   3347         }
   3348         if (stateIntChanged) {
   3349             dest.writeInt(stateInt);
   3350             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
   3351                     + Integer.toHexString(stateInt)
   3352                     + " batteryStatus=" + cur.batteryStatus
   3353                     + " batteryHealth=" + cur.batteryHealth
   3354                     + " batteryPlugType=" + cur.batteryPlugType
   3355                     + " states=0x" + Integer.toHexString(cur.states));
   3356         }
   3357         if (state2IntChanged) {
   3358             dest.writeInt(cur.states2);
   3359             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
   3360                     + Integer.toHexString(cur.states2));
   3361         }
   3362         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
   3363             int wakeLockIndex;
   3364             int wakeReasonIndex;
   3365             if (cur.wakelockTag != null) {
   3366                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
   3367                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
   3368                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
   3369             } else {
   3370                 wakeLockIndex = 0xffff;
   3371             }
   3372             if (cur.wakeReasonTag != null) {
   3373                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
   3374                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
   3375                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
   3376             } else {
   3377                 wakeReasonIndex = 0xffff;
   3378             }
   3379             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
   3380         }
   3381         if (cur.eventCode != HistoryItem.EVENT_NONE) {
   3382             int index = writeHistoryTag(cur.eventTag);
   3383             int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
   3384             dest.writeInt(codeAndIndex);
   3385             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
   3386                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
   3387                     + cur.eventTag.string);
   3388         }
   3389         if (computeStepDetails) {
   3390             if (mPlatformIdleStateCallback != null) {
   3391                 mCurHistoryStepDetails.statPlatformIdleState =
   3392                         mPlatformIdleStateCallback.getPlatformLowPowerStats();
   3393                 if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
   3394                         mCurHistoryStepDetails.statPlatformIdleState);
   3395 
   3396                 mCurHistoryStepDetails.statSubsystemPowerState =
   3397                         mPlatformIdleStateCallback.getSubsystemLowPowerStats();
   3398                 if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
   3399                         mCurHistoryStepDetails.statSubsystemPowerState);
   3400 
   3401             }
   3402             computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
   3403             if (includeStepDetails != 0) {
   3404                 mCurHistoryStepDetails.writeToParcel(dest);
   3405             }
   3406             cur.stepDetails = mCurHistoryStepDetails;
   3407             mLastHistoryStepDetails = mCurHistoryStepDetails;
   3408         } else {
   3409             cur.stepDetails = null;
   3410         }
   3411         if (mLastHistoryStepLevel < cur.batteryLevel) {
   3412             mLastHistoryStepDetails = null;
   3413         }
   3414         mLastHistoryStepLevel = cur.batteryLevel;
   3415 
   3416         if (batteryChargeChanged) {
   3417             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
   3418             dest.writeInt(cur.batteryChargeUAh);
   3419         }
   3420     }
   3421 
   3422     private int buildBatteryLevelInt(HistoryItem h) {
   3423         return ((((int)h.batteryLevel)<<25)&0xfe000000)
   3424                 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
   3425                 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
   3426     }
   3427 
   3428     private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
   3429         out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
   3430         out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
   3431         out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
   3432     }
   3433 
   3434     private int buildStateInt(HistoryItem h) {
   3435         int plugType = 0;
   3436         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
   3437             plugType = 1;
   3438         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
   3439             plugType = 2;
   3440         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
   3441             plugType = 3;
   3442         }
   3443         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
   3444                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
   3445                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
   3446                 | (h.states&(~STATE_BATTERY_MASK));
   3447     }
   3448 
   3449     private void computeHistoryStepDetails(final HistoryStepDetails out,
   3450             final HistoryStepDetails last) {
   3451         final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
   3452 
   3453         // Perform a CPU update right after we do this collection, so we have started
   3454         // collecting good data for the next step.
   3455         requestImmediateCpuUpdate();
   3456 
   3457         if (last == null) {
   3458             // We are not generating a delta, so all we need to do is reset the stats
   3459             // we will later be doing a delta from.
   3460             final int NU = mUidStats.size();
   3461             for (int i=0; i<NU; i++) {
   3462                 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   3463                 uid.mLastStepUserTime = uid.mCurStepUserTime;
   3464                 uid.mLastStepSystemTime = uid.mCurStepSystemTime;
   3465             }
   3466             mLastStepCpuUserTime = mCurStepCpuUserTime;
   3467             mLastStepCpuSystemTime = mCurStepCpuSystemTime;
   3468             mLastStepStatUserTime = mCurStepStatUserTime;
   3469             mLastStepStatSystemTime = mCurStepStatSystemTime;
   3470             mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
   3471             mLastStepStatIrqTime = mCurStepStatIrqTime;
   3472             mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
   3473             mLastStepStatIdleTime = mCurStepStatIdleTime;
   3474             tmp.clear();
   3475             return;
   3476         }
   3477         if (DEBUG) {
   3478             Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
   3479                     + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
   3480                     + " irq=" + mLastStepStatIrqTime + " sirq="
   3481                     + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
   3482             Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
   3483                     + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
   3484                     + " irq=" + mCurStepStatIrqTime + " sirq="
   3485                     + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
   3486         }
   3487         out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
   3488         out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
   3489         out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
   3490         out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
   3491         out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
   3492         out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
   3493         out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
   3494         out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
   3495         out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
   3496         out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
   3497         out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
   3498         final int NU = mUidStats.size();
   3499         for (int i=0; i<NU; i++) {
   3500             final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   3501             final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
   3502             final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
   3503             final int totalTime = totalUTime + totalSTime;
   3504             uid.mLastStepUserTime = uid.mCurStepUserTime;
   3505             uid.mLastStepSystemTime = uid.mCurStepSystemTime;
   3506             if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
   3507                 continue;
   3508             }
   3509             if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
   3510                 out.appCpuUid3 = uid.mUid;
   3511                 out.appCpuUTime3 = totalUTime;
   3512                 out.appCpuSTime3 = totalSTime;
   3513             } else {
   3514                 out.appCpuUid3 = out.appCpuUid2;
   3515                 out.appCpuUTime3 = out.appCpuUTime2;
   3516                 out.appCpuSTime3 = out.appCpuSTime2;
   3517                 if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
   3518                     out.appCpuUid2 = uid.mUid;
   3519                     out.appCpuUTime2 = totalUTime;
   3520                     out.appCpuSTime2 = totalSTime;
   3521                 } else {
   3522                     out.appCpuUid2 = out.appCpuUid1;
   3523                     out.appCpuUTime2 = out.appCpuUTime1;
   3524                     out.appCpuSTime2 = out.appCpuSTime1;
   3525                     out.appCpuUid1 = uid.mUid;
   3526                     out.appCpuUTime1 = totalUTime;
   3527                     out.appCpuSTime1 = totalSTime;
   3528                 }
   3529             }
   3530         }
   3531         mLastStepCpuUserTime = mCurStepCpuUserTime;
   3532         mLastStepCpuSystemTime = mCurStepCpuSystemTime;
   3533         mLastStepStatUserTime = mCurStepStatUserTime;
   3534         mLastStepStatSystemTime = mCurStepStatSystemTime;
   3535         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
   3536         mLastStepStatIrqTime = mCurStepStatIrqTime;
   3537         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
   3538         mLastStepStatIdleTime = mCurStepStatIdleTime;
   3539     }
   3540 
   3541     public void readHistoryDelta(Parcel src, HistoryItem cur) {
   3542         int firstToken = src.readInt();
   3543         int deltaTimeToken = firstToken&DELTA_TIME_MASK;
   3544         cur.cmd = HistoryItem.CMD_UPDATE;
   3545         cur.numReadInts = 1;
   3546         if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
   3547                 + " deltaTimeToken=" + deltaTimeToken);
   3548 
   3549         if (deltaTimeToken < DELTA_TIME_ABS) {
   3550             cur.time += deltaTimeToken;
   3551         } else if (deltaTimeToken == DELTA_TIME_ABS) {
   3552             cur.time = src.readLong();
   3553             cur.numReadInts += 2;
   3554             if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
   3555             cur.readFromParcel(src);
   3556             return;
   3557         } else if (deltaTimeToken == DELTA_TIME_INT) {
   3558             int delta = src.readInt();
   3559             cur.time += delta;
   3560             cur.numReadInts += 1;
   3561             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
   3562         } else {
   3563             long delta = src.readLong();
   3564             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
   3565             cur.time += delta;
   3566             cur.numReadInts += 2;
   3567         }
   3568 
   3569         final int batteryLevelInt;
   3570         if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
   3571             batteryLevelInt = src.readInt();
   3572             readBatteryLevelInt(batteryLevelInt, cur);
   3573             cur.numReadInts += 1;
   3574             if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
   3575                     + Integer.toHexString(batteryLevelInt)
   3576                     + " batteryLevel=" + cur.batteryLevel
   3577                     + " batteryTemp=" + cur.batteryTemperature
   3578                     + " batteryVolt=" + (int)cur.batteryVoltage);
   3579         } else {
   3580             batteryLevelInt = 0;
   3581         }
   3582 
   3583         if ((firstToken&DELTA_STATE_FLAG) != 0) {
   3584             int stateInt = src.readInt();
   3585             cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
   3586             cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
   3587                     & STATE_BATTERY_STATUS_MASK);
   3588             cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
   3589                     & STATE_BATTERY_HEALTH_MASK);
   3590             cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
   3591                     & STATE_BATTERY_PLUG_MASK);
   3592             switch (cur.batteryPlugType) {
   3593                 case 1:
   3594                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
   3595                     break;
   3596                 case 2:
   3597                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
   3598                     break;
   3599                 case 3:
   3600                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
   3601                     break;
   3602             }
   3603             cur.numReadInts += 1;
   3604             if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
   3605                     + Integer.toHexString(stateInt)
   3606                     + " batteryStatus=" + cur.batteryStatus
   3607                     + " batteryHealth=" + cur.batteryHealth
   3608                     + " batteryPlugType=" + cur.batteryPlugType
   3609                     + " states=0x" + Integer.toHexString(cur.states));
   3610         } else {
   3611             cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
   3612         }
   3613 
   3614         if ((firstToken&DELTA_STATE2_FLAG) != 0) {
   3615             cur.states2 = src.readInt();
   3616             if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
   3617                     + Integer.toHexString(cur.states2));
   3618         }
   3619 
   3620         if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
   3621             int indexes = src.readInt();
   3622             int wakeLockIndex = indexes&0xffff;
   3623             int wakeReasonIndex = (indexes>>16)&0xffff;
   3624             if (wakeLockIndex != 0xffff) {
   3625                 cur.wakelockTag = cur.localWakelockTag;
   3626                 readHistoryTag(wakeLockIndex, cur.wakelockTag);
   3627                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
   3628                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
   3629             } else {
   3630                 cur.wakelockTag = null;
   3631             }
   3632             if (wakeReasonIndex != 0xffff) {
   3633                 cur.wakeReasonTag = cur.localWakeReasonTag;
   3634                 readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
   3635                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
   3636                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
   3637             } else {
   3638                 cur.wakeReasonTag = null;
   3639             }
   3640             cur.numReadInts += 1;
   3641         } else {
   3642             cur.wakelockTag = null;
   3643             cur.wakeReasonTag = null;
   3644         }
   3645 
   3646         if ((firstToken&DELTA_EVENT_FLAG) != 0) {
   3647             cur.eventTag = cur.localEventTag;
   3648             final int codeAndIndex = src.readInt();
   3649             cur.eventCode = (codeAndIndex&0xffff);
   3650             final int index = ((codeAndIndex>>16)&0xffff);
   3651             readHistoryTag(index, cur.eventTag);
   3652             cur.numReadInts += 1;
   3653             if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
   3654                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
   3655                     + cur.eventTag.string);
   3656         } else {
   3657             cur.eventCode = HistoryItem.EVENT_NONE;
   3658         }
   3659 
   3660         if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
   3661             cur.stepDetails = mReadHistoryStepDetails;
   3662             cur.stepDetails.readFromParcel(src);
   3663         } else {
   3664             cur.stepDetails = null;
   3665         }
   3666 
   3667         if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
   3668             cur.batteryChargeUAh = src.readInt();
   3669         }
   3670     }
   3671 
   3672     @Override
   3673     public void commitCurrentHistoryBatchLocked() {
   3674         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
   3675     }
   3676 
   3677     void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) {
   3678         if (!mHaveBatteryLevel || !mRecordingHistory) {
   3679             return;
   3680         }
   3681 
   3682         final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
   3683         final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
   3684         final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
   3685         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
   3686         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
   3687         if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
   3688                 + Integer.toHexString(diffStates) + " lastDiff="
   3689                 + Integer.toHexString(lastDiffStates) + " diff2="
   3690                 + Integer.toHexString(diffStates2) + " lastDiff2="
   3691                 + Integer.toHexString(lastDiffStates2));
   3692         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
   3693                 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
   3694                 && (diffStates2&lastDiffStates2) == 0
   3695                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
   3696                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
   3697                 && mHistoryLastWritten.stepDetails == null
   3698                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
   3699                         || cur.eventCode == HistoryItem.EVENT_NONE)
   3700                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
   3701                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
   3702                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
   3703                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
   3704                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
   3705                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
   3706             // We can merge this new change in with the last one.  Merging is
   3707             // allowed as long as only the states have changed, and within those states
   3708             // as long as no bit has changed both between now and the last entry, as
   3709             // well as the last entry and the one before it (so we capture any toggles).
   3710             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
   3711             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
   3712             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
   3713             mHistoryBufferLastPos = -1;
   3714             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
   3715             // If the last written history had a wakelock tag, we need to retain it.
   3716             // Note that the condition above made sure that we aren't in a case where
   3717             // both it and the current history item have a wakelock tag.
   3718             if (mHistoryLastWritten.wakelockTag != null) {
   3719                 cur.wakelockTag = cur.localWakelockTag;
   3720                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
   3721             }
   3722             // If the last written history had a wake reason tag, we need to retain it.
   3723             // Note that the condition above made sure that we aren't in a case where
   3724             // both it and the current history item have a wakelock tag.
   3725             if (mHistoryLastWritten.wakeReasonTag != null) {
   3726                 cur.wakeReasonTag = cur.localWakeReasonTag;
   3727                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
   3728             }
   3729             // If the last written history had an event, we need to retain it.
   3730             // Note that the condition above made sure that we aren't in a case where
   3731             // both it and the current history item have an event.
   3732             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
   3733                 cur.eventCode = mHistoryLastWritten.eventCode;
   3734                 cur.eventTag = cur.localEventTag;
   3735                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
   3736             }
   3737             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
   3738         }
   3739 
   3740         boolean recordResetDueToOverflow = false;
   3741         final int dataSize = mHistoryBuffer.dataSize();
   3742         if (dataSize >= MAX_MAX_HISTORY_BUFFER*3) {
   3743             // Clients can't deal with history buffers this large. This only
   3744             // really happens when the device is on charger and interacted with
   3745             // for long periods of time, like in retail mode. Since the device is
   3746             // most likely charged, when unplugged, stats would have reset anyways.
   3747             // Reset the stats and mark that we overflowed.
   3748             // b/32540341
   3749             resetAllStatsLocked();
   3750 
   3751             // Mark that we want to set *OVERFLOW* event and the RESET:START
   3752             // events.
   3753             recordResetDueToOverflow = true;
   3754 
   3755         } else if (dataSize >= MAX_HISTORY_BUFFER) {
   3756             if (!mHistoryOverflow) {
   3757                 mHistoryOverflow = true;
   3758                 addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
   3759                 addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
   3760                 return;
   3761             }
   3762 
   3763             // After overflow, we allow various bit-wise states to settle to 0.
   3764             boolean writeAnyway = false;
   3765             final int curStates = cur.states & HistoryItem.SETTLE_TO_ZERO_STATES
   3766                     & mActiveHistoryStates;
   3767             if (mHistoryLastWritten.states != curStates) {
   3768                 // mActiveHistoryStates keeps track of which bits in .states are now being
   3769                 // forced to 0.
   3770                 int old = mActiveHistoryStates;
   3771                 mActiveHistoryStates &= curStates | ~HistoryItem.SETTLE_TO_ZERO_STATES;
   3772                 writeAnyway |= old != mActiveHistoryStates;
   3773             }
   3774             final int curStates2 = cur.states2 & HistoryItem.SETTLE_TO_ZERO_STATES2
   3775                     & mActiveHistoryStates2;
   3776             if (mHistoryLastWritten.states2 != curStates2) {
   3777                 // mActiveHistoryStates2 keeps track of which bits in .states2 are now being
   3778                 // forced to 0.
   3779                 int old = mActiveHistoryStates2;
   3780                 mActiveHistoryStates2 &= curStates2 | ~HistoryItem.SETTLE_TO_ZERO_STATES2;
   3781                 writeAnyway |= old != mActiveHistoryStates2;
   3782             }
   3783 
   3784             // Once we've reached the maximum number of items, we only
   3785             // record changes to the battery level and the most interesting states.
   3786             // Once we've reached the maximum maximum number of items, we only
   3787             // record changes to the battery level.
   3788             if (!writeAnyway && mHistoryLastWritten.batteryLevel == cur.batteryLevel &&
   3789                     (dataSize >= MAX_MAX_HISTORY_BUFFER
   3790                             || ((mHistoryLastWritten.states^cur.states)
   3791                                     & HistoryItem.MOST_INTERESTING_STATES) == 0
   3792                             || ((mHistoryLastWritten.states2^cur.states2)
   3793                                     & HistoryItem.MOST_INTERESTING_STATES2) == 0)) {
   3794                 return;
   3795             }
   3796 
   3797             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
   3798             return;
   3799         }
   3800 
   3801         if (dataSize == 0 || recordResetDueToOverflow) {
   3802             // The history is currently empty; we need it to start with a time stamp.
   3803             cur.currentTime = System.currentTimeMillis();
   3804             if (recordResetDueToOverflow) {
   3805                 addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
   3806             }
   3807             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
   3808         }
   3809         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
   3810     }
   3811 
   3812     private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
   3813         if (mIteratingHistory) {
   3814             throw new IllegalStateException("Can't do this while iterating history!");
   3815         }
   3816         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
   3817         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
   3818         mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
   3819         mHistoryLastWritten.states &= mActiveHistoryStates;
   3820         mHistoryLastWritten.states2 &= mActiveHistoryStates2;
   3821         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
   3822         mLastHistoryElapsedRealtime = elapsedRealtimeMs;
   3823         cur.wakelockTag = null;
   3824         cur.wakeReasonTag = null;
   3825         cur.eventCode = HistoryItem.EVENT_NONE;
   3826         cur.eventTag = null;
   3827         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
   3828                 + " now " + mHistoryBuffer.dataPosition()
   3829                 + " size is now " + mHistoryBuffer.dataSize());
   3830     }
   3831 
   3832     int mChangedStates = 0;
   3833     int mChangedStates2 = 0;
   3834 
   3835     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
   3836         if (mTrackRunningHistoryElapsedRealtime != 0) {
   3837             final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
   3838             final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
   3839             if (diffUptime < (diffElapsed-20)) {
   3840                 final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
   3841                 mHistoryAddTmp.setTo(mHistoryLastWritten);
   3842                 mHistoryAddTmp.wakelockTag = null;
   3843                 mHistoryAddTmp.wakeReasonTag = null;
   3844                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
   3845                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
   3846                 addHistoryRecordInnerLocked(wakeElapsedTime, mHistoryAddTmp);
   3847             }
   3848         }
   3849         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
   3850         mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
   3851         mTrackRunningHistoryUptime = uptimeMs;
   3852         addHistoryRecordInnerLocked(elapsedRealtimeMs, mHistoryCur);
   3853     }
   3854 
   3855     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur) {
   3856         addHistoryBufferLocked(elapsedRealtimeMs, cur);
   3857 
   3858         if (!USE_OLD_HISTORY) {
   3859             return;
   3860         }
   3861 
   3862         if (!mHaveBatteryLevel || !mRecordingHistory) {
   3863             return;
   3864         }
   3865 
   3866         // If the current time is basically the same as the last time,
   3867         // and no states have since the last recorded entry changed and
   3868         // are now resetting back to their original value, then just collapse
   3869         // into one record.
   3870         if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
   3871                 && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
   3872                 && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
   3873                 && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
   3874             // If the current is the same as the one before, then we no
   3875             // longer need the entry.
   3876             if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
   3877                     && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
   3878                     && mHistoryLastEnd.sameNonEvent(cur)) {
   3879                 mHistoryLastEnd.next = null;
   3880                 mHistoryEnd.next = mHistoryCache;
   3881                 mHistoryCache = mHistoryEnd;
   3882                 mHistoryEnd = mHistoryLastEnd;
   3883                 mHistoryLastEnd = null;
   3884             } else {
   3885                 mChangedStates |= mHistoryEnd.states^(cur.states&mActiveHistoryStates);
   3886                 mChangedStates2 |= mHistoryEnd.states^(cur.states2&mActiveHistoryStates2);
   3887                 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
   3888             }
   3889             return;
   3890         }
   3891 
   3892         mChangedStates = 0;
   3893         mChangedStates2 = 0;
   3894 
   3895         if (mNumHistoryItems == MAX_HISTORY_ITEMS
   3896                 || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
   3897             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
   3898         }
   3899 
   3900         if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
   3901             // Once we've reached the maximum number of items, we only
   3902             // record changes to the battery level and the most interesting states.
   3903             // Once we've reached the maximum maximum number of items, we only
   3904             // record changes to the battery level.
   3905             if (mHistoryEnd != null && mHistoryEnd.batteryLevel
   3906                     == cur.batteryLevel &&
   3907                     (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
   3908                             || ((mHistoryEnd.states^(cur.states&mActiveHistoryStates))
   3909                                     & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
   3910                 return;
   3911             }
   3912         }
   3913 
   3914         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
   3915     }
   3916 
   3917     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
   3918             String name, int uid) {
   3919         mHistoryCur.eventCode = code;
   3920         mHistoryCur.eventTag = mHistoryCur.localEventTag;
   3921         mHistoryCur.eventTag.string = name;
   3922         mHistoryCur.eventTag.uid = uid;
   3923         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
   3924     }
   3925 
   3926     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
   3927         HistoryItem rec = mHistoryCache;
   3928         if (rec != null) {
   3929             mHistoryCache = rec.next;
   3930         } else {
   3931             rec = new HistoryItem();
   3932         }
   3933         rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
   3934 
   3935         addHistoryRecordLocked(rec);
   3936     }
   3937 
   3938     void addHistoryRecordLocked(HistoryItem rec) {
   3939         mNumHistoryItems++;
   3940         rec.next = null;
   3941         mHistoryLastEnd = mHistoryEnd;
   3942         if (mHistoryEnd != null) {
   3943             mHistoryEnd.next = rec;
   3944             mHistoryEnd = rec;
   3945         } else {
   3946             mHistory = mHistoryEnd = rec;
   3947         }
   3948     }
   3949 
   3950     void clearHistoryLocked() {
   3951         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
   3952         if (USE_OLD_HISTORY) {
   3953             if (mHistory != null) {
   3954                 mHistoryEnd.next = mHistoryCache;
   3955                 mHistoryCache = mHistory;
   3956                 mHistory = mHistoryLastEnd = mHistoryEnd = null;
   3957             }
   3958             mNumHistoryItems = 0;
   3959         }
   3960 
   3961         mHistoryBaseTime = 0;
   3962         mLastHistoryElapsedRealtime = 0;
   3963         mTrackRunningHistoryElapsedRealtime = 0;
   3964         mTrackRunningHistoryUptime = 0;
   3965 
   3966         mHistoryBuffer.setDataSize(0);
   3967         mHistoryBuffer.setDataPosition(0);
   3968         mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER / 2);
   3969         mHistoryLastLastWritten.clear();
   3970         mHistoryLastWritten.clear();
   3971         mHistoryTagPool.clear();
   3972         mNextHistoryTagIdx = 0;
   3973         mNumHistoryTagChars = 0;
   3974         mHistoryBufferLastPos = -1;
   3975         mHistoryOverflow = false;
   3976         mActiveHistoryStates = 0xffffffff;
   3977         mActiveHistoryStates2 = 0xffffffff;
   3978     }
   3979 
   3980     @GuardedBy("this")
   3981     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
   3982             long realtime) {
   3983         final boolean screenOff = !isScreenOn(screenState);
   3984         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
   3985         final boolean updateOnBatteryScreenOffTimeBase =
   3986                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
   3987 
   3988         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
   3989             if (updateOnBatteryScreenOffTimeBase) {
   3990                 updateKernelWakelocksLocked();
   3991                 updateBatteryPropertiesLocked();
   3992             }
   3993             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
   3994             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
   3995             // improved, remove the surrounding if{}.
   3996             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
   3997                 updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes.
   3998             }
   3999             if (DEBUG_ENERGY_CPU) {
   4000                 Slog.d(TAG, "Updating cpu time because screen is now "
   4001                         + Display.stateToString(screenState)
   4002                         + " and battery is " + (unplugged ? "on" : "off"));
   4003             }
   4004 
   4005             mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
   4006             if (updateOnBatteryTimeBase) {
   4007                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
   4008                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime);
   4009                 }
   4010             }
   4011             if (updateOnBatteryScreenOffTimeBase) {
   4012                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, uptime, realtime);
   4013                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
   4014                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime);
   4015                 }
   4016             }
   4017         }
   4018     }
   4019 
   4020     private void updateBatteryPropertiesLocked() {
   4021         try {
   4022             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
   4023                     ServiceManager.getService("batteryproperties"));
   4024             registrar.scheduleUpdate();
   4025         } catch (RemoteException e) {
   4026             // Ignore.
   4027         }
   4028     }
   4029 
   4030     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
   4031         mIsolatedUids.put(isolatedUid, appUid);
   4032         StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, appUid, isolatedUid,
   4033                 StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
   4034         final Uid u = getUidStatsLocked(appUid);
   4035         u.addIsolatedUid(isolatedUid);
   4036     }
   4037 
   4038     /**
   4039      * Schedules a read of the latest cpu times before removing the isolated UID.
   4040      * @see #removeIsolatedUidLocked(int)
   4041      */
   4042     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
   4043         int curUid = mIsolatedUids.get(isolatedUid, -1);
   4044         if (curUid == appUid) {
   4045             if (mExternalSync != null) {
   4046                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
   4047             }
   4048         }
   4049     }
   4050 
   4051     /**
   4052      * This should only be called after the cpu times have been read.
   4053      * @see #scheduleRemoveIsolatedUidLocked(int, int)
   4054      */
   4055     @GuardedBy("this")
   4056     public void removeIsolatedUidLocked(int isolatedUid) {
   4057         StatsLog.write(
   4058                 StatsLog.ISOLATED_UID_CHANGED, mIsolatedUids.get(isolatedUid, -1),
   4059                 isolatedUid, StatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED);
   4060         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
   4061         if (idx >= 0) {
   4062             final int ownerUid = mIsolatedUids.valueAt(idx);
   4063             final Uid u = getUidStatsLocked(ownerUid);
   4064             u.removeIsolatedUid(isolatedUid);
   4065             mIsolatedUids.removeAt(idx);
   4066         }
   4067         mPendingRemovedUids.add(new UidToRemove(isolatedUid, mClocks.elapsedRealtime()));
   4068     }
   4069 
   4070     public int mapUid(int uid) {
   4071         int isolated = mIsolatedUids.get(uid, -1);
   4072         return isolated > 0 ? isolated : uid;
   4073     }
   4074 
   4075     public void noteEventLocked(int code, String name, int uid) {
   4076         uid = mapUid(uid);
   4077         if (!mActiveEvents.updateState(code, name, uid, 0)) {
   4078             return;
   4079         }
   4080         final long elapsedRealtime = mClocks.elapsedRealtime();
   4081         final long uptime = mClocks.uptimeMillis();
   4082         addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
   4083     }
   4084 
   4085     boolean ensureStartClockTime(final long currentTime) {
   4086         final long ABOUT_ONE_YEAR = 365*24*60*60*1000L;
   4087         if ((currentTime > ABOUT_ONE_YEAR && mStartClockTime < (currentTime-ABOUT_ONE_YEAR))
   4088                 || (mStartClockTime > currentTime)) {
   4089             // If the start clock time has changed by more than a year, then presumably
   4090             // the previous time was completely bogus.  So we are going to figure out a
   4091             // new time based on how much time has elapsed since we started counting.
   4092             mStartClockTime = currentTime - (mClocks.elapsedRealtime()-(mRealtimeStart/1000));
   4093             return true;
   4094         }
   4095         return false;
   4096     }
   4097 
   4098     public void noteCurrentTimeChangedLocked() {
   4099         final long currentTime = System.currentTimeMillis();
   4100         final long elapsedRealtime = mClocks.elapsedRealtime();
   4101         final long uptime = mClocks.uptimeMillis();
   4102         recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
   4103         ensureStartClockTime(currentTime);
   4104     }
   4105 
   4106     public void noteProcessStartLocked(String name, int uid) {
   4107         uid = mapUid(uid);
   4108         if (isOnBattery()) {
   4109             Uid u = getUidStatsLocked(uid);
   4110             u.getProcessStatsLocked(name).incStartsLocked();
   4111         }
   4112         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
   4113             return;
   4114         }
   4115         if (!mRecordAllHistory) {
   4116             return;
   4117         }
   4118         final long elapsedRealtime = mClocks.elapsedRealtime();
   4119         final long uptime = mClocks.uptimeMillis();
   4120         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
   4121     }
   4122 
   4123     public void noteProcessCrashLocked(String name, int uid) {
   4124         uid = mapUid(uid);
   4125         if (isOnBattery()) {
   4126             Uid u = getUidStatsLocked(uid);
   4127             u.getProcessStatsLocked(name).incNumCrashesLocked();
   4128         }
   4129     }
   4130 
   4131     public void noteProcessAnrLocked(String name, int uid) {
   4132         uid = mapUid(uid);
   4133         if (isOnBattery()) {
   4134             Uid u = getUidStatsLocked(uid);
   4135             u.getProcessStatsLocked(name).incNumAnrsLocked();
   4136         }
   4137     }
   4138 
   4139     public void noteUidProcessStateLocked(int uid, int state) {
   4140         int parentUid = mapUid(uid);
   4141         if (uid != parentUid) {
   4142             // Isolated UIDs process state is already rolled up into parent, so no need to track
   4143             // Otherwise the parent's process state will get downgraded incorrectly
   4144             return;
   4145         }
   4146         getUidStatsLocked(uid).updateUidProcessStateLocked(state);
   4147     }
   4148 
   4149     public void noteProcessFinishLocked(String name, int uid) {
   4150         uid = mapUid(uid);
   4151         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
   4152             return;
   4153         }
   4154         if (!mRecordAllHistory) {
   4155             return;
   4156         }
   4157         final long elapsedRealtime = mClocks.elapsedRealtime();
   4158         final long uptime = mClocks.uptimeMillis();
   4159         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
   4160     }
   4161 
   4162     public void noteSyncStartLocked(String name, int uid) {
   4163         uid = mapUid(uid);
   4164         final long elapsedRealtime = mClocks.elapsedRealtime();
   4165         final long uptime = mClocks.uptimeMillis();
   4166         getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
   4167         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
   4168             return;
   4169         }
   4170         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
   4171     }
   4172 
   4173     public void noteSyncFinishLocked(String name, int uid) {
   4174         uid = mapUid(uid);
   4175         final long elapsedRealtime = mClocks.elapsedRealtime();
   4176         final long uptime = mClocks.uptimeMillis();
   4177         getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
   4178         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
   4179             return;
   4180         }
   4181         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
   4182     }
   4183 
   4184     public void noteJobStartLocked(String name, int uid) {
   4185         uid = mapUid(uid);
   4186         final long elapsedRealtime = mClocks.elapsedRealtime();
   4187         final long uptime = mClocks.uptimeMillis();
   4188         getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
   4189         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
   4190             return;
   4191         }
   4192         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
   4193     }
   4194 
   4195     public void noteJobFinishLocked(String name, int uid, int stopReason) {
   4196         uid = mapUid(uid);
   4197         final long elapsedRealtime = mClocks.elapsedRealtime();
   4198         final long uptime = mClocks.uptimeMillis();
   4199         getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason);
   4200         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
   4201             return;
   4202         }
   4203         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
   4204     }
   4205 
   4206     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
   4207         uid = mapUid(uid);
   4208         getUidStatsLocked(uid).noteJobsDeferredLocked(numDeferred, sinceLast);
   4209     }
   4210 
   4211     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
   4212         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid);
   4213     }
   4214 
   4215     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
   4216         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid);
   4217     }
   4218 
   4219     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
   4220             int uid) {
   4221         if (!mRecordAllHistory) {
   4222             return;
   4223         }
   4224 
   4225         final long elapsedRealtime = mClocks.elapsedRealtime();
   4226         final long uptime = mClocks.uptimeMillis();
   4227 
   4228         if (workSource != null) {
   4229             for (int i = 0; i < workSource.size(); ++i) {
   4230                 uid = mapUid(workSource.get(i));
   4231                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
   4232                     addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
   4233                 }
   4234             }
   4235 
   4236             List<WorkChain> workChains = workSource.getWorkChains();
   4237             if (workChains != null) {
   4238                 for (int i = 0; i < workChains.size(); ++i) {
   4239                     uid = mapUid(workChains.get(i).getAttributionUid());
   4240                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
   4241                         addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
   4242                     }
   4243                 }
   4244             }
   4245         } else {
   4246             uid = mapUid(uid);
   4247 
   4248             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
   4249                 addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
   4250             }
   4251         }
   4252     }
   4253 
   4254     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
   4255             String tag) {
   4256         if (workSource != null) {
   4257             for (int i = 0; i < workSource.size(); ++i) {
   4258                 uid = workSource.get(i);
   4259                 final String workSourceName = workSource.getName(i);
   4260 
   4261                 if (isOnBattery()) {
   4262                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
   4263                             workSourceName != null ? workSourceName : packageName);
   4264                     pkg.noteWakeupAlarmLocked(tag);
   4265                 }
   4266                 StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, workSource.get(i),
   4267                         workSource.getName(i), tag);
   4268             }
   4269 
   4270             ArrayList<WorkChain> workChains = workSource.getWorkChains();
   4271             if (workChains != null) {
   4272                 for (int i = 0; i < workChains.size(); ++i) {
   4273                     final WorkChain wc = workChains.get(i);
   4274                     uid = wc.getAttributionUid();
   4275 
   4276                     if (isOnBattery()) {
   4277                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
   4278                         pkg.noteWakeupAlarmLocked(tag);
   4279                     }
   4280                     StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, wc.getUids(), wc.getTags(), tag);
   4281                 }
   4282             }
   4283         } else {
   4284             if (isOnBattery()) {
   4285                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
   4286                 pkg.noteWakeupAlarmLocked(tag);
   4287             }
   4288             StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, uid, null, tag);
   4289         }
   4290     }
   4291 
   4292     private void requestWakelockCpuUpdate() {
   4293         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
   4294     }
   4295 
   4296     private void requestImmediateCpuUpdate() {
   4297         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
   4298     }
   4299 
   4300     public void setRecordAllHistoryLocked(boolean enabled) {
   4301         mRecordAllHistory = enabled;
   4302         if (!enabled) {
   4303             // Clear out any existing state.
   4304             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
   4305             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
   4306             // Record the currently running processes as stopping, now that we are no
   4307             // longer tracking them.
   4308             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
   4309                     HistoryItem.EVENT_PROC);
   4310             if (active != null) {
   4311                 long mSecRealtime = mClocks.elapsedRealtime();
   4312                 final long mSecUptime = mClocks.uptimeMillis();
   4313                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
   4314                     SparseIntArray uids = ent.getValue();
   4315                     for (int j=0; j<uids.size(); j++) {
   4316                         addHistoryEventLocked(mSecRealtime, mSecUptime,
   4317                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
   4318                     }
   4319                 }
   4320             }
   4321         } else {
   4322             // Record the currently running processes as starting, now that we are tracking them.
   4323             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
   4324                     HistoryItem.EVENT_PROC);
   4325             if (active != null) {
   4326                 long mSecRealtime = mClocks.elapsedRealtime();
   4327                 final long mSecUptime = mClocks.uptimeMillis();
   4328                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
   4329                     SparseIntArray uids = ent.getValue();
   4330                     for (int j=0; j<uids.size(); j++) {
   4331                         addHistoryEventLocked(mSecRealtime, mSecUptime,
   4332                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
   4333                     }
   4334                 }
   4335             }
   4336         }
   4337     }
   4338 
   4339     public void setNoAutoReset(boolean enabled) {
   4340         mNoAutoReset = enabled;
   4341     }
   4342 
   4343     public void setPretendScreenOff(boolean pretendScreenOff) {
   4344         if (mPretendScreenOff != pretendScreenOff) {
   4345             mPretendScreenOff = pretendScreenOff;
   4346             noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON);
   4347         }
   4348     }
   4349 
   4350     private String mInitialAcquireWakeName;
   4351     private int mInitialAcquireWakeUid = -1;
   4352 
   4353     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
   4354         int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) {
   4355         uid = mapUid(uid);
   4356         if (type == WAKE_TYPE_PARTIAL) {
   4357             // Only care about partial wake locks, since full wake locks
   4358             // will be canceled when the user puts the screen to sleep.
   4359             aggregateLastWakeupUptimeLocked(uptime);
   4360             if (historyName == null) {
   4361                 historyName = name;
   4362             }
   4363             if (mRecordAllHistory) {
   4364                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
   4365                         uid, 0)) {
   4366                     addHistoryEventLocked(elapsedRealtime, uptime,
   4367                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
   4368                 }
   4369             }
   4370             if (mWakeLockNesting == 0) {
   4371                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
   4372                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
   4373                         + Integer.toHexString(mHistoryCur.states));
   4374                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
   4375                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
   4376                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
   4377                 mWakeLockImportant = !unimportantForLogging;
   4378                 addHistoryRecordLocked(elapsedRealtime, uptime);
   4379             } else if (!mWakeLockImportant && !unimportantForLogging
   4380                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
   4381                 if (mHistoryLastWritten.wakelockTag != null) {
   4382                     // We'll try to update the last tag.
   4383                     mHistoryLastWritten.wakelockTag = null;
   4384                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
   4385                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
   4386                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
   4387                     addHistoryRecordLocked(elapsedRealtime, uptime);
   4388                 }
   4389                 mWakeLockImportant = true;
   4390             }
   4391             mWakeLockNesting++;
   4392         }
   4393         if (uid >= 0) {
   4394             if (mOnBatteryScreenOffTimeBase.isRunning()) {
   4395                 // We only update the cpu time when a wake lock is acquired if the screen is off.
   4396                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
   4397                 if (DEBUG_ENERGY_CPU) {
   4398                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
   4399                 }
   4400                 requestWakelockCpuUpdate();
   4401             }
   4402 
   4403             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
   4404 
   4405             if (wc != null) {
   4406                 StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
   4407                         getPowerManagerWakeLockLevel(type), name,
   4408                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
   4409             } else {
   4410                 StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
   4411                         getPowerManagerWakeLockLevel(type), name,
   4412                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
   4413             }
   4414         }
   4415     }
   4416 
   4417     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
   4418             int type, long elapsedRealtime, long uptime) {
   4419         uid = mapUid(uid);
   4420         if (type == WAKE_TYPE_PARTIAL) {
   4421             mWakeLockNesting--;
   4422             if (mRecordAllHistory) {
   4423                 if (historyName == null) {
   4424                     historyName = name;
   4425                 }
   4426                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
   4427                         uid, 0)) {
   4428                     addHistoryEventLocked(elapsedRealtime, uptime,
   4429                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
   4430                 }
   4431             }
   4432             if (mWakeLockNesting == 0) {
   4433                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
   4434                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
   4435                         + Integer.toHexString(mHistoryCur.states));
   4436                 mInitialAcquireWakeName = null;
   4437                 mInitialAcquireWakeUid = -1;
   4438                 addHistoryRecordLocked(elapsedRealtime, uptime);
   4439             }
   4440         }
   4441         if (uid >= 0) {
   4442             if (mOnBatteryScreenOffTimeBase.isRunning()) {
   4443                 if (DEBUG_ENERGY_CPU) {
   4444                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
   4445                 }
   4446                 requestWakelockCpuUpdate();
   4447             }
   4448 
   4449             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
   4450             if (wc != null) {
   4451                 StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
   4452                         getPowerManagerWakeLockLevel(type), name,
   4453                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
   4454             } else {
   4455                 StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
   4456                         getPowerManagerWakeLockLevel(type), name,
   4457                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
   4458             }
   4459         }
   4460     }
   4461 
   4462     /**
   4463      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
   4464      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
   4465      * These are estimations, since batterystats loses some of the original data.
   4466      * TODO: Delete this. Instead, StatsLog.write should be called from PowerManager's Notifier.
   4467      */
   4468     private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
   4469         switch (battertStatsWakelockType) {
   4470             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
   4471             case BatteryStats.WAKE_TYPE_PARTIAL:
   4472                 return PowerManager.PARTIAL_WAKE_LOCK;
   4473 
   4474             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
   4475             case BatteryStats.WAKE_TYPE_FULL:
   4476                 return PowerManager.FULL_WAKE_LOCK;
   4477 
   4478             case BatteryStats.WAKE_TYPE_DRAW:
   4479                 return PowerManager.DRAW_WAKE_LOCK;
   4480 
   4481             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
   4482             case BatteryStats.WAKE_TYPE_WINDOW:
   4483                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
   4484                 return -1;
   4485 
   4486             default:
   4487                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
   4488                 return -1;
   4489         }
   4490     }
   4491 
   4492     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
   4493             String historyName, int type, boolean unimportantForLogging) {
   4494         final long elapsedRealtime = mClocks.elapsedRealtime();
   4495         final long uptime = mClocks.uptimeMillis();
   4496         final int N = ws.size();
   4497         for (int i=0; i<N; i++) {
   4498             noteStartWakeLocked(ws.get(i), pid, null, name, historyName, type,
   4499                     unimportantForLogging, elapsedRealtime, uptime);
   4500         }
   4501 
   4502         List<WorkChain> wcs = ws.getWorkChains();
   4503         if (wcs != null) {
   4504             for (int i = 0; i < wcs.size(); ++i) {
   4505                 final WorkChain wc = wcs.get(i);
   4506                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
   4507                         unimportantForLogging, elapsedRealtime, uptime);
   4508             }
   4509         }
   4510     }
   4511 
   4512     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
   4513             String historyName, int type, WorkSource newWs, int newPid, String newName,
   4514             String newHistoryName, int newType, boolean newUnimportantForLogging) {
   4515         final long elapsedRealtime = mClocks.elapsedRealtime();
   4516         final long uptime = mClocks.uptimeMillis();
   4517 
   4518         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
   4519 
   4520         // For correct semantics, we start the need worksources first, so that we won't
   4521         // make inappropriate history items as if all wake locks went away and new ones
   4522         // appeared.  This is okay because tracking of wake locks allows nesting.
   4523         //
   4524         // First the starts :
   4525         final int NN = newWs.size();
   4526         for (int i=0; i<NN; i++) {
   4527             noteStartWakeLocked(newWs.get(i), newPid, null, newName, newHistoryName, newType,
   4528                     newUnimportantForLogging, elapsedRealtime, uptime);
   4529         }
   4530         if (wcs != null) {
   4531             List<WorkChain> newChains = wcs[0];
   4532             if (newChains != null) {
   4533                 for (int i = 0; i < newChains.size(); ++i) {
   4534                     final WorkChain newChain = newChains.get(i);
   4535                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
   4536                         newHistoryName, newType, newUnimportantForLogging, elapsedRealtime,
   4537                         uptime);
   4538                 }
   4539             }
   4540         }
   4541 
   4542         // Then the stops :
   4543         final int NO = ws.size();
   4544         for (int i=0; i<NO; i++) {
   4545             noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
   4546                     uptime);
   4547         }
   4548         if (wcs != null) {
   4549             List<WorkChain> goneChains = wcs[1];
   4550             if (goneChains != null) {
   4551                 for (int i = 0; i < goneChains.size(); ++i) {
   4552                     final WorkChain goneChain = goneChains.get(i);
   4553                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
   4554                             historyName, type, elapsedRealtime, uptime);
   4555                 }
   4556             }
   4557         }
   4558     }
   4559 
   4560     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
   4561             String historyName, int type) {
   4562         final long elapsedRealtime = mClocks.elapsedRealtime();
   4563         final long uptime = mClocks.uptimeMillis();
   4564         final int N = ws.size();
   4565         for (int i=0; i<N; i++) {
   4566             noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
   4567                     uptime);
   4568         }
   4569 
   4570         List<WorkChain> wcs = ws.getWorkChains();
   4571         if (wcs != null) {
   4572             for (int i = 0; i < wcs.size(); ++i) {
   4573                 final WorkChain wc = wcs.get(i);
   4574                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
   4575                         elapsedRealtime, uptime);
   4576             }
   4577         }
   4578     }
   4579 
   4580     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
   4581         StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
   4582                 uid, null, name, historyName,
   4583                 StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
   4584 
   4585         uid = mapUid(uid);
   4586         noteLongPartialWakeLockStartInternal(name, historyName, uid);
   4587     }
   4588 
   4589     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
   4590             WorkSource workSource) {
   4591         final int N = workSource.size();
   4592         for (int i = 0; i < N; ++i) {
   4593             final int uid = mapUid(workSource.get(i));
   4594             noteLongPartialWakeLockStartInternal(name, historyName, uid);
   4595             StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
   4596                     workSource.get(i), workSource.getName(i), name, historyName,
   4597                     StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
   4598         }
   4599 
   4600         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
   4601         if (workChains != null) {
   4602             for (int i = 0; i < workChains.size(); ++i) {
   4603                 final WorkChain workChain = workChains.get(i);
   4604                 final int uid = workChain.getAttributionUid();
   4605                 noteLongPartialWakeLockStartInternal(name, historyName, uid);
   4606 
   4607                 StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
   4608                         workChain.getUids(), workChain.getTags(), name, historyName,
   4609                         StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
   4610             }
   4611         }
   4612     }
   4613 
   4614     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid) {
   4615         final long elapsedRealtime = mClocks.elapsedRealtime();
   4616         final long uptime = mClocks.uptimeMillis();
   4617         if (historyName == null) {
   4618             historyName = name;
   4619         }
   4620         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
   4621                 0)) {
   4622             return;
   4623         }
   4624         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
   4625                 historyName, uid);
   4626     }
   4627 
   4628     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
   4629         StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, null,
   4630                 name, historyName, StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
   4631 
   4632         uid = mapUid(uid);
   4633         noteLongPartialWakeLockFinishInternal(name, historyName, uid);
   4634     }
   4635 
   4636     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
   4637             WorkSource workSource) {
   4638         final int N = workSource.size();
   4639         for (int i = 0; i < N; ++i) {
   4640             final int uid = mapUid(workSource.get(i));
   4641             noteLongPartialWakeLockFinishInternal(name, historyName, uid);
   4642             StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
   4643                     workSource.get(i), workSource.getName(i), name, historyName,
   4644                     StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
   4645         }
   4646 
   4647         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
   4648         if (workChains != null) {
   4649             for (int i = 0; i < workChains.size(); ++i) {
   4650                 final WorkChain workChain = workChains.get(i);
   4651                 final int uid = workChain.getAttributionUid();
   4652                 noteLongPartialWakeLockFinishInternal(name, historyName, uid);
   4653                 StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
   4654                         workChain.getUids(), workChain.getTags(), name, historyName,
   4655                         StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
   4656             }
   4657         }
   4658     }
   4659 
   4660     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid) {
   4661         final long elapsedRealtime = mClocks.elapsedRealtime();
   4662         final long uptime = mClocks.uptimeMillis();
   4663         if (historyName == null) {
   4664             historyName = name;
   4665         }
   4666         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
   4667                 0)) {
   4668             return;
   4669         }
   4670         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
   4671                 historyName, uid);
   4672     }
   4673 
   4674     void aggregateLastWakeupUptimeLocked(long uptimeMs) {
   4675         if (mLastWakeupReason != null) {
   4676             long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
   4677             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
   4678             timer.add(deltaUptime * 1000, 1); // time in in microseconds
   4679             StatsLog.write(StatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
   4680                     /* duration_usec */ deltaUptime * 1000);
   4681             mLastWakeupReason = null;
   4682         }
   4683     }
   4684 
   4685     public void noteWakeupReasonLocked(String reason) {
   4686         final long elapsedRealtime = mClocks.elapsedRealtime();
   4687         final long uptime = mClocks.uptimeMillis();
   4688         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
   4689                 + Integer.toHexString(mHistoryCur.states));
   4690         aggregateLastWakeupUptimeLocked(uptime);
   4691         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
   4692         mHistoryCur.wakeReasonTag.string = reason;
   4693         mHistoryCur.wakeReasonTag.uid = 0;
   4694         mLastWakeupReason = reason;
   4695         mLastWakeupUptimeMs = uptime;
   4696         addHistoryRecordLocked(elapsedRealtime, uptime);
   4697     }
   4698 
   4699     public boolean startAddingCpuLocked() {
   4700         mExternalSync.cancelCpuSyncDueToWakelockChange();
   4701         return mOnBatteryInternal;
   4702     }
   4703 
   4704     public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
   4705                                       int statSystemTime, int statIOWaitTime, int statIrqTime,
   4706                                       int statSoftIrqTime, int statIdleTime) {
   4707         if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
   4708                 + " user=" + statUserTime + " sys=" + statSystemTime
   4709                 + " io=" + statIOWaitTime + " irq=" + statIrqTime
   4710                 + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
   4711         mCurStepCpuUserTime += totalUTime;
   4712         mCurStepCpuSystemTime += totalSTime;
   4713         mCurStepStatUserTime += statUserTime;
   4714         mCurStepStatSystemTime += statSystemTime;
   4715         mCurStepStatIOWaitTime += statIOWaitTime;
   4716         mCurStepStatIrqTime += statIrqTime;
   4717         mCurStepStatSoftIrqTime += statSoftIrqTime;
   4718         mCurStepStatIdleTime += statIdleTime;
   4719     }
   4720 
   4721     public void noteProcessDiedLocked(int uid, int pid) {
   4722         uid = mapUid(uid);
   4723         Uid u = mUidStats.get(uid);
   4724         if (u != null) {
   4725             u.mPids.remove(pid);
   4726         }
   4727     }
   4728 
   4729     public long getProcessWakeTime(int uid, int pid, long realtime) {
   4730         uid = mapUid(uid);
   4731         Uid u = mUidStats.get(uid);
   4732         if (u != null) {
   4733             Uid.Pid p = u.mPids.get(pid);
   4734             if (p != null) {
   4735                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
   4736             }
   4737         }
   4738         return 0;
   4739     }
   4740 
   4741     public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
   4742         uid = mapUid(uid);
   4743         Uid u = mUidStats.get(uid);
   4744         if (u != null) {
   4745             u.reportExcessiveCpuLocked(proc, overTime, usedTime);
   4746         }
   4747     }
   4748 
   4749     int mSensorNesting;
   4750 
   4751     public void noteStartSensorLocked(int uid, int sensor) {
   4752         uid = mapUid(uid);
   4753         final long elapsedRealtime = mClocks.elapsedRealtime();
   4754         final long uptime = mClocks.uptimeMillis();
   4755         if (mSensorNesting == 0) {
   4756             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
   4757             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
   4758                     + Integer.toHexString(mHistoryCur.states));
   4759             addHistoryRecordLocked(elapsedRealtime, uptime);
   4760         }
   4761         mSensorNesting++;
   4762         getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
   4763     }
   4764 
   4765     public void noteStopSensorLocked(int uid, int sensor) {
   4766         uid = mapUid(uid);
   4767         final long elapsedRealtime = mClocks.elapsedRealtime();
   4768         final long uptime = mClocks.uptimeMillis();
   4769         mSensorNesting--;
   4770         if (mSensorNesting == 0) {
   4771             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
   4772             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
   4773                     + Integer.toHexString(mHistoryCur.states));
   4774             addHistoryRecordLocked(elapsedRealtime, uptime);
   4775         }
   4776         getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
   4777     }
   4778 
   4779     int mGpsNesting;
   4780 
   4781     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
   4782         for (int i = 0; i < newWs.size(); ++i) {
   4783             noteStartGpsLocked(newWs.get(i), null);
   4784         }
   4785 
   4786         for (int i = 0; i < oldWs.size(); ++i) {
   4787             noteStopGpsLocked((oldWs.get(i)), null);
   4788         }
   4789 
   4790         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
   4791         if (wcs != null) {
   4792             if (wcs[0] != null) {
   4793                 final List<WorkChain> newChains = wcs[0];
   4794                 for (int i = 0; i < newChains.size(); ++i) {
   4795                     noteStartGpsLocked(-1, newChains.get(i));
   4796                 }
   4797             }
   4798 
   4799             if (wcs[1] != null) {
   4800                 final List<WorkChain> goneChains = wcs[1];
   4801                 for (int i = 0; i < goneChains.size(); ++i) {
   4802                     noteStopGpsLocked(-1, goneChains.get(i));
   4803                 }
   4804             }
   4805         }
   4806     }
   4807 
   4808     private void noteStartGpsLocked(int uid, WorkChain workChain) {
   4809         uid = getAttributionUid(uid, workChain);
   4810         final long elapsedRealtime = mClocks.elapsedRealtime();
   4811         final long uptime = mClocks.uptimeMillis();
   4812         if (mGpsNesting == 0) {
   4813             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
   4814             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
   4815                     + Integer.toHexString(mHistoryCur.states));
   4816             addHistoryRecordLocked(elapsedRealtime, uptime);
   4817         }
   4818         mGpsNesting++;
   4819 
   4820         if (workChain == null) {
   4821             StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
   4822                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
   4823         } else {
   4824             StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED,
   4825                     workChain.getUids(), workChain.getTags(),
   4826                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
   4827         }
   4828 
   4829         getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
   4830     }
   4831 
   4832     private void noteStopGpsLocked(int uid, WorkChain workChain) {
   4833         uid = getAttributionUid(uid, workChain);
   4834         final long elapsedRealtime = mClocks.elapsedRealtime();
   4835         final long uptime = mClocks.uptimeMillis();
   4836         mGpsNesting--;
   4837         if (mGpsNesting == 0) {
   4838             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
   4839             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
   4840                     + Integer.toHexString(mHistoryCur.states));
   4841             addHistoryRecordLocked(elapsedRealtime, uptime);
   4842             stopAllGpsSignalQualityTimersLocked(-1);
   4843             mGpsSignalQualityBin = -1;
   4844         }
   4845 
   4846         if (workChain == null) {
   4847             StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
   4848                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
   4849         } else {
   4850             StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
   4851                     workChain.getTags(), StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
   4852         }
   4853 
   4854         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
   4855     }
   4856 
   4857     public void noteGpsSignalQualityLocked(int signalLevel) {
   4858         if (mGpsNesting == 0) {
   4859             return;
   4860         }
   4861         if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
   4862             stopAllGpsSignalQualityTimersLocked(-1);
   4863             return;
   4864         }
   4865         final long elapsedRealtime = mClocks.elapsedRealtime();
   4866         final long uptime = mClocks.uptimeMillis();
   4867         if (mGpsSignalQualityBin != signalLevel) {
   4868             if (mGpsSignalQualityBin >= 0) {
   4869                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
   4870             }
   4871             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
   4872                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
   4873             }
   4874             mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
   4875                     | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
   4876             addHistoryRecordLocked(elapsedRealtime, uptime);
   4877             mGpsSignalQualityBin = signalLevel;
   4878         }
   4879         return;
   4880     }
   4881 
   4882     @GuardedBy("this")
   4883     public void noteScreenStateLocked(int state) {
   4884         state = mPretendScreenOff ? Display.STATE_OFF : state;
   4885 
   4886         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
   4887         // original 4 are mapped to one of the originals.
   4888         if (state > MAX_TRACKED_SCREEN_STATE) {
   4889             switch (state) {
   4890                 case Display.STATE_VR:
   4891                     state = Display.STATE_ON;
   4892                     break;
   4893                 default:
   4894                     Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
   4895                     break;
   4896             }
   4897         }
   4898 
   4899         if (mScreenState != state) {
   4900             recordDailyStatsIfNeededLocked(true);
   4901             final int oldState = mScreenState;
   4902             mScreenState = state;
   4903             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
   4904                     + ", newState=" + Display.stateToString(state));
   4905 
   4906             if (state != Display.STATE_UNKNOWN) {
   4907                 int stepState = state-1;
   4908                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
   4909                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
   4910                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
   4911                 } else {
   4912                     Slog.wtf(TAG, "Unexpected screen state: " + state);
   4913                 }
   4914             }
   4915 
   4916             final long elapsedRealtime = mClocks.elapsedRealtime();
   4917             final long uptime = mClocks.uptimeMillis();
   4918 
   4919             boolean updateHistory = false;
   4920             if (isScreenDoze(state)) {
   4921                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
   4922                 mScreenDozeTimer.startRunningLocked(elapsedRealtime);
   4923                 updateHistory = true;
   4924             } else if (isScreenDoze(oldState)) {
   4925                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
   4926                 mScreenDozeTimer.stopRunningLocked(elapsedRealtime);
   4927                 updateHistory = true;
   4928             }
   4929             if (isScreenOn(state)) {
   4930                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
   4931                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
   4932                         + Integer.toHexString(mHistoryCur.states));
   4933                 mScreenOnTimer.startRunningLocked(elapsedRealtime);
   4934                 if (mScreenBrightnessBin >= 0) {
   4935                     mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
   4936                 }
   4937                 updateHistory = true;
   4938             } else if (isScreenOn(oldState)) {
   4939                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
   4940                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
   4941                         + Integer.toHexString(mHistoryCur.states));
   4942                 mScreenOnTimer.stopRunningLocked(elapsedRealtime);
   4943                 if (mScreenBrightnessBin >= 0) {
   4944                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
   4945                 }
   4946                 updateHistory = true;
   4947             }
   4948             if (updateHistory) {
   4949                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
   4950                         + Display.stateToString(state));
   4951                 addHistoryRecordLocked(elapsedRealtime, uptime);
   4952             }
   4953             mExternalSync.scheduleCpuSyncDueToScreenStateChange(
   4954                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
   4955             if (isScreenOn(state)) {
   4956                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
   4957                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
   4958                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
   4959                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
   4960                         elapsedRealtime, uptime);
   4961             } else if (isScreenOn(oldState)) {
   4962                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
   4963                         elapsedRealtime, uptime);
   4964                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
   4965                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
   4966             }
   4967             // Update discharge amounts.
   4968             if (mOnBatteryInternal) {
   4969                 updateDischargeScreenLevelsLocked(oldState, state);
   4970             }
   4971         }
   4972     }
   4973 
   4974     public void noteScreenBrightnessLocked(int brightness) {
   4975         // Bin the brightness.
   4976         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
   4977         if (bin < 0) bin = 0;
   4978         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
   4979         if (mScreenBrightnessBin != bin) {
   4980             final long elapsedRealtime = mClocks.elapsedRealtime();
   4981             final long uptime = mClocks.uptimeMillis();
   4982             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
   4983                     | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
   4984             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
   4985                     + Integer.toHexString(mHistoryCur.states));
   4986             addHistoryRecordLocked(elapsedRealtime, uptime);
   4987             if (mScreenState == Display.STATE_ON) {
   4988                 if (mScreenBrightnessBin >= 0) {
   4989                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
   4990                 }
   4991                 mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
   4992             }
   4993             mScreenBrightnessBin = bin;
   4994         }
   4995     }
   4996 
   4997     public void noteUserActivityLocked(int uid, int event) {
   4998         if (mOnBatteryInternal) {
   4999             uid = mapUid(uid);
   5000             getUidStatsLocked(uid).noteUserActivityLocked(event);
   5001         }
   5002     }
   5003 
   5004     public void noteWakeUpLocked(String reason, int reasonUid) {
   5005         final long elapsedRealtime = mClocks.elapsedRealtime();
   5006         final long uptime = mClocks.uptimeMillis();
   5007         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
   5008                 reason, reasonUid);
   5009     }
   5010 
   5011     public void noteInteractiveLocked(boolean interactive) {
   5012         if (mInteractive != interactive) {
   5013             final long elapsedRealtime = mClocks.elapsedRealtime();
   5014             mInteractive = interactive;
   5015             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
   5016             if (interactive) {
   5017                 mInteractiveTimer.startRunningLocked(elapsedRealtime);
   5018             } else {
   5019                 mInteractiveTimer.stopRunningLocked(elapsedRealtime);
   5020             }
   5021         }
   5022     }
   5023 
   5024     public void noteConnectivityChangedLocked(int type, String extra) {
   5025         final long elapsedRealtime = mClocks.elapsedRealtime();
   5026         final long uptime = mClocks.uptimeMillis();
   5027         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
   5028                 extra, type);
   5029         mNumConnectivityChange++;
   5030     }
   5031 
   5032     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
   5033             final long uptimeMillis, int uid) {
   5034         uid = mapUid(uid);
   5035         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
   5036                 uid);
   5037         getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
   5038     }
   5039 
   5040     /**
   5041      * Updates the radio power state and returns true if an external stats collection should occur.
   5042      */
   5043     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
   5044         final long elapsedRealtime = mClocks.elapsedRealtime();
   5045         final long uptime = mClocks.uptimeMillis();
   5046         if (mMobileRadioPowerState != powerState) {
   5047             long realElapsedRealtimeMs;
   5048             final boolean active =
   5049                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
   5050                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
   5051             if (active) {
   5052                 if (uid > 0) {
   5053                     noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid);
   5054                 }
   5055 
   5056                 mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
   5057                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
   5058             } else {
   5059                 realElapsedRealtimeMs = timestampNs / (1000*1000);
   5060                 long lastUpdateTimeMs = mMobileRadioActiveStartTime;
   5061                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
   5062                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
   5063                             + " is before start time " + lastUpdateTimeMs);
   5064                     realElapsedRealtimeMs = elapsedRealtime;
   5065                 } else if (realElapsedRealtimeMs < elapsedRealtime) {
   5066                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
   5067                             - realElapsedRealtimeMs);
   5068                 }
   5069                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
   5070             }
   5071             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
   5072                     + Integer.toHexString(mHistoryCur.states));
   5073             addHistoryRecordLocked(elapsedRealtime, uptime);
   5074             mMobileRadioPowerState = powerState;
   5075             StatsLog.write_non_chained(StatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null,
   5076                     powerState);
   5077             if (active) {
   5078                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
   5079                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
   5080             } else {
   5081                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
   5082                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
   5083                 // Tell the caller to collect radio network/power stats.
   5084                 return true;
   5085             }
   5086         }
   5087         return false;
   5088     }
   5089 
   5090     public void notePowerSaveModeLocked(boolean enabled) {
   5091         if (mPowerSaveModeEnabled != enabled) {
   5092             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
   5093             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
   5094             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
   5095             final long elapsedRealtime = mClocks.elapsedRealtime();
   5096             final long uptime = mClocks.uptimeMillis();
   5097             mPowerSaveModeEnabled = enabled;
   5098             if (enabled) {
   5099                 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
   5100                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
   5101                         + Integer.toHexString(mHistoryCur.states2));
   5102                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
   5103             } else {
   5104                 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
   5105                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
   5106                         + Integer.toHexString(mHistoryCur.states2));
   5107                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
   5108             }
   5109             addHistoryRecordLocked(elapsedRealtime, uptime);
   5110             StatsLog.write(StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ?
   5111                     StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON :
   5112                     StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
   5113         }
   5114     }
   5115 
   5116     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
   5117         final long elapsedRealtime = mClocks.elapsedRealtime();
   5118         final long uptime = mClocks.uptimeMillis();
   5119         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
   5120         if (mDeviceIdling && !nowIdling && activeReason == null) {
   5121             // We don't go out of general idling mode until explicitly taken out of
   5122             // device idle through going active or significant motion.
   5123             nowIdling = true;
   5124         }
   5125         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
   5126         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
   5127             // We don't go out of general light idling mode until explicitly taken out of
   5128             // device idle through going active or significant motion.
   5129             nowLightIdling = true;
   5130         }
   5131         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
   5132             addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
   5133                     activeReason, activeUid);
   5134         }
   5135         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
   5136             int statsmode;
   5137             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
   5138             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
   5139             else                     statsmode = DEVICE_IDLE_MODE_OFF;
   5140             StatsLog.write(StatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
   5141         }
   5142         if (mDeviceIdling != nowIdling) {
   5143             mDeviceIdling = nowIdling;
   5144             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
   5145             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
   5146             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
   5147             if (nowIdling) {
   5148                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
   5149             } else {
   5150                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
   5151             }
   5152         }
   5153         if (mDeviceLightIdling != nowLightIdling) {
   5154             mDeviceLightIdling = nowLightIdling;
   5155             if (nowLightIdling) {
   5156                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
   5157             } else {
   5158                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
   5159             }
   5160         }
   5161         if (mDeviceIdleMode != mode) {
   5162             mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
   5163                     | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
   5164             if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
   5165                     + Integer.toHexString(mHistoryCur.states2));
   5166             addHistoryRecordLocked(elapsedRealtime, uptime);
   5167             long lastDuration = elapsedRealtime - mLastIdleTimeStart;
   5168             mLastIdleTimeStart = elapsedRealtime;
   5169             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
   5170                 if (lastDuration > mLongestLightIdleTime) {
   5171                     mLongestLightIdleTime = lastDuration;
   5172                 }
   5173                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
   5174             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
   5175                 if (lastDuration > mLongestFullIdleTime) {
   5176                     mLongestFullIdleTime = lastDuration;
   5177                 }
   5178                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
   5179             }
   5180             if (mode == DEVICE_IDLE_MODE_LIGHT) {
   5181                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
   5182             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
   5183                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
   5184             }
   5185             mDeviceIdleMode = mode;
   5186             StatsLog.write(StatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
   5187         }
   5188     }
   5189 
   5190     public void notePackageInstalledLocked(String pkgName, long versionCode) {
   5191         final long elapsedRealtime = mClocks.elapsedRealtime();
   5192         final long uptime = mClocks.uptimeMillis();
   5193         // XXX need to figure out what to do with long version codes.
   5194         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
   5195                 pkgName, (int)versionCode);
   5196         PackageChange pc = new PackageChange();
   5197         pc.mPackageName = pkgName;
   5198         pc.mUpdate = true;
   5199         pc.mVersionCode = versionCode;
   5200         addPackageChange(pc);
   5201     }
   5202 
   5203     public void notePackageUninstalledLocked(String pkgName) {
   5204         final long elapsedRealtime = mClocks.elapsedRealtime();
   5205         final long uptime = mClocks.uptimeMillis();
   5206         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
   5207                 pkgName, 0);
   5208         PackageChange pc = new PackageChange();
   5209         pc.mPackageName = pkgName;
   5210         pc.mUpdate = true;
   5211         addPackageChange(pc);
   5212     }
   5213 
   5214     private void addPackageChange(PackageChange pc) {
   5215         if (mDailyPackageChanges == null) {
   5216             mDailyPackageChanges = new ArrayList<>();
   5217         }
   5218         mDailyPackageChanges.add(pc);
   5219     }
   5220 
   5221     void stopAllGpsSignalQualityTimersLocked(int except) {
   5222         final long elapsedRealtime = mClocks.elapsedRealtime();
   5223         for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
   5224             if (i == except) {
   5225                 continue;
   5226             }
   5227             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
   5228                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
   5229             }
   5230         }
   5231     }
   5232 
   5233     public void notePhoneOnLocked() {
   5234         if (!mPhoneOn) {
   5235             final long elapsedRealtime = mClocks.elapsedRealtime();
   5236             final long uptime = mClocks.uptimeMillis();
   5237             mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
   5238             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
   5239                     + Integer.toHexString(mHistoryCur.states));
   5240             addHistoryRecordLocked(elapsedRealtime, uptime);
   5241             mPhoneOn = true;
   5242             mPhoneOnTimer.startRunningLocked(elapsedRealtime);
   5243         }
   5244     }
   5245 
   5246     public void notePhoneOffLocked() {
   5247         if (mPhoneOn) {
   5248             final long elapsedRealtime = mClocks.elapsedRealtime();
   5249             final long uptime = mClocks.uptimeMillis();
   5250             mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
   5251             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
   5252                     + Integer.toHexString(mHistoryCur.states));
   5253             addHistoryRecordLocked(elapsedRealtime, uptime);
   5254             mPhoneOn = false;
   5255             mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
   5256         }
   5257     }
   5258 
   5259     private void registerUsbStateReceiver(Context context) {
   5260         final IntentFilter usbStateFilter = new IntentFilter();
   5261         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
   5262         context.registerReceiver(new BroadcastReceiver() {
   5263             @Override
   5264             public void onReceive(Context context, Intent intent) {
   5265                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
   5266                 synchronized (BatteryStatsImpl.this) {
   5267                     noteUsbConnectionStateLocked(state);
   5268                 }
   5269             }
   5270         }, usbStateFilter);
   5271         synchronized (this) {
   5272             if (mUsbDataState == USB_DATA_UNKNOWN) {
   5273                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
   5274                 final boolean initState = usbState != null && usbState.getBooleanExtra(
   5275                         UsbManager.USB_CONNECTED, false);
   5276                 noteUsbConnectionStateLocked(initState);
   5277             }
   5278         }
   5279     }
   5280 
   5281     private void noteUsbConnectionStateLocked(boolean connected) {
   5282         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
   5283         if (mUsbDataState != newState) {
   5284             mUsbDataState = newState;
   5285             if (connected) {
   5286                 mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
   5287             } else {
   5288                 mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
   5289             }
   5290             addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
   5291         }
   5292     }
   5293 
   5294     void stopAllPhoneSignalStrengthTimersLocked(int except) {
   5295         final long elapsedRealtime = mClocks.elapsedRealtime();
   5296         for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   5297             if (i == except) {
   5298                 continue;
   5299             }
   5300             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
   5301                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
   5302             }
   5303         }
   5304     }
   5305 
   5306     private int fixPhoneServiceState(int state, int signalBin) {
   5307         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
   5308             // In this case we will always be STATE_OUT_OF_SERVICE, so need
   5309             // to infer that we are scanning from other data.
   5310             if (state == ServiceState.STATE_OUT_OF_SERVICE
   5311                     && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
   5312                 state = ServiceState.STATE_IN_SERVICE;
   5313             }
   5314         }
   5315 
   5316         return state;
   5317     }
   5318 
   5319     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
   5320         boolean scanning = false;
   5321         boolean newHistory = false;
   5322 
   5323         mPhoneServiceStateRaw = state;
   5324         mPhoneSimStateRaw = simState;
   5325         mPhoneSignalStrengthBinRaw = strengthBin;
   5326 
   5327         final long elapsedRealtime = mClocks.elapsedRealtime();
   5328         final long uptime = mClocks.uptimeMillis();
   5329 
   5330         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
   5331             // In this case we will always be STATE_OUT_OF_SERVICE, so need
   5332             // to infer that we are scanning from other data.
   5333             if (state == ServiceState.STATE_OUT_OF_SERVICE
   5334                     && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
   5335                 state = ServiceState.STATE_IN_SERVICE;
   5336             }
   5337         }
   5338 
   5339         // If the phone is powered off, stop all timers.
   5340         if (state == ServiceState.STATE_POWER_OFF) {
   5341             strengthBin = -1;
   5342 
   5343         // If we are in service, make sure the correct signal string timer is running.
   5344         } else if (state == ServiceState.STATE_IN_SERVICE) {
   5345             // Bin will be changed below.
   5346 
   5347         // If we're out of service, we are in the lowest signal strength
   5348         // bin and have the scanning bit set.
   5349         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
   5350             scanning = true;
   5351             strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
   5352             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
   5353                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
   5354                 newHistory = true;
   5355                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
   5356                         + Integer.toHexString(mHistoryCur.states));
   5357                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
   5358             }
   5359         }
   5360 
   5361         if (!scanning) {
   5362             // If we are no longer scanning, then stop the scanning timer.
   5363             if (mPhoneSignalScanningTimer.isRunningLocked()) {
   5364                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
   5365                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
   5366                         + Integer.toHexString(mHistoryCur.states));
   5367                 newHistory = true;
   5368                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
   5369             }
   5370         }
   5371 
   5372         if (mPhoneServiceState != state) {
   5373             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
   5374                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
   5375             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
   5376                     + Integer.toHexString(mHistoryCur.states));
   5377             newHistory = true;
   5378             mPhoneServiceState = state;
   5379         }
   5380 
   5381         if (mPhoneSignalStrengthBin != strengthBin) {
   5382             if (mPhoneSignalStrengthBin >= 0) {
   5383                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
   5384                         elapsedRealtime);
   5385             }
   5386             if (strengthBin >= 0) {
   5387                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
   5388                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
   5389                 }
   5390                 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
   5391                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
   5392                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
   5393                         + Integer.toHexString(mHistoryCur.states));
   5394                 newHistory = true;
   5395                 StatsLog.write(StatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
   5396             } else {
   5397                 stopAllPhoneSignalStrengthTimersLocked(-1);
   5398             }
   5399             mPhoneSignalStrengthBin = strengthBin;
   5400         }
   5401 
   5402         if (newHistory) {
   5403             addHistoryRecordLocked(elapsedRealtime, uptime);
   5404         }
   5405     }
   5406 
   5407     /**
   5408      * Telephony stack updates the phone state.
   5409      * @param state phone state from ServiceState.getState()
   5410      */
   5411     public void notePhoneStateLocked(int state, int simState) {
   5412         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
   5413     }
   5414 
   5415     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
   5416         // Bin the strength.
   5417         int bin = signalStrength.getLevel();
   5418         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
   5419     }
   5420 
   5421     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
   5422         // BatteryStats uses 0 to represent no network type.
   5423         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
   5424         // Unknown is included in DATA_CONNECTION_OTHER.
   5425         int bin = DATA_CONNECTION_NONE;
   5426         if (hasData) {
   5427             if (dataType > 0 && dataType <= TelephonyManager.MAX_NETWORK_TYPE) {
   5428                 bin = dataType;
   5429             } else {
   5430                 bin = DATA_CONNECTION_OTHER;
   5431             }
   5432         }
   5433         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
   5434         if (mPhoneDataConnectionType != bin) {
   5435             final long elapsedRealtime = mClocks.elapsedRealtime();
   5436             final long uptime = mClocks.uptimeMillis();
   5437             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
   5438                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
   5439             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
   5440                     + Integer.toHexString(mHistoryCur.states));
   5441             addHistoryRecordLocked(elapsedRealtime, uptime);
   5442             if (mPhoneDataConnectionType >= 0) {
   5443                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
   5444                         elapsedRealtime);
   5445             }
   5446             mPhoneDataConnectionType = bin;
   5447             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
   5448         }
   5449     }
   5450 
   5451     public void noteWifiOnLocked() {
   5452         if (!mWifiOn) {
   5453             final long elapsedRealtime = mClocks.elapsedRealtime();
   5454             final long uptime = mClocks.uptimeMillis();
   5455             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
   5456             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
   5457                     + Integer.toHexString(mHistoryCur.states));
   5458             addHistoryRecordLocked(elapsedRealtime, uptime);
   5459             mWifiOn = true;
   5460             mWifiOnTimer.startRunningLocked(elapsedRealtime);
   5461             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
   5462         }
   5463     }
   5464 
   5465     public void noteWifiOffLocked() {
   5466         final long elapsedRealtime = mClocks.elapsedRealtime();
   5467         final long uptime = mClocks.uptimeMillis();
   5468         if (mWifiOn) {
   5469             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
   5470             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
   5471                     + Integer.toHexString(mHistoryCur.states));
   5472             addHistoryRecordLocked(elapsedRealtime, uptime);
   5473             mWifiOn = false;
   5474             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
   5475             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
   5476         }
   5477     }
   5478 
   5479     public void noteAudioOnLocked(int uid) {
   5480         uid = mapUid(uid);
   5481         final long elapsedRealtime = mClocks.elapsedRealtime();
   5482         final long uptime = mClocks.uptimeMillis();
   5483         if (mAudioOnNesting == 0) {
   5484             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
   5485             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
   5486                     + Integer.toHexString(mHistoryCur.states));
   5487             addHistoryRecordLocked(elapsedRealtime, uptime);
   5488             mAudioOnTimer.startRunningLocked(elapsedRealtime);
   5489         }
   5490         mAudioOnNesting++;
   5491         getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
   5492     }
   5493 
   5494     public void noteAudioOffLocked(int uid) {
   5495         if (mAudioOnNesting == 0) {
   5496             return;
   5497         }
   5498         uid = mapUid(uid);
   5499         final long elapsedRealtime = mClocks.elapsedRealtime();
   5500         final long uptime = mClocks.uptimeMillis();
   5501         if (--mAudioOnNesting == 0) {
   5502             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
   5503             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
   5504                     + Integer.toHexString(mHistoryCur.states));
   5505             addHistoryRecordLocked(elapsedRealtime, uptime);
   5506             mAudioOnTimer.stopRunningLocked(elapsedRealtime);
   5507         }
   5508         getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
   5509     }
   5510 
   5511     public void noteVideoOnLocked(int uid) {
   5512         uid = mapUid(uid);
   5513         final long elapsedRealtime = mClocks.elapsedRealtime();
   5514         final long uptime = mClocks.uptimeMillis();
   5515         if (mVideoOnNesting == 0) {
   5516             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
   5517             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
   5518                     + Integer.toHexString(mHistoryCur.states));
   5519             addHistoryRecordLocked(elapsedRealtime, uptime);
   5520             mVideoOnTimer.startRunningLocked(elapsedRealtime);
   5521         }
   5522         mVideoOnNesting++;
   5523         getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
   5524     }
   5525 
   5526     public void noteVideoOffLocked(int uid) {
   5527         if (mVideoOnNesting == 0) {
   5528             return;
   5529         }
   5530         uid = mapUid(uid);
   5531         final long elapsedRealtime = mClocks.elapsedRealtime();
   5532         final long uptime = mClocks.uptimeMillis();
   5533         if (--mVideoOnNesting == 0) {
   5534             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
   5535             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
   5536                     + Integer.toHexString(mHistoryCur.states));
   5537             addHistoryRecordLocked(elapsedRealtime, uptime);
   5538             mVideoOnTimer.stopRunningLocked(elapsedRealtime);
   5539         }
   5540         getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
   5541     }
   5542 
   5543     public void noteResetAudioLocked() {
   5544         if (mAudioOnNesting > 0) {
   5545             final long elapsedRealtime = mClocks.elapsedRealtime();
   5546             final long uptime = mClocks.uptimeMillis();
   5547             mAudioOnNesting = 0;
   5548             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
   5549             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
   5550                     + Integer.toHexString(mHistoryCur.states));
   5551             addHistoryRecordLocked(elapsedRealtime, uptime);
   5552             mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
   5553             for (int i=0; i<mUidStats.size(); i++) {
   5554                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   5555                 uid.noteResetAudioLocked(elapsedRealtime);
   5556             }
   5557         }
   5558     }
   5559 
   5560     public void noteResetVideoLocked() {
   5561         if (mVideoOnNesting > 0) {
   5562             final long elapsedRealtime = mClocks.elapsedRealtime();
   5563             final long uptime = mClocks.uptimeMillis();
   5564             mAudioOnNesting = 0;
   5565             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
   5566             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
   5567                     + Integer.toHexString(mHistoryCur.states));
   5568             addHistoryRecordLocked(elapsedRealtime, uptime);
   5569             mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
   5570             for (int i=0; i<mUidStats.size(); i++) {
   5571                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   5572                 uid.noteResetVideoLocked(elapsedRealtime);
   5573             }
   5574         }
   5575     }
   5576 
   5577     public void noteActivityResumedLocked(int uid) {
   5578         uid = mapUid(uid);
   5579         getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
   5580     }
   5581 
   5582     public void noteActivityPausedLocked(int uid) {
   5583         uid = mapUid(uid);
   5584         getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
   5585     }
   5586 
   5587     public void noteVibratorOnLocked(int uid, long durationMillis) {
   5588         uid = mapUid(uid);
   5589         getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
   5590     }
   5591 
   5592     public void noteVibratorOffLocked(int uid) {
   5593         uid = mapUid(uid);
   5594         getUidStatsLocked(uid).noteVibratorOffLocked();
   5595     }
   5596 
   5597     public void noteFlashlightOnLocked(int uid) {
   5598         uid = mapUid(uid);
   5599         final long elapsedRealtime = mClocks.elapsedRealtime();
   5600         final long uptime = mClocks.uptimeMillis();
   5601         if (mFlashlightOnNesting++ == 0) {
   5602             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
   5603             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
   5604                     + Integer.toHexString(mHistoryCur.states2));
   5605             addHistoryRecordLocked(elapsedRealtime, uptime);
   5606             mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
   5607         }
   5608         getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
   5609     }
   5610 
   5611     public void noteFlashlightOffLocked(int uid) {
   5612         if (mFlashlightOnNesting == 0) {
   5613             return;
   5614         }
   5615         uid = mapUid(uid);
   5616         final long elapsedRealtime = mClocks.elapsedRealtime();
   5617         final long uptime = mClocks.uptimeMillis();
   5618         if (--mFlashlightOnNesting == 0) {
   5619             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
   5620             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
   5621                     + Integer.toHexString(mHistoryCur.states2));
   5622             addHistoryRecordLocked(elapsedRealtime, uptime);
   5623             mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
   5624         }
   5625         getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
   5626     }
   5627 
   5628     public void noteCameraOnLocked(int uid) {
   5629         uid = mapUid(uid);
   5630         final long elapsedRealtime = mClocks.elapsedRealtime();
   5631         final long uptime = mClocks.uptimeMillis();
   5632         if (mCameraOnNesting++ == 0) {
   5633             mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
   5634             if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
   5635                     + Integer.toHexString(mHistoryCur.states2));
   5636             addHistoryRecordLocked(elapsedRealtime, uptime);
   5637             mCameraOnTimer.startRunningLocked(elapsedRealtime);
   5638         }
   5639         getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
   5640     }
   5641 
   5642     public void noteCameraOffLocked(int uid) {
   5643         if (mCameraOnNesting == 0) {
   5644             return;
   5645         }
   5646         uid = mapUid(uid);
   5647         final long elapsedRealtime = mClocks.elapsedRealtime();
   5648         final long uptime = mClocks.uptimeMillis();
   5649         if (--mCameraOnNesting == 0) {
   5650             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
   5651             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
   5652                     + Integer.toHexString(mHistoryCur.states2));
   5653             addHistoryRecordLocked(elapsedRealtime, uptime);
   5654             mCameraOnTimer.stopRunningLocked(elapsedRealtime);
   5655         }
   5656         getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
   5657     }
   5658 
   5659     public void noteResetCameraLocked() {
   5660         if (mCameraOnNesting > 0) {
   5661             final long elapsedRealtime = mClocks.elapsedRealtime();
   5662             final long uptime = mClocks.uptimeMillis();
   5663             mCameraOnNesting = 0;
   5664             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
   5665             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
   5666                     + Integer.toHexString(mHistoryCur.states2));
   5667             addHistoryRecordLocked(elapsedRealtime, uptime);
   5668             mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
   5669             for (int i=0; i<mUidStats.size(); i++) {
   5670                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   5671                 uid.noteResetCameraLocked(elapsedRealtime);
   5672             }
   5673         }
   5674     }
   5675 
   5676     public void noteResetFlashlightLocked() {
   5677         if (mFlashlightOnNesting > 0) {
   5678             final long elapsedRealtime = mClocks.elapsedRealtime();
   5679             final long uptime = mClocks.uptimeMillis();
   5680             mFlashlightOnNesting = 0;
   5681             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
   5682             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
   5683                     + Integer.toHexString(mHistoryCur.states2));
   5684             addHistoryRecordLocked(elapsedRealtime, uptime);
   5685             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
   5686             for (int i=0; i<mUidStats.size(); i++) {
   5687                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   5688                 uid.noteResetFlashlightLocked(elapsedRealtime);
   5689             }
   5690         }
   5691     }
   5692 
   5693     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
   5694             boolean isUnoptimized) {
   5695         uid = getAttributionUid(uid, workChain);
   5696         final long elapsedRealtime = mClocks.elapsedRealtime();
   5697         final long uptime = mClocks.uptimeMillis();
   5698         if (mBluetoothScanNesting == 0) {
   5699             mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
   5700             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
   5701                     + Integer.toHexString(mHistoryCur.states2));
   5702             addHistoryRecordLocked(elapsedRealtime, uptime);
   5703             mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
   5704         }
   5705         mBluetoothScanNesting++;
   5706         getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized);
   5707     }
   5708 
   5709     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
   5710         final int N = ws.size();
   5711         for (int i = 0; i < N; i++) {
   5712             noteBluetoothScanStartedLocked(null, ws.get(i), isUnoptimized);
   5713         }
   5714 
   5715         final List<WorkChain> workChains = ws.getWorkChains();
   5716         if (workChains != null) {
   5717             for (int i = 0; i < workChains.size(); ++i) {
   5718                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized);
   5719             }
   5720         }
   5721     }
   5722 
   5723     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
   5724             boolean isUnoptimized) {
   5725         uid = getAttributionUid(uid, workChain);
   5726         final long elapsedRealtime = mClocks.elapsedRealtime();
   5727         final long uptime = mClocks.uptimeMillis();
   5728         mBluetoothScanNesting--;
   5729         if (mBluetoothScanNesting == 0) {
   5730             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
   5731             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
   5732                     + Integer.toHexString(mHistoryCur.states2));
   5733             addHistoryRecordLocked(elapsedRealtime, uptime);
   5734             mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
   5735         }
   5736         getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime, isUnoptimized);
   5737     }
   5738 
   5739     private int getAttributionUid(int uid, WorkChain workChain) {
   5740         if (workChain != null) {
   5741             return mapUid(workChain.getAttributionUid());
   5742         }
   5743 
   5744         return mapUid(uid);
   5745     }
   5746 
   5747     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
   5748         final int N = ws.size();
   5749         for (int i = 0; i < N; i++) {
   5750             noteBluetoothScanStoppedLocked(null, ws.get(i), isUnoptimized);
   5751         }
   5752 
   5753         final List<WorkChain> workChains = ws.getWorkChains();
   5754         if (workChains != null) {
   5755             for (int i = 0; i < workChains.size(); ++i) {
   5756                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized);
   5757             }
   5758         }
   5759     }
   5760 
   5761     public void noteResetBluetoothScanLocked() {
   5762         if (mBluetoothScanNesting > 0) {
   5763             final long elapsedRealtime = mClocks.elapsedRealtime();
   5764             final long uptime = mClocks.uptimeMillis();
   5765             mBluetoothScanNesting = 0;
   5766             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
   5767             if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
   5768                     + Integer.toHexString(mHistoryCur.states2));
   5769             addHistoryRecordLocked(elapsedRealtime, uptime);
   5770             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
   5771             for (int i=0; i<mUidStats.size(); i++) {
   5772                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
   5773                 uid.noteResetBluetoothScanLocked(elapsedRealtime);
   5774             }
   5775         }
   5776     }
   5777 
   5778     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
   5779         final int N = ws.size();
   5780         for (int i = 0; i < N; i++) {
   5781             int uid = mapUid(ws.get(i));
   5782             getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
   5783             StatsLog.write_non_chained(StatsLog.BLE_SCAN_RESULT_RECEIVED, ws.get(i), ws.getName(i),
   5784                     numNewResults);
   5785         }
   5786 
   5787         final List<WorkChain> workChains = ws.getWorkChains();
   5788         if (workChains != null) {
   5789             for (int i = 0; i < workChains.size(); ++i) {
   5790                 final WorkChain wc = workChains.get(i);
   5791                 int uid = mapUid(wc.getAttributionUid());
   5792                 getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
   5793                 StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED,
   5794                         wc.getUids(), wc.getTags(), numNewResults);
   5795             }
   5796         }
   5797     }
   5798 
   5799     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
   5800             final long uptimeMillis, int uid) {
   5801         uid = mapUid(uid);
   5802         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
   5803                 uid);
   5804         getUidStatsLocked(uid).noteWifiRadioApWakeupLocked();
   5805     }
   5806 
   5807     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
   5808         final long elapsedRealtime = mClocks.elapsedRealtime();
   5809         final long uptime = mClocks.uptimeMillis();
   5810         if (mWifiRadioPowerState != powerState) {
   5811             final boolean active =
   5812                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
   5813                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
   5814             if (active) {
   5815                 if (uid > 0) {
   5816                     noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid);
   5817                 }
   5818                 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
   5819                 mWifiActiveTimer.startRunningLocked(elapsedRealtime);
   5820             } else {
   5821                 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
   5822                 mWifiActiveTimer.stopRunningLocked(
   5823                     timestampNs / (1000 * 1000));
   5824             }
   5825             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
   5826                     + Integer.toHexString(mHistoryCur.states));
   5827             addHistoryRecordLocked(elapsedRealtime, uptime);
   5828             mWifiRadioPowerState = powerState;
   5829             StatsLog.write_non_chained(StatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null,
   5830                     powerState);
   5831         }
   5832     }
   5833 
   5834     public void noteWifiRunningLocked(WorkSource ws) {
   5835         if (!mGlobalWifiRunning) {
   5836             final long elapsedRealtime = mClocks.elapsedRealtime();
   5837             final long uptime = mClocks.uptimeMillis();
   5838             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
   5839             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
   5840                     + Integer.toHexString(mHistoryCur.states));
   5841             addHistoryRecordLocked(elapsedRealtime, uptime);
   5842             mGlobalWifiRunning = true;
   5843             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
   5844             int N = ws.size();
   5845             for (int i=0; i<N; i++) {
   5846                 int uid = mapUid(ws.get(i));
   5847                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
   5848             }
   5849 
   5850             List<WorkChain> workChains = ws.getWorkChains();
   5851             if (workChains != null) {
   5852                 for (int i = 0; i < workChains.size(); ++i) {
   5853                     int uid = mapUid(workChains.get(i).getAttributionUid());
   5854                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
   5855                 }
   5856             }
   5857 
   5858             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
   5859         } else {
   5860             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
   5861         }
   5862     }
   5863 
   5864     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
   5865         if (mGlobalWifiRunning) {
   5866             final long elapsedRealtime = mClocks.elapsedRealtime();
   5867             int N = oldWs.size();
   5868             for (int i=0; i<N; i++) {
   5869                 int uid = mapUid(oldWs.get(i));
   5870                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
   5871             }
   5872 
   5873             List<WorkChain> workChains = oldWs.getWorkChains();
   5874             if (workChains != null) {
   5875                 for (int i = 0; i < workChains.size(); ++i) {
   5876                     int uid = mapUid(workChains.get(i).getAttributionUid());
   5877                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
   5878                 }
   5879             }
   5880 
   5881             N = newWs.size();
   5882             for (int i=0; i<N; i++) {
   5883                 int uid = mapUid(newWs.get(i));
   5884                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
   5885             }
   5886 
   5887             workChains = newWs.getWorkChains();
   5888             if (workChains != null) {
   5889                 for (int i = 0; i < workChains.size(); ++i) {
   5890                     int uid = mapUid(workChains.get(i).getAttributionUid());
   5891                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
   5892                 }
   5893             }
   5894         } else {
   5895             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
   5896         }
   5897     }
   5898 
   5899     public void noteWifiStoppedLocked(WorkSource ws) {
   5900         if (mGlobalWifiRunning) {
   5901             final long elapsedRealtime = mClocks.elapsedRealtime();
   5902             final long uptime = mClocks.uptimeMillis();
   5903             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
   5904             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
   5905                     + Integer.toHexString(mHistoryCur.states));
   5906             addHistoryRecordLocked(elapsedRealtime, uptime);
   5907             mGlobalWifiRunning = false;
   5908             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
   5909             int N = ws.size();
   5910             for (int i=0; i<N; i++) {
   5911                 int uid = mapUid(ws.get(i));
   5912                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
   5913             }
   5914 
   5915             List<WorkChain> workChains = ws.getWorkChains();
   5916             if (workChains != null) {
   5917                 for (int i = 0; i < workChains.size(); ++i) {
   5918                     int uid = mapUid(workChains.get(i).getAttributionUid());
   5919                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
   5920                 }
   5921             }
   5922 
   5923             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
   5924         } else {
   5925             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
   5926         }
   5927     }
   5928 
   5929     public void noteWifiStateLocked(int wifiState, String accessPoint) {
   5930         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
   5931         if (mWifiState != wifiState) {
   5932             final long elapsedRealtime = mClocks.elapsedRealtime();
   5933             if (mWifiState >= 0) {
   5934                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
   5935             }
   5936             mWifiState = wifiState;
   5937             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
   5938             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
   5939         }
   5940     }
   5941 
   5942     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
   5943         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
   5944         if (mWifiSupplState != supplState) {
   5945             final long elapsedRealtime = mClocks.elapsedRealtime();
   5946             final long uptime = mClocks.uptimeMillis();
   5947             if (mWifiSupplState >= 0) {
   5948                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
   5949             }
   5950             mWifiSupplState = supplState;
   5951             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
   5952             mHistoryCur.states2 =
   5953                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
   5954                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
   5955             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
   5956                     + Integer.toHexString(mHistoryCur.states2));
   5957             addHistoryRecordLocked(elapsedRealtime, uptime);
   5958         }
   5959     }
   5960 
   5961     void stopAllWifiSignalStrengthTimersLocked(int except) {
   5962         final long elapsedRealtime = mClocks.elapsedRealtime();
   5963         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   5964             if (i == except) {
   5965                 continue;
   5966             }
   5967             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
   5968                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
   5969             }
   5970         }
   5971     }
   5972 
   5973     public void noteWifiRssiChangedLocked(int newRssi) {
   5974         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
   5975         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
   5976         if (mWifiSignalStrengthBin != strengthBin) {
   5977             final long elapsedRealtime = mClocks.elapsedRealtime();
   5978             final long uptime = mClocks.uptimeMillis();
   5979             if (mWifiSignalStrengthBin >= 0) {
   5980                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
   5981                         elapsedRealtime);
   5982             }
   5983             if (strengthBin >= 0) {
   5984                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
   5985                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
   5986                 }
   5987                 mHistoryCur.states2 =
   5988                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
   5989                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
   5990                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
   5991                         + Integer.toHexString(mHistoryCur.states2));
   5992                 addHistoryRecordLocked(elapsedRealtime, uptime);
   5993             } else {
   5994                 stopAllWifiSignalStrengthTimersLocked(-1);
   5995             }
   5996             StatsLog.write(StatsLog.WIFI_SIGNAL_STRENGTH_CHANGED, strengthBin);
   5997             mWifiSignalStrengthBin = strengthBin;
   5998         }
   5999     }
   6000 
   6001     int mWifiFullLockNesting = 0;
   6002 
   6003     public void noteFullWifiLockAcquiredLocked(int uid) {
   6004         final long elapsedRealtime = mClocks.elapsedRealtime();
   6005         final long uptime = mClocks.uptimeMillis();
   6006         if (mWifiFullLockNesting == 0) {
   6007             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
   6008             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
   6009                     + Integer.toHexString(mHistoryCur.states));
   6010             addHistoryRecordLocked(elapsedRealtime, uptime);
   6011         }
   6012         mWifiFullLockNesting++;
   6013         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
   6014     }
   6015 
   6016     public void noteFullWifiLockReleasedLocked(int uid) {
   6017         final long elapsedRealtime = mClocks.elapsedRealtime();
   6018         final long uptime = mClocks.uptimeMillis();
   6019         mWifiFullLockNesting--;
   6020         if (mWifiFullLockNesting == 0) {
   6021             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
   6022             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
   6023                     + Integer.toHexString(mHistoryCur.states));
   6024             addHistoryRecordLocked(elapsedRealtime, uptime);
   6025         }
   6026         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
   6027     }
   6028 
   6029     int mWifiScanNesting = 0;
   6030 
   6031     public void noteWifiScanStartedLocked(int uid) {
   6032         final long elapsedRealtime = mClocks.elapsedRealtime();
   6033         final long uptime = mClocks.uptimeMillis();
   6034         if (mWifiScanNesting == 0) {
   6035             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
   6036             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
   6037                     + Integer.toHexString(mHistoryCur.states));
   6038             addHistoryRecordLocked(elapsedRealtime, uptime);
   6039         }
   6040         mWifiScanNesting++;
   6041         getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
   6042     }
   6043 
   6044     public void noteWifiScanStoppedLocked(int uid) {
   6045         final long elapsedRealtime = mClocks.elapsedRealtime();
   6046         final long uptime = mClocks.uptimeMillis();
   6047         mWifiScanNesting--;
   6048         if (mWifiScanNesting == 0) {
   6049             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
   6050             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
   6051                     + Integer.toHexString(mHistoryCur.states));
   6052             addHistoryRecordLocked(elapsedRealtime, uptime);
   6053         }
   6054         getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
   6055     }
   6056 
   6057     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
   6058         uid = mapUid(uid);
   6059         final long elapsedRealtime = mClocks.elapsedRealtime();
   6060         getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
   6061     }
   6062 
   6063     public void noteWifiBatchedScanStoppedLocked(int uid) {
   6064         uid = mapUid(uid);
   6065         final long elapsedRealtime = mClocks.elapsedRealtime();
   6066         getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
   6067     }
   6068 
   6069     int mWifiMulticastNesting = 0;
   6070 
   6071     public void noteWifiMulticastEnabledLocked(int uid) {
   6072         uid = mapUid(uid);
   6073         final long elapsedRealtime = mClocks.elapsedRealtime();
   6074         final long uptime = mClocks.uptimeMillis();
   6075         if (mWifiMulticastNesting == 0) {
   6076             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
   6077             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
   6078                     + Integer.toHexString(mHistoryCur.states));
   6079             addHistoryRecordLocked(elapsedRealtime, uptime);
   6080 
   6081             // Start Wifi Multicast overall timer
   6082             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
   6083                 if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
   6084                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtime);
   6085             }
   6086         }
   6087         mWifiMulticastNesting++;
   6088         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
   6089     }
   6090 
   6091     public void noteWifiMulticastDisabledLocked(int uid) {
   6092         uid = mapUid(uid);
   6093         final long elapsedRealtime = mClocks.elapsedRealtime();
   6094         final long uptime = mClocks.uptimeMillis();
   6095         mWifiMulticastNesting--;
   6096         if (mWifiMulticastNesting == 0) {
   6097             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
   6098             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
   6099                     + Integer.toHexString(mHistoryCur.states));
   6100             addHistoryRecordLocked(elapsedRealtime, uptime);
   6101 
   6102             // Stop Wifi Multicast overall timer
   6103             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
   6104                 if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
   6105                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtime);
   6106             }
   6107         }
   6108         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
   6109     }
   6110 
   6111     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
   6112         int N = ws.size();
   6113         for (int i=0; i<N; i++) {
   6114             final int uid = mapUid(ws.get(i));
   6115             noteFullWifiLockAcquiredLocked(uid);
   6116             StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
   6117                     StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
   6118         }
   6119 
   6120         final List<WorkChain> workChains = ws.getWorkChains();
   6121         if (workChains != null) {
   6122             for (int i = 0; i < workChains.size(); ++i) {
   6123                 final WorkChain workChain = workChains.get(i);
   6124                 final int uid = mapUid(workChain.getAttributionUid());
   6125                 noteFullWifiLockAcquiredLocked(uid);
   6126                 StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
   6127                         workChain.getUids(), workChain.getTags(),
   6128                         StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
   6129             }
   6130         }
   6131     }
   6132 
   6133     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
   6134         int N = ws.size();
   6135         for (int i=0; i<N; i++) {
   6136             final int uid = mapUid(ws.get(i));
   6137             noteFullWifiLockReleasedLocked(uid);
   6138             StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
   6139                     StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
   6140         }
   6141 
   6142         final List<WorkChain> workChains = ws.getWorkChains();
   6143         if (workChains != null) {
   6144             for (int i = 0; i < workChains.size(); ++i) {
   6145                 final WorkChain workChain = workChains.get(i);
   6146                 final int uid = mapUid(workChain.getAttributionUid());
   6147                 noteFullWifiLockReleasedLocked(uid);
   6148                 StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
   6149                         workChain.getUids(), workChain.getTags(),
   6150                         StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
   6151             }
   6152         }
   6153     }
   6154 
   6155     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
   6156         int N = ws.size();
   6157         for (int i=0; i<N; i++) {
   6158             final int uid = mapUid(ws.get(i));
   6159             noteWifiScanStartedLocked(uid);
   6160             StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i),
   6161                     StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON);
   6162         }
   6163 
   6164         final List<WorkChain> workChains = ws.getWorkChains();
   6165         if (workChains != null) {
   6166             for (int i = 0; i < workChains.size(); ++i) {
   6167                 final WorkChain workChain = workChains.get(i);
   6168                 final int uid = mapUid(workChain.getAttributionUid());
   6169                 noteWifiScanStartedLocked(uid);
   6170                 StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED, workChain.getUids(),
   6171                         workChain.getTags(), StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON);
   6172             }
   6173         }
   6174     }
   6175 
   6176     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
   6177         int N = ws.size();
   6178         for (int i=0; i<N; i++) {
   6179             final int uid = mapUid(ws.get(i));
   6180             noteWifiScanStoppedLocked(uid);
   6181             StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i),
   6182                     StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF);
   6183         }
   6184 
   6185         final List<WorkChain> workChains = ws.getWorkChains();
   6186         if (workChains != null) {
   6187             for (int i = 0; i < workChains.size(); ++i) {
   6188                 final WorkChain workChain = workChains.get(i);
   6189                 final int uid = mapUid(workChain.getAttributionUid());
   6190                 noteWifiScanStoppedLocked(uid);
   6191                 StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED,
   6192                         workChain.getUids(), workChain.getTags(),
   6193                         StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF);
   6194             }
   6195         }
   6196     }
   6197 
   6198     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
   6199         int N = ws.size();
   6200         for (int i=0; i<N; i++) {
   6201             noteWifiBatchedScanStartedLocked(ws.get(i), csph);
   6202         }
   6203 
   6204         final List<WorkChain> workChains = ws.getWorkChains();
   6205         if (workChains != null) {
   6206             for (int i = 0; i < workChains.size(); ++i) {
   6207                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph);
   6208             }
   6209         }
   6210     }
   6211 
   6212     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
   6213         int N = ws.size();
   6214         for (int i=0; i<N; i++) {
   6215             noteWifiBatchedScanStoppedLocked(ws.get(i));
   6216         }
   6217 
   6218         final List<WorkChain> workChains = ws.getWorkChains();
   6219         if (workChains != null) {
   6220             for (int i = 0; i < workChains.size(); ++i) {
   6221                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid());
   6222             }
   6223         }
   6224     }
   6225 
   6226     private static String[] includeInStringArray(String[] array, String str) {
   6227         if (ArrayUtils.indexOf(array, str) >= 0) {
   6228             return array;
   6229         }
   6230         String[] newArray = new String[array.length+1];
   6231         System.arraycopy(array, 0, newArray, 0, array.length);
   6232         newArray[array.length] = str;
   6233         return newArray;
   6234     }
   6235 
   6236     private static String[] excludeFromStringArray(String[] array, String str) {
   6237         int index = ArrayUtils.indexOf(array, str);
   6238         if (index >= 0) {
   6239             String[] newArray = new String[array.length-1];
   6240             if (index > 0) {
   6241                 System.arraycopy(array, 0, newArray, 0, index);
   6242             }
   6243             if (index < array.length-1) {
   6244                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
   6245             }
   6246             return newArray;
   6247         }
   6248         return array;
   6249     }
   6250 
   6251     public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
   6252         if (TextUtils.isEmpty(iface)) return;
   6253 
   6254         synchronized (mModemNetworkLock) {
   6255             if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
   6256                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
   6257                 if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
   6258             } else {
   6259                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
   6260                 if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
   6261             }
   6262         }
   6263 
   6264         synchronized (mWifiNetworkLock) {
   6265             if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
   6266                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
   6267                 if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
   6268             } else {
   6269                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
   6270                 if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
   6271             }
   6272         }
   6273     }
   6274 
   6275     public String[] getWifiIfaces() {
   6276         synchronized (mWifiNetworkLock) {
   6277             return mWifiIfaces;
   6278         }
   6279     }
   6280 
   6281     public String[] getMobileIfaces() {
   6282         synchronized (mModemNetworkLock) {
   6283             return mModemIfaces;
   6284         }
   6285     }
   6286 
   6287     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
   6288         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6289     }
   6290 
   6291     @Override public int getScreenOnCount(int which) {
   6292         return mScreenOnTimer.getCountLocked(which);
   6293     }
   6294 
   6295     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
   6296         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6297     }
   6298 
   6299     @Override public int getScreenDozeCount(int which) {
   6300         return mScreenDozeTimer.getCountLocked(which);
   6301     }
   6302 
   6303     @Override public long getScreenBrightnessTime(int brightnessBin,
   6304             long elapsedRealtimeUs, int which) {
   6305         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
   6306                 elapsedRealtimeUs, which);
   6307     }
   6308 
   6309     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
   6310         return mScreenBrightnessTimer[brightnessBin];
   6311     }
   6312 
   6313     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
   6314         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6315     }
   6316 
   6317     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
   6318         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6319     }
   6320 
   6321     @Override public int getPowerSaveModeEnabledCount(int which) {
   6322         return mPowerSaveModeEnabledTimer.getCountLocked(which);
   6323     }
   6324 
   6325     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
   6326             int which) {
   6327         switch (mode) {
   6328             case DEVICE_IDLE_MODE_LIGHT:
   6329                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6330             case DEVICE_IDLE_MODE_DEEP:
   6331                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6332         }
   6333         return 0;
   6334     }
   6335 
   6336     @Override public int getDeviceIdleModeCount(int mode, int which) {
   6337         switch (mode) {
   6338             case DEVICE_IDLE_MODE_LIGHT:
   6339                 return mDeviceIdleModeLightTimer.getCountLocked(which);
   6340             case DEVICE_IDLE_MODE_DEEP:
   6341                 return mDeviceIdleModeFullTimer.getCountLocked(which);
   6342         }
   6343         return 0;
   6344     }
   6345 
   6346     @Override public long getLongestDeviceIdleModeTime(int mode) {
   6347         switch (mode) {
   6348             case DEVICE_IDLE_MODE_LIGHT:
   6349                 return mLongestLightIdleTime;
   6350             case DEVICE_IDLE_MODE_DEEP:
   6351                 return mLongestFullIdleTime;
   6352         }
   6353         return 0;
   6354     }
   6355 
   6356     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
   6357         switch (mode) {
   6358             case DEVICE_IDLE_MODE_LIGHT:
   6359                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6360             case DEVICE_IDLE_MODE_DEEP:
   6361                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6362         }
   6363         return 0;
   6364     }
   6365 
   6366     @Override public int getDeviceIdlingCount(int mode, int which) {
   6367         switch (mode) {
   6368             case DEVICE_IDLE_MODE_LIGHT:
   6369                 return mDeviceLightIdlingTimer.getCountLocked(which);
   6370             case DEVICE_IDLE_MODE_DEEP:
   6371                 return mDeviceIdlingTimer.getCountLocked(which);
   6372         }
   6373         return 0;
   6374     }
   6375 
   6376     @Override public int getNumConnectivityChange(int which) {
   6377         int val = mNumConnectivityChange;
   6378         if (which == STATS_CURRENT) {
   6379             val -= mLoadedNumConnectivityChange;
   6380         } else if (which == STATS_SINCE_UNPLUGGED) {
   6381             val -= mUnpluggedNumConnectivityChange;
   6382         }
   6383         return val;
   6384     }
   6385 
   6386     @Override public long getGpsSignalQualityTime(int strengthBin,
   6387         long elapsedRealtimeUs, int which) {
   6388         if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
   6389             return 0;
   6390         }
   6391         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
   6392             elapsedRealtimeUs, which);
   6393     }
   6394 
   6395     @Override public long getGpsBatteryDrainMaMs() {
   6396         final double opVolt = mPowerProfile.getAveragePower(
   6397             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
   6398         if (opVolt == 0) {
   6399             return 0;
   6400         }
   6401         double energyUsedMaMs = 0.0;
   6402         final int which = STATS_SINCE_CHARGED;
   6403         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
   6404         for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
   6405             energyUsedMaMs
   6406                 += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
   6407                 * (getGpsSignalQualityTime(i, rawRealtime, which) / 1000);
   6408         }
   6409         return (long) energyUsedMaMs;
   6410     }
   6411 
   6412     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
   6413         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6414     }
   6415 
   6416     @Override public int getPhoneOnCount(int which) {
   6417         return mPhoneOnTimer.getCountLocked(which);
   6418     }
   6419 
   6420     @Override public long getPhoneSignalStrengthTime(int strengthBin,
   6421             long elapsedRealtimeUs, int which) {
   6422         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
   6423                 elapsedRealtimeUs, which);
   6424     }
   6425 
   6426     @Override public long getPhoneSignalScanningTime(
   6427             long elapsedRealtimeUs, int which) {
   6428         return mPhoneSignalScanningTimer.getTotalTimeLocked(
   6429                 elapsedRealtimeUs, which);
   6430     }
   6431 
   6432     @Override public Timer getPhoneSignalScanningTimer() {
   6433         return mPhoneSignalScanningTimer;
   6434     }
   6435 
   6436     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
   6437         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
   6438     }
   6439 
   6440     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
   6441         return mPhoneSignalStrengthsTimer[strengthBin];
   6442     }
   6443 
   6444     @Override public long getPhoneDataConnectionTime(int dataType,
   6445             long elapsedRealtimeUs, int which) {
   6446         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
   6447                 elapsedRealtimeUs, which);
   6448     }
   6449 
   6450     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
   6451         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
   6452     }
   6453 
   6454     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
   6455         return mPhoneDataConnectionsTimer[dataType];
   6456     }
   6457 
   6458     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
   6459         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6460     }
   6461 
   6462     @Override public int getMobileRadioActiveCount(int which) {
   6463         return mMobileRadioActiveTimer.getCountLocked(which);
   6464     }
   6465 
   6466     @Override public long getMobileRadioActiveAdjustedTime(int which) {
   6467         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
   6468     }
   6469 
   6470     @Override public long getMobileRadioActiveUnknownTime(int which) {
   6471         return mMobileRadioActiveUnknownTime.getCountLocked(which);
   6472     }
   6473 
   6474     @Override public int getMobileRadioActiveUnknownCount(int which) {
   6475         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
   6476     }
   6477 
   6478     @Override public long getWifiMulticastWakelockTime(
   6479             long elapsedRealtimeUs, int which) {
   6480         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
   6481                 elapsedRealtimeUs, which);
   6482     }
   6483 
   6484     @Override public int getWifiMulticastWakelockCount(int which) {
   6485         return mWifiMulticastWakelockTimer.getCountLocked(which);
   6486     }
   6487 
   6488     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
   6489         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6490     }
   6491 
   6492     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
   6493         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6494     }
   6495 
   6496     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
   6497         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6498     }
   6499 
   6500     @Override public long getWifiStateTime(int wifiState,
   6501             long elapsedRealtimeUs, int which) {
   6502         return mWifiStateTimer[wifiState].getTotalTimeLocked(
   6503                 elapsedRealtimeUs, which);
   6504     }
   6505 
   6506     @Override public int getWifiStateCount(int wifiState, int which) {
   6507         return mWifiStateTimer[wifiState].getCountLocked(which);
   6508     }
   6509 
   6510     @Override public Timer getWifiStateTimer(int wifiState) {
   6511         return mWifiStateTimer[wifiState];
   6512     }
   6513 
   6514     @Override public long getWifiSupplStateTime(int state,
   6515             long elapsedRealtimeUs, int which) {
   6516         return mWifiSupplStateTimer[state].getTotalTimeLocked(
   6517                 elapsedRealtimeUs, which);
   6518     }
   6519 
   6520     @Override public int getWifiSupplStateCount(int state, int which) {
   6521         return mWifiSupplStateTimer[state].getCountLocked(which);
   6522     }
   6523 
   6524     @Override public Timer getWifiSupplStateTimer(int state) {
   6525         return mWifiSupplStateTimer[state];
   6526     }
   6527 
   6528     @Override public long getWifiSignalStrengthTime(int strengthBin,
   6529             long elapsedRealtimeUs, int which) {
   6530         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
   6531                 elapsedRealtimeUs, which);
   6532     }
   6533 
   6534     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
   6535         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
   6536     }
   6537 
   6538     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
   6539         return mWifiSignalStrengthsTimer[strengthBin];
   6540     }
   6541 
   6542     @Override
   6543     public ControllerActivityCounter getBluetoothControllerActivity() {
   6544         return mBluetoothActivity;
   6545     }
   6546 
   6547     @Override
   6548     public ControllerActivityCounter getWifiControllerActivity() {
   6549         return mWifiActivity;
   6550     }
   6551 
   6552     @Override
   6553     public ControllerActivityCounter getModemControllerActivity() {
   6554         return mModemActivity;
   6555     }
   6556 
   6557     @Override
   6558     public boolean hasBluetoothActivityReporting() {
   6559         return mHasBluetoothReporting;
   6560     }
   6561 
   6562     @Override
   6563     public boolean hasWifiActivityReporting() {
   6564         return mHasWifiReporting;
   6565     }
   6566 
   6567     @Override
   6568     public boolean hasModemActivityReporting() {
   6569         return mHasModemReporting;
   6570     }
   6571 
   6572     @Override
   6573     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
   6574         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6575     }
   6576 
   6577     @Override
   6578     public long getFlashlightOnCount(int which) {
   6579         return mFlashlightOnTimer.getCountLocked(which);
   6580     }
   6581 
   6582     @Override
   6583     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
   6584         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6585     }
   6586 
   6587     @Override
   6588     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
   6589         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   6590     }
   6591 
   6592     @Override
   6593     public long getNetworkActivityBytes(int type, int which) {
   6594         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
   6595             return mNetworkByteActivityCounters[type].getCountLocked(which);
   6596         } else {
   6597             return 0;
   6598         }
   6599     }
   6600 
   6601     @Override
   6602     public long getNetworkActivityPackets(int type, int which) {
   6603         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
   6604             return mNetworkPacketActivityCounters[type].getCountLocked(which);
   6605         } else {
   6606             return 0;
   6607         }
   6608     }
   6609 
   6610     @Override public long getStartClockTime() {
   6611         final long currentTime = System.currentTimeMillis();
   6612         if (ensureStartClockTime(currentTime)) {
   6613             recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
   6614                     mClocks.uptimeMillis());
   6615         }
   6616         return mStartClockTime;
   6617     }
   6618 
   6619     @Override public String getStartPlatformVersion() {
   6620         return mStartPlatformVersion;
   6621     }
   6622 
   6623     @Override public String getEndPlatformVersion() {
   6624         return mEndPlatformVersion;
   6625     }
   6626 
   6627     @Override public int getParcelVersion() {
   6628         return VERSION;
   6629     }
   6630 
   6631     @Override public boolean getIsOnBattery() {
   6632         return mOnBattery;
   6633     }
   6634 
   6635     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
   6636         return mUidStats;
   6637     }
   6638 
   6639     private static void detachTimerIfNotNull(BatteryStatsImpl.Timer timer) {
   6640         if (timer != null) {
   6641             timer.detach();
   6642         }
   6643     }
   6644 
   6645     private static boolean resetTimerIfNotNull(BatteryStatsImpl.Timer timer,
   6646             boolean detachIfReset) {
   6647         if (timer != null) {
   6648             return timer.reset(detachIfReset);
   6649         }
   6650         return true;
   6651     }
   6652 
   6653     private static boolean resetTimerIfNotNull(DualTimer timer, boolean detachIfReset) {
   6654         if (timer != null) {
   6655             return timer.reset(detachIfReset);
   6656         }
   6657         return true;
   6658     }
   6659 
   6660     private static void detachLongCounterIfNotNull(LongSamplingCounter counter) {
   6661         if (counter != null) {
   6662             counter.detach();
   6663         }
   6664     }
   6665 
   6666     private static void resetLongCounterIfNotNull(LongSamplingCounter counter,
   6667             boolean detachIfReset) {
   6668         if (counter != null) {
   6669             counter.reset(detachIfReset);
   6670         }
   6671     }
   6672 
   6673     /**
   6674      * The statistics associated with a particular uid.
   6675      */
   6676     public static class Uid extends BatteryStats.Uid {
   6677         /**
   6678          * BatteryStatsImpl that we are associated with.
   6679          */
   6680         protected BatteryStatsImpl mBsi;
   6681 
   6682         final int mUid;
   6683 
   6684         /** TimeBase for when uid is in background and device is on battery. */
   6685         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
   6686         public final TimeBase mOnBatteryBackgroundTimeBase;
   6687         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
   6688         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
   6689 
   6690         boolean mWifiRunning;
   6691         StopwatchTimer mWifiRunningTimer;
   6692 
   6693         boolean mFullWifiLockOut;
   6694         StopwatchTimer mFullWifiLockTimer;
   6695 
   6696         boolean mWifiScanStarted;
   6697         DualTimer mWifiScanTimer;
   6698 
   6699         static final int NO_BATCHED_SCAN_STARTED = -1;
   6700         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
   6701         StopwatchTimer[] mWifiBatchedScanTimer;
   6702 
   6703         boolean mWifiMulticastEnabled;
   6704         StopwatchTimer mWifiMulticastTimer;
   6705 
   6706         StopwatchTimer mAudioTurnedOnTimer;
   6707         StopwatchTimer mVideoTurnedOnTimer;
   6708         StopwatchTimer mFlashlightTurnedOnTimer;
   6709         StopwatchTimer mCameraTurnedOnTimer;
   6710         StopwatchTimer mForegroundActivityTimer;
   6711         StopwatchTimer mForegroundServiceTimer;
   6712         /** Total time spent by the uid holding any partial wakelocks. */
   6713         DualTimer mAggregatedPartialWakelockTimer;
   6714         DualTimer mBluetoothScanTimer;
   6715         DualTimer mBluetoothUnoptimizedScanTimer;
   6716         Counter mBluetoothScanResultCounter;
   6717         Counter mBluetoothScanResultBgCounter;
   6718 
   6719         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
   6720         StopwatchTimer[] mProcessStateTimer;
   6721 
   6722         boolean mInForegroundService = false;
   6723 
   6724         BatchTimer mVibratorOnTimer;
   6725 
   6726         Counter[] mUserActivityCounters;
   6727 
   6728         LongSamplingCounter[] mNetworkByteActivityCounters;
   6729         LongSamplingCounter[] mNetworkPacketActivityCounters;
   6730         LongSamplingCounter mMobileRadioActiveTime;
   6731         LongSamplingCounter mMobileRadioActiveCount;
   6732 
   6733         /**
   6734          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
   6735          */
   6736         private LongSamplingCounter mMobileRadioApWakeupCount;
   6737 
   6738         /**
   6739          * How many times this UID woke up the Application Processor due to a Wifi packet.
   6740          */
   6741         private LongSamplingCounter mWifiRadioApWakeupCount;
   6742 
   6743         /**
   6744          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
   6745          * Can be null if the UID has had no such activity.
   6746          */
   6747         private ControllerActivityCounterImpl mWifiControllerActivity;
   6748 
   6749         /**
   6750          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
   6751          * Can be null if the UID has had no such activity.
   6752          */
   6753         private ControllerActivityCounterImpl mBluetoothControllerActivity;
   6754 
   6755         /**
   6756          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
   6757          * Can be null if the UID has had no such activity.
   6758          */
   6759         private ControllerActivityCounterImpl mModemControllerActivity;
   6760 
   6761         /**
   6762          * The CPU times we had at the last history details update.
   6763          */
   6764         long mLastStepUserTime;
   6765         long mLastStepSystemTime;
   6766         long mCurStepUserTime;
   6767         long mCurStepSystemTime;
   6768 
   6769         LongSamplingCounter mUserCpuTime;
   6770         LongSamplingCounter mSystemCpuTime;
   6771         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
   6772         LongSamplingCounter mCpuActiveTimeMs;
   6773 
   6774         LongSamplingCounterArray mCpuFreqTimeMs;
   6775         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
   6776         LongSamplingCounterArray mCpuClusterTimesMs;
   6777 
   6778         LongSamplingCounterArray[] mProcStateTimeMs;
   6779         LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
   6780 
   6781         IntArray mChildUids;
   6782 
   6783         /**
   6784          * The statistics we have collected for this uid's wake locks.
   6785          */
   6786         final OverflowArrayMap<Wakelock> mWakelockStats;
   6787 
   6788         /**
   6789          * The statistics we have collected for this uid's syncs.
   6790          */
   6791         final OverflowArrayMap<DualTimer> mSyncStats;
   6792 
   6793         /**
   6794          * The statistics we have collected for this uid's jobs.
   6795          */
   6796         final OverflowArrayMap<DualTimer> mJobStats;
   6797 
   6798         /**
   6799          * Count of the jobs that have completed and the reasons why they completed.
   6800          */
   6801         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
   6802 
   6803         /**
   6804          * Count of app launch events that had associated deferred job counts or info about
   6805          * last time a job was run.
   6806          */
   6807         Counter mJobsDeferredEventCount;
   6808 
   6809         /**
   6810          * Count of deferred jobs that were pending when the app was launched or brought to
   6811          * the foreground through a user interaction.
   6812          */
   6813         Counter mJobsDeferredCount;
   6814 
   6815         /**
   6816          * Sum of time since the last time a job was run for this app before it was launched.
   6817          */
   6818         LongSamplingCounter mJobsFreshnessTimeMs;
   6819 
   6820         /**
   6821          * Array of counts of instances where the time since the last job was run for the app
   6822          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
   6823          */
   6824         final Counter[] mJobsFreshnessBuckets;
   6825 
   6826         /**
   6827          * The statistics we have collected for this uid's sensor activations.
   6828          */
   6829         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
   6830 
   6831         /**
   6832          * The statistics we have collected for this uid's processes.
   6833          */
   6834         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
   6835 
   6836         /**
   6837          * The statistics we have collected for this uid's processes.
   6838          */
   6839         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
   6840 
   6841         /**
   6842          * The transient wake stats we have collected for this uid's pids.
   6843          */
   6844         final SparseArray<Pid> mPids = new SparseArray<>();
   6845 
   6846         public Uid(BatteryStatsImpl bsi, int uid) {
   6847             mBsi = bsi;
   6848             mUid = uid;
   6849 
   6850             mOnBatteryBackgroundTimeBase = new TimeBase();
   6851             mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
   6852                     mBsi.mClocks.elapsedRealtime() * 1000);
   6853 
   6854             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase();
   6855             mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
   6856                     mBsi.mClocks.elapsedRealtime() * 1000);
   6857 
   6858             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   6859             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   6860             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   6861             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
   6862 
   6863             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
   6864                 @Override public Wakelock instantiateObject() {
   6865                     return new Wakelock(mBsi, Uid.this);
   6866                 }
   6867             };
   6868             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
   6869                 @Override public DualTimer instantiateObject() {
   6870                     return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
   6871                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
   6872                 }
   6873             };
   6874             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
   6875                 @Override public DualTimer instantiateObject() {
   6876                     return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
   6877                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
   6878                 }
   6879             };
   6880 
   6881             mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
   6882                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
   6883             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
   6884                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
   6885             mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
   6886                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
   6887             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
   6888             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
   6889                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
   6890             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
   6891             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
   6892             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
   6893             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   6894             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
   6895         }
   6896 
   6897         @VisibleForTesting
   6898         public void setProcessStateForTest(int procState) {
   6899             mProcessState = procState;
   6900         }
   6901 
   6902         @Override
   6903         public long[] getCpuFreqTimes(int which) {
   6904             return nullIfAllZeros(mCpuFreqTimeMs, which);
   6905         }
   6906 
   6907         @Override
   6908         public long[] getScreenOffCpuFreqTimes(int which) {
   6909             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
   6910         }
   6911 
   6912         @Override
   6913         public long getCpuActiveTime() {
   6914             return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
   6915         }
   6916 
   6917         @Override
   6918         public long[] getCpuClusterTimes() {
   6919             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
   6920         }
   6921 
   6922 
   6923         @Override
   6924         public long[] getCpuFreqTimes(int which, int procState) {
   6925             if (which < 0 || which >= NUM_PROCESS_STATE) {
   6926                 return null;
   6927             }
   6928             if (mProcStateTimeMs == null) {
   6929                 return null;
   6930             }
   6931             if (!mBsi.mPerProcStateCpuTimesAvailable) {
   6932                 mProcStateTimeMs = null;
   6933                 return null;
   6934             }
   6935             return nullIfAllZeros(mProcStateTimeMs[procState], which);
   6936         }
   6937 
   6938         @Override
   6939         public long[] getScreenOffCpuFreqTimes(int which, int procState) {
   6940             if (which < 0 || which >= NUM_PROCESS_STATE) {
   6941                 return null;
   6942             }
   6943             if (mProcStateScreenOffTimeMs == null) {
   6944                 return null;
   6945             }
   6946             if (!mBsi.mPerProcStateCpuTimesAvailable) {
   6947                 mProcStateScreenOffTimeMs = null;
   6948                 return null;
   6949             }
   6950             return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which);
   6951         }
   6952 
   6953         public void addIsolatedUid(int isolatedUid) {
   6954             if (mChildUids == null) {
   6955                 mChildUids = new IntArray();
   6956             } else if (mChildUids.indexOf(isolatedUid) >= 0) {
   6957                 return;
   6958             }
   6959             mChildUids.add(isolatedUid);
   6960         }
   6961 
   6962         public void removeIsolatedUid(int isolatedUid) {
   6963             final int idx = mChildUids == null ? -1 : mChildUids.indexOf(isolatedUid);
   6964             if (idx < 0) {
   6965                 return;
   6966             }
   6967             mChildUids.remove(idx);
   6968         }
   6969 
   6970         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
   6971             if (cpuTimesMs == null) {
   6972                 return null;
   6973             }
   6974             final long[] counts = cpuTimesMs.getCountsLocked(which);
   6975             if (counts == null) {
   6976                 return null;
   6977             }
   6978             // Return counts only if at least one of the elements is non-zero.
   6979             for (int i = counts.length - 1; i >= 0; --i) {
   6980                 if (counts[i] != 0) {
   6981                     return counts;
   6982                 }
   6983             }
   6984             return null;
   6985         }
   6986 
   6987         private void addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery) {
   6988             if (mProcStateTimeMs == null) {
   6989                 mProcStateTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
   6990             }
   6991             if (mProcStateTimeMs[procState] == null
   6992                     || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
   6993                 mProcStateTimeMs[procState] = new LongSamplingCounterArray(
   6994                         mBsi.mOnBatteryTimeBase);
   6995             }
   6996             mProcStateTimeMs[procState].addCountLocked(cpuTimesMs, onBattery);
   6997         }
   6998 
   6999         private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs,
   7000                 boolean onBatteryScreenOff) {
   7001             if (mProcStateScreenOffTimeMs == null) {
   7002                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
   7003             }
   7004             if (mProcStateScreenOffTimeMs[procState] == null
   7005                     || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) {
   7006                 mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
   7007                         mBsi.mOnBatteryScreenOffTimeBase);
   7008             }
   7009             mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs, onBatteryScreenOff);
   7010         }
   7011 
   7012         @Override
   7013         public Timer getAggregatedPartialWakelockTimer() {
   7014             return mAggregatedPartialWakelockTimer;
   7015         }
   7016 
   7017         @Override
   7018         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
   7019             return mWakelockStats.getMap();
   7020         }
   7021 
   7022         @Override
   7023         public Timer getMulticastWakelockStats() {
   7024             return mWifiMulticastTimer;
   7025         }
   7026 
   7027         @Override
   7028         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
   7029             return mSyncStats.getMap();
   7030         }
   7031 
   7032         @Override
   7033         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
   7034             return mJobStats.getMap();
   7035         }
   7036 
   7037         @Override
   7038         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
   7039             return mJobCompletions;
   7040         }
   7041 
   7042         @Override
   7043         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
   7044             return mSensorStats;
   7045         }
   7046 
   7047         @Override
   7048         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
   7049             return mProcessStats;
   7050         }
   7051 
   7052         @Override
   7053         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
   7054             return mPackageStats;
   7055         }
   7056 
   7057         @Override
   7058         public int getUid() {
   7059             return mUid;
   7060         }
   7061 
   7062         @Override
   7063         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
   7064             if (!mWifiRunning) {
   7065                 mWifiRunning = true;
   7066                 if (mWifiRunningTimer == null) {
   7067                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
   7068                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
   7069                 }
   7070                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
   7071             }
   7072         }
   7073 
   7074         @Override
   7075         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
   7076             if (mWifiRunning) {
   7077                 mWifiRunning = false;
   7078                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
   7079             }
   7080         }
   7081 
   7082         @Override
   7083         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
   7084             if (!mFullWifiLockOut) {
   7085                 mFullWifiLockOut = true;
   7086                 if (mFullWifiLockTimer == null) {
   7087                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
   7088                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
   7089                 }
   7090                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
   7091             }
   7092         }
   7093 
   7094         @Override
   7095         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
   7096             if (mFullWifiLockOut) {
   7097                 mFullWifiLockOut = false;
   7098                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
   7099             }
   7100         }
   7101 
   7102         @Override
   7103         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
   7104             if (!mWifiScanStarted) {
   7105                 mWifiScanStarted = true;
   7106                 if (mWifiScanTimer == null) {
   7107                     mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
   7108                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
   7109                             mOnBatteryBackgroundTimeBase);
   7110                 }
   7111                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
   7112             }
   7113         }
   7114 
   7115         @Override
   7116         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
   7117             if (mWifiScanStarted) {
   7118                 mWifiScanStarted = false;
   7119                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
   7120             }
   7121         }
   7122 
   7123         @Override
   7124         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
   7125             int bin = 0;
   7126             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
   7127                 csph = csph >> 3;
   7128                 bin++;
   7129             }
   7130 
   7131             if (mWifiBatchedScanBinStarted == bin) return;
   7132 
   7133             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
   7134                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
   7135                         stopRunningLocked(elapsedRealtimeMs);
   7136             }
   7137             mWifiBatchedScanBinStarted = bin;
   7138             if (mWifiBatchedScanTimer[bin] == null) {
   7139                 makeWifiBatchedScanBin(bin, null);
   7140             }
   7141             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
   7142         }
   7143 
   7144         @Override
   7145         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
   7146             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
   7147                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
   7148                         stopRunningLocked(elapsedRealtimeMs);
   7149                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
   7150             }
   7151         }
   7152 
   7153         @Override
   7154         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
   7155             if (!mWifiMulticastEnabled) {
   7156                 mWifiMulticastEnabled = true;
   7157                 if (mWifiMulticastTimer == null) {
   7158                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   7159                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
   7160                 }
   7161                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
   7162                 StatsLog.write_non_chained(
   7163                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null,
   7164                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__ON);
   7165             }
   7166         }
   7167 
   7168         @Override
   7169         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
   7170             if (mWifiMulticastEnabled) {
   7171                 mWifiMulticastEnabled = false;
   7172                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
   7173                 StatsLog.write_non_chained(
   7174                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null,
   7175                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__OFF);
   7176             }
   7177         }
   7178 
   7179         @Override
   7180         public ControllerActivityCounter getWifiControllerActivity() {
   7181             return mWifiControllerActivity;
   7182         }
   7183 
   7184         @Override
   7185         public ControllerActivityCounter getBluetoothControllerActivity() {
   7186             return mBluetoothControllerActivity;
   7187         }
   7188 
   7189         @Override
   7190         public ControllerActivityCounter getModemControllerActivity() {
   7191             return mModemControllerActivity;
   7192         }
   7193 
   7194         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
   7195             if (mWifiControllerActivity == null) {
   7196                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   7197                         NUM_BT_TX_LEVELS);
   7198             }
   7199             return mWifiControllerActivity;
   7200         }
   7201 
   7202         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
   7203             if (mBluetoothControllerActivity == null) {
   7204                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   7205                         NUM_BT_TX_LEVELS);
   7206             }
   7207             return mBluetoothControllerActivity;
   7208         }
   7209 
   7210         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
   7211             if (mModemControllerActivity == null) {
   7212                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   7213                         ModemActivityInfo.TX_POWER_LEVELS);
   7214             }
   7215             return mModemControllerActivity;
   7216         }
   7217 
   7218         public StopwatchTimer createAudioTurnedOnTimerLocked() {
   7219             if (mAudioTurnedOnTimer == null) {
   7220                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
   7221                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
   7222             }
   7223             return mAudioTurnedOnTimer;
   7224         }
   7225 
   7226         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
   7227             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
   7228         }
   7229 
   7230         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
   7231             if (mAudioTurnedOnTimer != null) {
   7232                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
   7233             }
   7234         }
   7235 
   7236         public void noteResetAudioLocked(long elapsedRealtimeMs) {
   7237             if (mAudioTurnedOnTimer != null) {
   7238                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
   7239             }
   7240         }
   7241 
   7242         public StopwatchTimer createVideoTurnedOnTimerLocked() {
   7243             if (mVideoTurnedOnTimer == null) {
   7244                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
   7245                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
   7246             }
   7247             return mVideoTurnedOnTimer;
   7248         }
   7249 
   7250         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
   7251             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
   7252         }
   7253 
   7254         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
   7255             if (mVideoTurnedOnTimer != null) {
   7256                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
   7257             }
   7258         }
   7259 
   7260         public void noteResetVideoLocked(long elapsedRealtimeMs) {
   7261             if (mVideoTurnedOnTimer != null) {
   7262                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
   7263             }
   7264         }
   7265 
   7266         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
   7267             if (mFlashlightTurnedOnTimer == null) {
   7268                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   7269                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
   7270             }
   7271             return mFlashlightTurnedOnTimer;
   7272         }
   7273 
   7274         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
   7275             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
   7276         }
   7277 
   7278         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
   7279             if (mFlashlightTurnedOnTimer != null) {
   7280                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
   7281             }
   7282         }
   7283 
   7284         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
   7285             if (mFlashlightTurnedOnTimer != null) {
   7286                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
   7287             }
   7288         }
   7289 
   7290         public StopwatchTimer createCameraTurnedOnTimerLocked() {
   7291             if (mCameraTurnedOnTimer == null) {
   7292                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
   7293                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
   7294             }
   7295             return mCameraTurnedOnTimer;
   7296         }
   7297 
   7298         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
   7299             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
   7300         }
   7301 
   7302         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
   7303             if (mCameraTurnedOnTimer != null) {
   7304                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
   7305             }
   7306         }
   7307 
   7308         public void noteResetCameraLocked(long elapsedRealtimeMs) {
   7309             if (mCameraTurnedOnTimer != null) {
   7310                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
   7311             }
   7312         }
   7313 
   7314         public StopwatchTimer createForegroundActivityTimerLocked() {
   7315             if (mForegroundActivityTimer == null) {
   7316                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   7317                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
   7318             }
   7319             return mForegroundActivityTimer;
   7320         }
   7321 
   7322         public StopwatchTimer createForegroundServiceTimerLocked() {
   7323             if (mForegroundServiceTimer == null) {
   7324                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   7325                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
   7326             }
   7327             return mForegroundServiceTimer;
   7328         }
   7329 
   7330         public DualTimer createAggregatedPartialWakelockTimerLocked() {
   7331             if (mAggregatedPartialWakelockTimer == null) {
   7332                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
   7333                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
   7334                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
   7335             }
   7336             return mAggregatedPartialWakelockTimer;
   7337         }
   7338 
   7339         public DualTimer createBluetoothScanTimerLocked() {
   7340             if (mBluetoothScanTimer == null) {
   7341                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
   7342                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
   7343                         mOnBatteryBackgroundTimeBase);
   7344             }
   7345             return mBluetoothScanTimer;
   7346         }
   7347 
   7348         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
   7349             if (mBluetoothUnoptimizedScanTimer == null) {
   7350                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
   7351                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
   7352                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
   7353             }
   7354             return mBluetoothUnoptimizedScanTimer;
   7355         }
   7356 
   7357         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
   7358                 boolean isUnoptimized) {
   7359             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
   7360             if (isUnoptimized) {
   7361                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
   7362             }
   7363         }
   7364 
   7365         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
   7366             if (mBluetoothScanTimer != null) {
   7367                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
   7368             }
   7369             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
   7370                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
   7371             }
   7372         }
   7373 
   7374         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
   7375             if (mBluetoothScanTimer != null) {
   7376                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
   7377             }
   7378             if (mBluetoothUnoptimizedScanTimer != null) {
   7379                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
   7380             }
   7381         }
   7382 
   7383         public Counter createBluetoothScanResultCounterLocked() {
   7384             if (mBluetoothScanResultCounter == null) {
   7385                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
   7386             }
   7387             return mBluetoothScanResultCounter;
   7388         }
   7389 
   7390         public Counter createBluetoothScanResultBgCounterLocked() {
   7391             if (mBluetoothScanResultBgCounter == null) {
   7392                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
   7393             }
   7394             return mBluetoothScanResultBgCounter;
   7395         }
   7396 
   7397         public void noteBluetoothScanResultsLocked(int numNewResults) {
   7398             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
   7399             // Uses background timebase, so the count will only be incremented if uid in background.
   7400             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
   7401         }
   7402 
   7403         @Override
   7404         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
   7405             // We always start, since we want multiple foreground PIDs to nest
   7406             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
   7407         }
   7408 
   7409         @Override
   7410         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
   7411             if (mForegroundActivityTimer != null) {
   7412                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
   7413             }
   7414         }
   7415 
   7416         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
   7417             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
   7418         }
   7419 
   7420         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
   7421             if (mForegroundServiceTimer != null) {
   7422                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
   7423             }
   7424         }
   7425 
   7426         public BatchTimer createVibratorOnTimerLocked() {
   7427             if (mVibratorOnTimer == null) {
   7428                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
   7429                         mBsi.mOnBatteryTimeBase);
   7430             }
   7431             return mVibratorOnTimer;
   7432         }
   7433 
   7434         public void noteVibratorOnLocked(long durationMillis) {
   7435             createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
   7436         }
   7437 
   7438         public void noteVibratorOffLocked() {
   7439             if (mVibratorOnTimer != null) {
   7440                 mVibratorOnTimer.abortLastDuration(mBsi);
   7441             }
   7442         }
   7443 
   7444         @Override
   7445         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
   7446             if (mWifiRunningTimer == null) {
   7447                 return 0;
   7448             }
   7449             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   7450         }
   7451 
   7452         @Override
   7453         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
   7454             if (mFullWifiLockTimer == null) {
   7455                 return 0;
   7456             }
   7457             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   7458         }
   7459 
   7460         @Override
   7461         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
   7462             if (mWifiScanTimer == null) {
   7463                 return 0;
   7464             }
   7465             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   7466         }
   7467 
   7468         @Override
   7469         public int getWifiScanCount(int which) {
   7470             if (mWifiScanTimer == null) {
   7471                 return 0;
   7472             }
   7473             return mWifiScanTimer.getCountLocked(which);
   7474         }
   7475 
   7476         @Override
   7477         public Timer getWifiScanTimer() {
   7478             return mWifiScanTimer;
   7479         }
   7480 
   7481         @Override
   7482         public int getWifiScanBackgroundCount(int which) {
   7483             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
   7484                 return 0;
   7485             }
   7486             return mWifiScanTimer.getSubTimer().getCountLocked(which);
   7487         }
   7488 
   7489         @Override
   7490         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
   7491             if (mWifiScanTimer == null) {
   7492                 return 0;
   7493             }
   7494             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
   7495             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
   7496         }
   7497 
   7498         @Override
   7499         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
   7500             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
   7501                 return 0;
   7502             }
   7503             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
   7504             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
   7505         }
   7506 
   7507         @Override
   7508         public Timer getWifiScanBackgroundTimer() {
   7509             if (mWifiScanTimer == null) {
   7510                 return null;
   7511             }
   7512             return mWifiScanTimer.getSubTimer();
   7513         }
   7514 
   7515         @Override
   7516         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
   7517             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
   7518             if (mWifiBatchedScanTimer[csphBin] == null) {
   7519                 return 0;
   7520             }
   7521             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
   7522         }
   7523 
   7524         @Override
   7525         public int getWifiBatchedScanCount(int csphBin, int which) {
   7526             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
   7527             if (mWifiBatchedScanTimer[csphBin] == null) {
   7528                 return 0;
   7529             }
   7530             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
   7531         }
   7532 
   7533         @Override
   7534         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
   7535             if (mWifiMulticastTimer == null) {
   7536                 return 0;
   7537             }
   7538             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
   7539         }
   7540 
   7541         @Override
   7542         public Timer getAudioTurnedOnTimer() {
   7543             return mAudioTurnedOnTimer;
   7544         }
   7545 
   7546         @Override
   7547         public Timer getVideoTurnedOnTimer() {
   7548             return mVideoTurnedOnTimer;
   7549         }
   7550 
   7551         @Override
   7552         public Timer getFlashlightTurnedOnTimer() {
   7553             return mFlashlightTurnedOnTimer;
   7554         }
   7555 
   7556         @Override
   7557         public Timer getCameraTurnedOnTimer() {
   7558             return mCameraTurnedOnTimer;
   7559         }
   7560 
   7561         @Override
   7562         public Timer getForegroundActivityTimer() {
   7563             return mForegroundActivityTimer;
   7564         }
   7565 
   7566         @Override
   7567         public Timer getForegroundServiceTimer() {
   7568             return mForegroundServiceTimer;
   7569         }
   7570 
   7571         @Override
   7572         public Timer getBluetoothScanTimer() {
   7573             return mBluetoothScanTimer;
   7574         }
   7575 
   7576         @Override
   7577         public Timer getBluetoothScanBackgroundTimer() {
   7578             if (mBluetoothScanTimer == null) {
   7579                 return null;
   7580             }
   7581             return mBluetoothScanTimer.getSubTimer();
   7582         }
   7583 
   7584         @Override
   7585         public Timer getBluetoothUnoptimizedScanTimer() {
   7586             return mBluetoothUnoptimizedScanTimer;
   7587         }
   7588 
   7589         @Override
   7590         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
   7591             if (mBluetoothUnoptimizedScanTimer == null) {
   7592                 return null;
   7593             }
   7594             return mBluetoothUnoptimizedScanTimer.getSubTimer();
   7595         }
   7596 
   7597         @Override
   7598         public Counter getBluetoothScanResultCounter() {
   7599             return mBluetoothScanResultCounter;
   7600         }
   7601 
   7602         @Override
   7603         public Counter getBluetoothScanResultBgCounter() {
   7604             return mBluetoothScanResultBgCounter;
   7605         }
   7606 
   7607         void makeProcessState(int i, Parcel in) {
   7608             if (i < 0 || i >= NUM_PROCESS_STATE) return;
   7609 
   7610             if (in == null) {
   7611                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
   7612                         mBsi.mOnBatteryTimeBase);
   7613             } else {
   7614                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
   7615                         mBsi.mOnBatteryTimeBase, in);
   7616             }
   7617         }
   7618 
   7619         @Override
   7620         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
   7621             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
   7622             if (mProcessStateTimer[state] == null) {
   7623                 return 0;
   7624             }
   7625             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
   7626         }
   7627 
   7628         @Override
   7629         public Timer getProcessStateTimer(int state) {
   7630             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
   7631             return mProcessStateTimer[state];
   7632         }
   7633 
   7634         @Override
   7635         public Timer getVibratorOnTimer() {
   7636             return mVibratorOnTimer;
   7637         }
   7638 
   7639         @Override
   7640         public void noteUserActivityLocked(int type) {
   7641             if (mUserActivityCounters == null) {
   7642                 initUserActivityLocked();
   7643             }
   7644             if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
   7645                 mUserActivityCounters[type].stepAtomic();
   7646             } else {
   7647                 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
   7648                         new Throwable());
   7649             }
   7650         }
   7651 
   7652         @Override
   7653         public boolean hasUserActivity() {
   7654             return mUserActivityCounters != null;
   7655         }
   7656 
   7657         @Override
   7658         public int getUserActivityCount(int type, int which) {
   7659             if (mUserActivityCounters == null) {
   7660                 return 0;
   7661             }
   7662             return mUserActivityCounters[type].getCountLocked(which);
   7663         }
   7664 
   7665         void makeWifiBatchedScanBin(int i, Parcel in) {
   7666             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
   7667 
   7668             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
   7669             if (collected == null) {
   7670                 collected = new ArrayList<StopwatchTimer>();
   7671                 mBsi.mWifiBatchedScanTimers.put(i, collected);
   7672             }
   7673             if (in == null) {
   7674                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
   7675                         collected, mBsi.mOnBatteryTimeBase);
   7676             } else {
   7677                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
   7678                         collected, mBsi.mOnBatteryTimeBase, in);
   7679             }
   7680         }
   7681 
   7682 
   7683         void initUserActivityLocked() {
   7684             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
   7685             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   7686                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
   7687             }
   7688         }
   7689 
   7690         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
   7691             if (mNetworkByteActivityCounters == null) {
   7692                 initNetworkActivityLocked();
   7693             }
   7694             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
   7695                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
   7696                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
   7697             } else {
   7698                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
   7699                         new Throwable());
   7700             }
   7701         }
   7702 
   7703         void noteMobileRadioActiveTimeLocked(long batteryUptime) {
   7704             if (mNetworkByteActivityCounters == null) {
   7705                 initNetworkActivityLocked();
   7706             }
   7707             mMobileRadioActiveTime.addCountLocked(batteryUptime);
   7708             mMobileRadioActiveCount.addCountLocked(1);
   7709         }
   7710 
   7711         @Override
   7712         public boolean hasNetworkActivity() {
   7713             return mNetworkByteActivityCounters != null;
   7714         }
   7715 
   7716         @Override
   7717         public long getNetworkActivityBytes(int type, int which) {
   7718             if (mNetworkByteActivityCounters != null && type >= 0
   7719                     && type < mNetworkByteActivityCounters.length) {
   7720                 return mNetworkByteActivityCounters[type].getCountLocked(which);
   7721             } else {
   7722                 return 0;
   7723             }
   7724         }
   7725 
   7726         @Override
   7727         public long getNetworkActivityPackets(int type, int which) {
   7728             if (mNetworkPacketActivityCounters != null && type >= 0
   7729                     && type < mNetworkPacketActivityCounters.length) {
   7730                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
   7731             } else {
   7732                 return 0;
   7733             }
   7734         }
   7735 
   7736         @Override
   7737         public long getMobileRadioActiveTime(int which) {
   7738             return mMobileRadioActiveTime != null
   7739                     ? mMobileRadioActiveTime.getCountLocked(which) : 0;
   7740         }
   7741 
   7742         @Override
   7743         public int getMobileRadioActiveCount(int which) {
   7744             return mMobileRadioActiveCount != null
   7745                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
   7746         }
   7747 
   7748         @Override
   7749         public long getUserCpuTimeUs(int which) {
   7750             return mUserCpuTime.getCountLocked(which);
   7751         }
   7752 
   7753         @Override
   7754         public long getSystemCpuTimeUs(int which) {
   7755             return mSystemCpuTime.getCountLocked(which);
   7756         }
   7757 
   7758         @Override
   7759         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
   7760             if (mCpuClusterSpeedTimesUs != null) {
   7761                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
   7762                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
   7763                     if (cpuSpeedTimesUs != null) {
   7764                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
   7765                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
   7766                             if (c != null) {
   7767                                 return c.getCountLocked(which);
   7768                             }
   7769                         }
   7770                     }
   7771                 }
   7772             }
   7773             return 0;
   7774         }
   7775 
   7776         public void noteMobileRadioApWakeupLocked() {
   7777             if (mMobileRadioApWakeupCount == null) {
   7778                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   7779             }
   7780             mMobileRadioApWakeupCount.addCountLocked(1);
   7781         }
   7782 
   7783         @Override
   7784         public long getMobileRadioApWakeupCount(int which) {
   7785             if (mMobileRadioApWakeupCount != null) {
   7786                 return mMobileRadioApWakeupCount.getCountLocked(which);
   7787             }
   7788             return 0;
   7789         }
   7790 
   7791         public void noteWifiRadioApWakeupLocked() {
   7792             if (mWifiRadioApWakeupCount == null) {
   7793                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   7794             }
   7795             mWifiRadioApWakeupCount.addCountLocked(1);
   7796         }
   7797 
   7798         @Override
   7799         public long getWifiRadioApWakeupCount(int which) {
   7800             if (mWifiRadioApWakeupCount != null) {
   7801                 return mWifiRadioApWakeupCount.getCountLocked(which);
   7802             }
   7803             return 0;
   7804         }
   7805 
   7806         @Override
   7807         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
   7808             sb.setLength(0);
   7809             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
   7810             if (deferredEventCount == 0) {
   7811                 return;
   7812             }
   7813             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
   7814             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
   7815             sb.append(deferredEventCount); sb.append(',');
   7816             sb.append(deferredCount); sb.append(',');
   7817             sb.append(totalLatency);
   7818             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
   7819                 if (mJobsFreshnessBuckets[i] == null) {
   7820                     sb.append(",0");
   7821                 } else {
   7822                     sb.append(",");
   7823                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
   7824                 }
   7825             }
   7826         }
   7827 
   7828         @Override
   7829         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
   7830             sb.setLength(0);
   7831             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
   7832             if (deferredEventCount == 0) {
   7833                 return;
   7834             }
   7835             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
   7836             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
   7837             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
   7838             sb.append("count="); sb.append(deferredCount); sb.append(", ");
   7839             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
   7840             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
   7841                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
   7842                 if (mJobsFreshnessBuckets[i] == null) {
   7843                     sb.append("0");
   7844                 } else {
   7845                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
   7846                 }
   7847                 sb.append(" ");
   7848             }
   7849         }
   7850 
   7851         void initNetworkActivityLocked() {
   7852             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   7853             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   7854             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   7855                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   7856                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   7857             }
   7858             mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   7859             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
   7860         }
   7861 
   7862         /**
   7863          * Clear all stats for this uid.  Returns true if the uid is completely
   7864          * inactive so can be dropped.
   7865          */
   7866         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
   7867         public boolean reset(long uptime, long realtime) {
   7868             boolean active = false;
   7869 
   7870             mOnBatteryBackgroundTimeBase.init(uptime, realtime);
   7871             mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
   7872 
   7873             if (mWifiRunningTimer != null) {
   7874                 active |= !mWifiRunningTimer.reset(false);
   7875                 active |= mWifiRunning;
   7876             }
   7877             if (mFullWifiLockTimer != null) {
   7878                 active |= !mFullWifiLockTimer.reset(false);
   7879                 active |= mFullWifiLockOut;
   7880             }
   7881             if (mWifiScanTimer != null) {
   7882                 active |= !mWifiScanTimer.reset(false);
   7883                 active |= mWifiScanStarted;
   7884             }
   7885             if (mWifiBatchedScanTimer != null) {
   7886                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   7887                     if (mWifiBatchedScanTimer[i] != null) {
   7888                         active |= !mWifiBatchedScanTimer[i].reset(false);
   7889                     }
   7890                 }
   7891                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
   7892             }
   7893             if (mWifiMulticastTimer != null) {
   7894                 active |= !mWifiMulticastTimer.reset(false);
   7895                 active |= mWifiMulticastEnabled;
   7896             }
   7897 
   7898             active |= !resetTimerIfNotNull(mAudioTurnedOnTimer, false);
   7899             active |= !resetTimerIfNotNull(mVideoTurnedOnTimer, false);
   7900             active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false);
   7901             active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false);
   7902             active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
   7903             active |= !resetTimerIfNotNull(mForegroundServiceTimer, false);
   7904             active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false);
   7905             active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
   7906             active |= !resetTimerIfNotNull(mBluetoothUnoptimizedScanTimer, false);
   7907             if (mBluetoothScanResultCounter != null) {
   7908                 mBluetoothScanResultCounter.reset(false);
   7909             }
   7910             if (mBluetoothScanResultBgCounter != null) {
   7911                 mBluetoothScanResultBgCounter.reset(false);
   7912             }
   7913 
   7914             if (mProcessStateTimer != null) {
   7915                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
   7916                     if (mProcessStateTimer[i] != null) {
   7917                         active |= !mProcessStateTimer[i].reset(false);
   7918                     }
   7919                 }
   7920                 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
   7921             }
   7922             if (mVibratorOnTimer != null) {
   7923                 if (mVibratorOnTimer.reset(false)) {
   7924                     mVibratorOnTimer.detach();
   7925                     mVibratorOnTimer = null;
   7926                 } else {
   7927                     active = true;
   7928                 }
   7929             }
   7930 
   7931             if (mUserActivityCounters != null) {
   7932                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   7933                     mUserActivityCounters[i].reset(false);
   7934                 }
   7935             }
   7936 
   7937             if (mNetworkByteActivityCounters != null) {
   7938                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   7939                     mNetworkByteActivityCounters[i].reset(false);
   7940                     mNetworkPacketActivityCounters[i].reset(false);
   7941                 }
   7942                 mMobileRadioActiveTime.reset(false);
   7943                 mMobileRadioActiveCount.reset(false);
   7944             }
   7945 
   7946             if (mWifiControllerActivity != null) {
   7947                 mWifiControllerActivity.reset(false);
   7948             }
   7949 
   7950             if (mBluetoothControllerActivity != null) {
   7951                 mBluetoothControllerActivity.reset(false);
   7952             }
   7953 
   7954             if (mModemControllerActivity != null) {
   7955                 mModemControllerActivity.reset(false);
   7956             }
   7957 
   7958             mUserCpuTime.reset(false);
   7959             mSystemCpuTime.reset(false);
   7960 
   7961             if (mCpuClusterSpeedTimesUs != null) {
   7962                 for (LongSamplingCounter[] speeds : mCpuClusterSpeedTimesUs) {
   7963                     if (speeds != null) {
   7964                         for (LongSamplingCounter speed : speeds) {
   7965                             if (speed != null) {
   7966                                 speed.reset(false);
   7967                             }
   7968                         }
   7969                     }
   7970                 }
   7971             }
   7972 
   7973             if (mCpuFreqTimeMs != null) {
   7974                 mCpuFreqTimeMs.reset(false);
   7975             }
   7976             if (mScreenOffCpuFreqTimeMs != null) {
   7977                 mScreenOffCpuFreqTimeMs.reset(false);
   7978             }
   7979 
   7980             mCpuActiveTimeMs.reset(false);
   7981             mCpuClusterTimesMs.reset(false);
   7982 
   7983             if (mProcStateTimeMs != null) {
   7984                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
   7985                     if (counters != null) {
   7986                         counters.reset(false);
   7987                     }
   7988                 }
   7989             }
   7990             if (mProcStateScreenOffTimeMs != null) {
   7991                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
   7992                     if (counters != null) {
   7993                         counters.reset(false);
   7994                     }
   7995                 }
   7996             }
   7997 
   7998             resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false);
   7999             resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false);
   8000 
   8001             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
   8002             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
   8003                 Wakelock wl = wakeStats.valueAt(iw);
   8004                 if (wl.reset()) {
   8005                     wakeStats.removeAt(iw);
   8006                 } else {
   8007                     active = true;
   8008                 }
   8009             }
   8010             mWakelockStats.cleanup();
   8011             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
   8012             for (int is=syncStats.size()-1; is>=0; is--) {
   8013                 DualTimer timer = syncStats.valueAt(is);
   8014                 if (timer.reset(false)) {
   8015                     syncStats.removeAt(is);
   8016                     timer.detach();
   8017                 } else {
   8018                     active = true;
   8019                 }
   8020             }
   8021             mSyncStats.cleanup();
   8022             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
   8023             for (int ij=jobStats.size()-1; ij>=0; ij--) {
   8024                 DualTimer timer = jobStats.valueAt(ij);
   8025                 if (timer.reset(false)) {
   8026                     jobStats.removeAt(ij);
   8027                     timer.detach();
   8028                 } else {
   8029                     active = true;
   8030                 }
   8031             }
   8032             mJobStats.cleanup();
   8033             mJobCompletions.clear();
   8034 
   8035             mJobsDeferredEventCount.reset(false);
   8036             mJobsDeferredCount.reset(false);
   8037             mJobsFreshnessTimeMs.reset(false);
   8038             for (int ij = 0; ij < JOB_FRESHNESS_BUCKETS.length; ij++) {
   8039                 if (mJobsFreshnessBuckets[ij] != null) {
   8040                     mJobsFreshnessBuckets[ij].reset(false);
   8041                 }
   8042             }
   8043 
   8044             for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
   8045                 Sensor s = mSensorStats.valueAt(ise);
   8046                 if (s.reset()) {
   8047                     mSensorStats.removeAt(ise);
   8048                 } else {
   8049                     active = true;
   8050                 }
   8051             }
   8052 
   8053             for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
   8054                 Proc proc = mProcessStats.valueAt(ip);
   8055                 proc.detach();
   8056             }
   8057             mProcessStats.clear();
   8058             if (mPids.size() > 0) {
   8059                 for (int i=mPids.size()-1; i>=0; i--) {
   8060                     Pid pid = mPids.valueAt(i);
   8061                     if (pid.mWakeNesting > 0) {
   8062                         active = true;
   8063                     } else {
   8064                         mPids.removeAt(i);
   8065                     }
   8066                 }
   8067             }
   8068             if (mPackageStats.size() > 0) {
   8069                 Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
   8070                 while (it.hasNext()) {
   8071                     Map.Entry<String, Pkg> pkgEntry = it.next();
   8072                     Pkg p = pkgEntry.getValue();
   8073                     p.detach();
   8074                     if (p.mServiceStats.size() > 0) {
   8075                         Iterator<Map.Entry<String, Pkg.Serv>> it2
   8076                                 = p.mServiceStats.entrySet().iterator();
   8077                         while (it2.hasNext()) {
   8078                             Map.Entry<String, Pkg.Serv> servEntry = it2.next();
   8079                             servEntry.getValue().detach();
   8080                         }
   8081                     }
   8082                 }
   8083                 mPackageStats.clear();
   8084             }
   8085 
   8086             mLastStepUserTime = mLastStepSystemTime = 0;
   8087             mCurStepUserTime = mCurStepSystemTime = 0;
   8088 
   8089             if (!active) {
   8090                 if (mWifiRunningTimer != null) {
   8091                     mWifiRunningTimer.detach();
   8092                 }
   8093                 if (mFullWifiLockTimer != null) {
   8094                     mFullWifiLockTimer.detach();
   8095                 }
   8096                 if (mWifiScanTimer != null) {
   8097                     mWifiScanTimer.detach();
   8098                 }
   8099                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   8100                     if (mWifiBatchedScanTimer[i] != null) {
   8101                         mWifiBatchedScanTimer[i].detach();
   8102                     }
   8103                 }
   8104                 if (mWifiMulticastTimer != null) {
   8105                     mWifiMulticastTimer.detach();
   8106                 }
   8107                 if (mAudioTurnedOnTimer != null) {
   8108                     mAudioTurnedOnTimer.detach();
   8109                     mAudioTurnedOnTimer = null;
   8110                 }
   8111                 if (mVideoTurnedOnTimer != null) {
   8112                     mVideoTurnedOnTimer.detach();
   8113                     mVideoTurnedOnTimer = null;
   8114                 }
   8115                 if (mFlashlightTurnedOnTimer != null) {
   8116                     mFlashlightTurnedOnTimer.detach();
   8117                     mFlashlightTurnedOnTimer = null;
   8118                 }
   8119                 if (mCameraTurnedOnTimer != null) {
   8120                     mCameraTurnedOnTimer.detach();
   8121                     mCameraTurnedOnTimer = null;
   8122                 }
   8123                 if (mForegroundActivityTimer != null) {
   8124                     mForegroundActivityTimer.detach();
   8125                     mForegroundActivityTimer = null;
   8126                 }
   8127                 if (mForegroundServiceTimer != null) {
   8128                     mForegroundServiceTimer.detach();
   8129                     mForegroundServiceTimer = null;
   8130                 }
   8131                 if (mAggregatedPartialWakelockTimer != null) {
   8132                     mAggregatedPartialWakelockTimer.detach();
   8133                     mAggregatedPartialWakelockTimer = null;
   8134                 }
   8135                 if (mBluetoothScanTimer != null) {
   8136                     mBluetoothScanTimer.detach();
   8137                     mBluetoothScanTimer = null;
   8138                 }
   8139                 if (mBluetoothUnoptimizedScanTimer != null) {
   8140                     mBluetoothUnoptimizedScanTimer.detach();
   8141                     mBluetoothUnoptimizedScanTimer = null;
   8142                 }
   8143                 if (mBluetoothScanResultCounter != null) {
   8144                     mBluetoothScanResultCounter.detach();
   8145                     mBluetoothScanResultCounter = null;
   8146                 }
   8147                 if (mBluetoothScanResultBgCounter != null) {
   8148                     mBluetoothScanResultBgCounter.detach();
   8149                     mBluetoothScanResultBgCounter = null;
   8150                 }
   8151                 if (mUserActivityCounters != null) {
   8152                     for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   8153                         mUserActivityCounters[i].detach();
   8154                     }
   8155                 }
   8156                 if (mNetworkByteActivityCounters != null) {
   8157                     for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   8158                         mNetworkByteActivityCounters[i].detach();
   8159                         mNetworkPacketActivityCounters[i].detach();
   8160                     }
   8161                 }
   8162 
   8163                 if (mWifiControllerActivity != null) {
   8164                     mWifiControllerActivity.detach();
   8165                 }
   8166 
   8167                 if (mBluetoothControllerActivity != null) {
   8168                     mBluetoothControllerActivity.detach();
   8169                 }
   8170 
   8171                 if (mModemControllerActivity != null) {
   8172                     mModemControllerActivity.detach();
   8173                 }
   8174 
   8175                 mPids.clear();
   8176 
   8177                 mUserCpuTime.detach();
   8178                 mSystemCpuTime.detach();
   8179 
   8180                 if (mCpuClusterSpeedTimesUs != null) {
   8181                     for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
   8182                         if (cpuSpeeds != null) {
   8183                             for (LongSamplingCounter c : cpuSpeeds) {
   8184                                 if (c != null) {
   8185                                     c.detach();
   8186                                 }
   8187                             }
   8188                         }
   8189                     }
   8190                 }
   8191 
   8192                 if (mCpuFreqTimeMs != null) {
   8193                     mCpuFreqTimeMs.detach();
   8194                 }
   8195                 if (mScreenOffCpuFreqTimeMs != null) {
   8196                     mScreenOffCpuFreqTimeMs.detach();
   8197                 }
   8198                 mCpuActiveTimeMs.detach();
   8199                 mCpuClusterTimesMs.detach();
   8200 
   8201                 if (mProcStateTimeMs != null) {
   8202                     for (LongSamplingCounterArray counters : mProcStateTimeMs) {
   8203                         if (counters != null) {
   8204                             counters.detach();
   8205                         }
   8206                     }
   8207                 }
   8208                 if (mProcStateScreenOffTimeMs != null) {
   8209                     for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
   8210                         if (counters != null) {
   8211                             counters.detach();
   8212                         }
   8213                     }
   8214                 }
   8215                 detachLongCounterIfNotNull(mMobileRadioApWakeupCount);
   8216                 detachLongCounterIfNotNull(mWifiRadioApWakeupCount);
   8217             }
   8218 
   8219             return !active;
   8220         }
   8221 
   8222         void writeJobCompletionsToParcelLocked(Parcel out) {
   8223             int NJC = mJobCompletions.size();
   8224             out.writeInt(NJC);
   8225             for (int ijc=0; ijc<NJC; ijc++) {
   8226                 out.writeString(mJobCompletions.keyAt(ijc));
   8227                 SparseIntArray types = mJobCompletions.valueAt(ijc);
   8228                 int NT = types.size();
   8229                 out.writeInt(NT);
   8230                 for (int it=0; it<NT; it++) {
   8231                     out.writeInt(types.keyAt(it));
   8232                     out.writeInt(types.valueAt(it));
   8233                 }
   8234             }
   8235         }
   8236 
   8237         void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
   8238             mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
   8239             mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
   8240 
   8241             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
   8242             int NW = wakeStats.size();
   8243             out.writeInt(NW);
   8244             for (int iw=0; iw<NW; iw++) {
   8245                 out.writeString(wakeStats.keyAt(iw));
   8246                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
   8247                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
   8248             }
   8249 
   8250             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
   8251             int NS = syncStats.size();
   8252             out.writeInt(NS);
   8253             for (int is=0; is<NS; is++) {
   8254                 out.writeString(syncStats.keyAt(is));
   8255                 DualTimer timer = syncStats.valueAt(is);
   8256                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
   8257             }
   8258 
   8259             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
   8260             int NJ = jobStats.size();
   8261             out.writeInt(NJ);
   8262             for (int ij=0; ij<NJ; ij++) {
   8263                 out.writeString(jobStats.keyAt(ij));
   8264                 DualTimer timer = jobStats.valueAt(ij);
   8265                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
   8266             }
   8267 
   8268             writeJobCompletionsToParcelLocked(out);
   8269 
   8270             mJobsDeferredEventCount.writeToParcel(out);
   8271             mJobsDeferredCount.writeToParcel(out);
   8272             mJobsFreshnessTimeMs.writeToParcel(out);
   8273             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
   8274                 Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
   8275             }
   8276 
   8277             int NSE = mSensorStats.size();
   8278             out.writeInt(NSE);
   8279             for (int ise=0; ise<NSE; ise++) {
   8280                 out.writeInt(mSensorStats.keyAt(ise));
   8281                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
   8282                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
   8283             }
   8284 
   8285             int NP = mProcessStats.size();
   8286             out.writeInt(NP);
   8287             for (int ip=0; ip<NP; ip++) {
   8288                 out.writeString(mProcessStats.keyAt(ip));
   8289                 Uid.Proc proc = mProcessStats.valueAt(ip);
   8290                 proc.writeToParcelLocked(out);
   8291             }
   8292 
   8293             out.writeInt(mPackageStats.size());
   8294             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
   8295                 out.writeString(pkgEntry.getKey());
   8296                 Uid.Pkg pkg = pkgEntry.getValue();
   8297                 pkg.writeToParcelLocked(out);
   8298             }
   8299 
   8300             if (mWifiRunningTimer != null) {
   8301                 out.writeInt(1);
   8302                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
   8303             } else {
   8304                 out.writeInt(0);
   8305             }
   8306             if (mFullWifiLockTimer != null) {
   8307                 out.writeInt(1);
   8308                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
   8309             } else {
   8310                 out.writeInt(0);
   8311             }
   8312             if (mWifiScanTimer != null) {
   8313                 out.writeInt(1);
   8314                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
   8315             } else {
   8316                 out.writeInt(0);
   8317             }
   8318             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   8319                 if (mWifiBatchedScanTimer[i] != null) {
   8320                     out.writeInt(1);
   8321                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
   8322                 } else {
   8323                     out.writeInt(0);
   8324                 }
   8325             }
   8326             if (mWifiMulticastTimer != null) {
   8327                 out.writeInt(1);
   8328                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
   8329             } else {
   8330                 out.writeInt(0);
   8331             }
   8332 
   8333             if (mAudioTurnedOnTimer != null) {
   8334                 out.writeInt(1);
   8335                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
   8336             } else {
   8337                 out.writeInt(0);
   8338             }
   8339             if (mVideoTurnedOnTimer != null) {
   8340                 out.writeInt(1);
   8341                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
   8342             } else {
   8343                 out.writeInt(0);
   8344             }
   8345             if (mFlashlightTurnedOnTimer != null) {
   8346                 out.writeInt(1);
   8347                 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
   8348             } else {
   8349                 out.writeInt(0);
   8350             }
   8351             if (mCameraTurnedOnTimer != null) {
   8352                 out.writeInt(1);
   8353                 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
   8354             } else {
   8355                 out.writeInt(0);
   8356             }
   8357             if (mForegroundActivityTimer != null) {
   8358                 out.writeInt(1);
   8359                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
   8360             } else {
   8361                 out.writeInt(0);
   8362             }
   8363             if (mForegroundServiceTimer != null) {
   8364                 out.writeInt(1);
   8365                 mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
   8366             } else {
   8367                 out.writeInt(0);
   8368             }
   8369             if (mAggregatedPartialWakelockTimer != null) {
   8370                 out.writeInt(1);
   8371                 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
   8372             } else {
   8373                 out.writeInt(0);
   8374             }
   8375             if (mBluetoothScanTimer != null) {
   8376                 out.writeInt(1);
   8377                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
   8378             } else {
   8379                 out.writeInt(0);
   8380             }
   8381             if (mBluetoothUnoptimizedScanTimer != null) {
   8382                 out.writeInt(1);
   8383                 mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
   8384             } else {
   8385                 out.writeInt(0);
   8386             }
   8387             if (mBluetoothScanResultCounter != null) {
   8388                 out.writeInt(1);
   8389                 mBluetoothScanResultCounter.writeToParcel(out);
   8390             } else {
   8391                 out.writeInt(0);
   8392             }
   8393             if (mBluetoothScanResultBgCounter != null) {
   8394                 out.writeInt(1);
   8395                 mBluetoothScanResultBgCounter.writeToParcel(out);
   8396             } else {
   8397                 out.writeInt(0);
   8398             }
   8399             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
   8400                 if (mProcessStateTimer[i] != null) {
   8401                     out.writeInt(1);
   8402                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
   8403                 } else {
   8404                     out.writeInt(0);
   8405                 }
   8406             }
   8407             if (mVibratorOnTimer != null) {
   8408                 out.writeInt(1);
   8409                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
   8410             } else {
   8411                 out.writeInt(0);
   8412             }
   8413             if (mUserActivityCounters != null) {
   8414                 out.writeInt(1);
   8415                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   8416                     mUserActivityCounters[i].writeToParcel(out);
   8417                 }
   8418             } else {
   8419                 out.writeInt(0);
   8420             }
   8421             if (mNetworkByteActivityCounters != null) {
   8422                 out.writeInt(1);
   8423                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   8424                     mNetworkByteActivityCounters[i].writeToParcel(out);
   8425                     mNetworkPacketActivityCounters[i].writeToParcel(out);
   8426                 }
   8427                 mMobileRadioActiveTime.writeToParcel(out);
   8428                 mMobileRadioActiveCount.writeToParcel(out);
   8429             } else {
   8430                 out.writeInt(0);
   8431             }
   8432 
   8433             if (mWifiControllerActivity != null) {
   8434                 out.writeInt(1);
   8435                 mWifiControllerActivity.writeToParcel(out, 0);
   8436             } else {
   8437                 out.writeInt(0);
   8438             }
   8439 
   8440             if (mBluetoothControllerActivity != null) {
   8441                 out.writeInt(1);
   8442                 mBluetoothControllerActivity.writeToParcel(out, 0);
   8443             } else {
   8444                 out.writeInt(0);
   8445             }
   8446 
   8447             if (mModemControllerActivity != null) {
   8448                 out.writeInt(1);
   8449                 mModemControllerActivity.writeToParcel(out, 0);
   8450             } else {
   8451                 out.writeInt(0);
   8452             }
   8453 
   8454             mUserCpuTime.writeToParcel(out);
   8455             mSystemCpuTime.writeToParcel(out);
   8456 
   8457             if (mCpuClusterSpeedTimesUs != null) {
   8458                 out.writeInt(1);
   8459                 out.writeInt(mCpuClusterSpeedTimesUs.length);
   8460                 for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
   8461                     if (cpuSpeeds != null) {
   8462                         out.writeInt(1);
   8463                         out.writeInt(cpuSpeeds.length);
   8464                         for (LongSamplingCounter c : cpuSpeeds) {
   8465                             if (c != null) {
   8466                                 out.writeInt(1);
   8467                                 c.writeToParcel(out);
   8468                             } else {
   8469                                 out.writeInt(0);
   8470                             }
   8471                         }
   8472                     } else {
   8473                         out.writeInt(0);
   8474                     }
   8475                 }
   8476             } else {
   8477                 out.writeInt(0);
   8478             }
   8479 
   8480             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
   8481             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
   8482 
   8483             mCpuActiveTimeMs.writeToParcel(out);
   8484             mCpuClusterTimesMs.writeToParcel(out);
   8485 
   8486             if (mProcStateTimeMs != null) {
   8487                 out.writeInt(mProcStateTimeMs.length);
   8488                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
   8489                     LongSamplingCounterArray.writeToParcel(out, counters);
   8490                 }
   8491             } else {
   8492                 out.writeInt(0);
   8493             }
   8494             if (mProcStateScreenOffTimeMs != null) {
   8495                 out.writeInt(mProcStateScreenOffTimeMs.length);
   8496                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
   8497                     LongSamplingCounterArray.writeToParcel(out, counters);
   8498                 }
   8499             } else {
   8500                 out.writeInt(0);
   8501             }
   8502 
   8503             if (mMobileRadioApWakeupCount != null) {
   8504                 out.writeInt(1);
   8505                 mMobileRadioApWakeupCount.writeToParcel(out);
   8506             } else {
   8507                 out.writeInt(0);
   8508             }
   8509 
   8510             if (mWifiRadioApWakeupCount != null) {
   8511                 out.writeInt(1);
   8512                 mWifiRadioApWakeupCount.writeToParcel(out);
   8513             } else {
   8514                 out.writeInt(0);
   8515             }
   8516         }
   8517 
   8518         void readJobCompletionsFromParcelLocked(Parcel in) {
   8519             int numJobCompletions = in.readInt();
   8520             mJobCompletions.clear();
   8521             for (int j = 0; j < numJobCompletions; j++) {
   8522                 String jobName = in.readString();
   8523                 int numTypes = in.readInt();
   8524                 if (numTypes > 0) {
   8525                     SparseIntArray types = new SparseIntArray();
   8526                     for (int k = 0; k < numTypes; k++) {
   8527                         int type = in.readInt();
   8528                         int count = in.readInt();
   8529                         types.put(type, count);
   8530                     }
   8531                     mJobCompletions.put(jobName, types);
   8532                 }
   8533             }
   8534         }
   8535 
   8536         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
   8537             mOnBatteryBackgroundTimeBase.readFromParcel(in);
   8538             mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
   8539 
   8540             int numWakelocks = in.readInt();
   8541             mWakelockStats.clear();
   8542             for (int j = 0; j < numWakelocks; j++) {
   8543                 String wakelockName = in.readString();
   8544                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
   8545                 wakelock.readFromParcelLocked(
   8546                         timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
   8547                 mWakelockStats.add(wakelockName, wakelock);
   8548             }
   8549 
   8550             int numSyncs = in.readInt();
   8551             mSyncStats.clear();
   8552             for (int j = 0; j < numSyncs; j++) {
   8553                 String syncName = in.readString();
   8554                 if (in.readInt() != 0) {
   8555                     mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
   8556                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
   8557                 }
   8558             }
   8559 
   8560             int numJobs = in.readInt();
   8561             mJobStats.clear();
   8562             for (int j = 0; j < numJobs; j++) {
   8563                 String jobName = in.readString();
   8564                 if (in.readInt() != 0) {
   8565                     mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
   8566                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
   8567                 }
   8568             }
   8569 
   8570             readJobCompletionsFromParcelLocked(in);
   8571 
   8572             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
   8573             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
   8574             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   8575             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
   8576                 mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
   8577                         in);
   8578             }
   8579 
   8580             int numSensors = in.readInt();
   8581             mSensorStats.clear();
   8582             for (int k = 0; k < numSensors; k++) {
   8583                 int sensorNumber = in.readInt();
   8584                 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
   8585                 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
   8586                         in);
   8587                 mSensorStats.put(sensorNumber, sensor);
   8588             }
   8589 
   8590             int numProcs = in.readInt();
   8591             mProcessStats.clear();
   8592             for (int k = 0; k < numProcs; k++) {
   8593                 String processName = in.readString();
   8594                 Uid.Proc proc = new Proc(mBsi, processName);
   8595                 proc.readFromParcelLocked(in);
   8596                 mProcessStats.put(processName, proc);
   8597             }
   8598 
   8599             int numPkgs = in.readInt();
   8600             mPackageStats.clear();
   8601             for (int l = 0; l < numPkgs; l++) {
   8602                 String packageName = in.readString();
   8603                 Uid.Pkg pkg = new Pkg(mBsi);
   8604                 pkg.readFromParcelLocked(in);
   8605                 mPackageStats.put(packageName, pkg);
   8606             }
   8607 
   8608             mWifiRunning = false;
   8609             if (in.readInt() != 0) {
   8610                 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
   8611                         mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
   8612             } else {
   8613                 mWifiRunningTimer = null;
   8614             }
   8615             mFullWifiLockOut = false;
   8616             if (in.readInt() != 0) {
   8617                 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
   8618                         mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
   8619             } else {
   8620                 mFullWifiLockTimer = null;
   8621             }
   8622             mWifiScanStarted = false;
   8623             if (in.readInt() != 0) {
   8624                 mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
   8625                         mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
   8626                         in);
   8627             } else {
   8628                 mWifiScanTimer = null;
   8629             }
   8630             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
   8631             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   8632                 if (in.readInt() != 0) {
   8633                     makeWifiBatchedScanBin(i, in);
   8634                 } else {
   8635                     mWifiBatchedScanTimer[i] = null;
   8636                 }
   8637             }
   8638             mWifiMulticastEnabled = false;
   8639             if (in.readInt() != 0) {
   8640                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
   8641                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
   8642             } else {
   8643                 mWifiMulticastTimer = null;
   8644             }
   8645             if (in.readInt() != 0) {
   8646                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
   8647                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
   8648             } else {
   8649                 mAudioTurnedOnTimer = null;
   8650             }
   8651             if (in.readInt() != 0) {
   8652                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
   8653                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
   8654             } else {
   8655                 mVideoTurnedOnTimer = null;
   8656             }
   8657             if (in.readInt() != 0) {
   8658                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   8659                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
   8660             } else {
   8661                 mFlashlightTurnedOnTimer = null;
   8662             }
   8663             if (in.readInt() != 0) {
   8664                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
   8665                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
   8666             } else {
   8667                 mCameraTurnedOnTimer = null;
   8668             }
   8669             if (in.readInt() != 0) {
   8670                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   8671                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
   8672             } else {
   8673                 mForegroundActivityTimer = null;
   8674             }
   8675             if (in.readInt() != 0) {
   8676                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
   8677                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
   8678             } else {
   8679                 mForegroundServiceTimer = null;
   8680             }
   8681             if (in.readInt() != 0) {
   8682                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
   8683                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
   8684                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
   8685                         in);
   8686             } else {
   8687                 mAggregatedPartialWakelockTimer = null;
   8688             }
   8689             if (in.readInt() != 0) {
   8690                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
   8691                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
   8692                         mOnBatteryBackgroundTimeBase, in);
   8693             } else {
   8694                 mBluetoothScanTimer = null;
   8695             }
   8696             if (in.readInt() != 0) {
   8697                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
   8698                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
   8699                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
   8700             } else {
   8701                 mBluetoothUnoptimizedScanTimer = null;
   8702             }
   8703             if (in.readInt() != 0) {
   8704                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
   8705             } else {
   8706                 mBluetoothScanResultCounter = null;
   8707             }
   8708             if (in.readInt() != 0) {
   8709                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
   8710             } else {
   8711                 mBluetoothScanResultBgCounter = null;
   8712             }
   8713             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
   8714             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
   8715                 if (in.readInt() != 0) {
   8716                     makeProcessState(i, in);
   8717                 } else {
   8718                     mProcessStateTimer[i] = null;
   8719                 }
   8720             }
   8721             if (in.readInt() != 0) {
   8722                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
   8723                         mBsi.mOnBatteryTimeBase, in);
   8724             } else {
   8725                 mVibratorOnTimer = null;
   8726             }
   8727             if (in.readInt() != 0) {
   8728                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
   8729                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
   8730                     mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
   8731                 }
   8732             } else {
   8733                 mUserActivityCounters = null;
   8734             }
   8735             if (in.readInt() != 0) {
   8736                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   8737                 mNetworkPacketActivityCounters
   8738                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
   8739                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   8740                     mNetworkByteActivityCounters[i]
   8741                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   8742                     mNetworkPacketActivityCounters[i]
   8743                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   8744                 }
   8745                 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   8746                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   8747             } else {
   8748                 mNetworkByteActivityCounters = null;
   8749                 mNetworkPacketActivityCounters = null;
   8750             }
   8751 
   8752             if (in.readInt() != 0) {
   8753                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   8754                         NUM_WIFI_TX_LEVELS, in);
   8755             } else {
   8756                 mWifiControllerActivity = null;
   8757             }
   8758 
   8759             if (in.readInt() != 0) {
   8760                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   8761                         NUM_BT_TX_LEVELS, in);
   8762             } else {
   8763                 mBluetoothControllerActivity = null;
   8764             }
   8765 
   8766             if (in.readInt() != 0) {
   8767                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
   8768                         ModemActivityInfo.TX_POWER_LEVELS, in);
   8769             } else {
   8770                 mModemControllerActivity = null;
   8771             }
   8772 
   8773             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   8774             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   8775 
   8776             if (in.readInt() != 0) {
   8777                 int numCpuClusters = in.readInt();
   8778                 if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
   8779                     throw new ParcelFormatException("Incompatible number of cpu clusters");
   8780                 }
   8781 
   8782                 mCpuClusterSpeedTimesUs = new LongSamplingCounter[numCpuClusters][];
   8783                 for (int cluster = 0; cluster < numCpuClusters; cluster++) {
   8784                     if (in.readInt() != 0) {
   8785                         int numSpeeds = in.readInt();
   8786                         if (mBsi.mPowerProfile != null &&
   8787                                 mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
   8788                             throw new ParcelFormatException("Incompatible number of cpu speeds");
   8789                         }
   8790 
   8791                         final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
   8792                         mCpuClusterSpeedTimesUs[cluster] = cpuSpeeds;
   8793                         for (int speed = 0; speed < numSpeeds; speed++) {
   8794                             if (in.readInt() != 0) {
   8795                                 cpuSpeeds[speed] = new LongSamplingCounter(
   8796                                         mBsi.mOnBatteryTimeBase, in);
   8797                             }
   8798                         }
   8799                     } else {
   8800                         mCpuClusterSpeedTimesUs[cluster] = null;
   8801                     }
   8802                 }
   8803             } else {
   8804                 mCpuClusterSpeedTimesUs = null;
   8805             }
   8806 
   8807             mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
   8808             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
   8809                     in, mBsi.mOnBatteryScreenOffTimeBase);
   8810 
   8811             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   8812             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
   8813 
   8814             int length = in.readInt();
   8815             if (length == NUM_PROCESS_STATE) {
   8816                 mProcStateTimeMs = new LongSamplingCounterArray[length];
   8817                 for (int procState = 0; procState < length; ++procState) {
   8818                     mProcStateTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
   8819                             in, mBsi.mOnBatteryTimeBase);
   8820                 }
   8821             } else {
   8822                 mProcStateTimeMs = null;
   8823             }
   8824             length = in.readInt();
   8825             if (length == NUM_PROCESS_STATE) {
   8826                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
   8827                 for (int procState = 0; procState < length; ++procState) {
   8828                     mProcStateScreenOffTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
   8829                             in, mBsi.mOnBatteryScreenOffTimeBase);
   8830                 }
   8831             } else {
   8832                 mProcStateScreenOffTimeMs = null;
   8833             }
   8834 
   8835             if (in.readInt() != 0) {
   8836                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   8837             } else {
   8838                 mMobileRadioApWakeupCount = null;
   8839             }
   8840 
   8841             if (in.readInt() != 0) {
   8842                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
   8843             } else {
   8844                 mWifiRadioApWakeupCount = null;
   8845             }
   8846         }
   8847 
   8848         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
   8849             mJobsDeferredEventCount.addAtomic(1);
   8850             mJobsDeferredCount.addAtomic(numDeferred);
   8851             if (sinceLast != 0) {
   8852                 // Add the total time, which can be divided by the event count to get an average
   8853                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
   8854                 // Also keep track of how many times there were in these different buckets.
   8855                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
   8856                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
   8857                         if (mJobsFreshnessBuckets[i] == null) {
   8858                             mJobsFreshnessBuckets[i] = new Counter(
   8859                                     mBsi.mOnBatteryTimeBase);
   8860                         }
   8861                         mJobsFreshnessBuckets[i].addAtomic(1);
   8862                         break;
   8863                     }
   8864                 }
   8865             }
   8866         }
   8867 
   8868         /**
   8869          * The statistics associated with a particular wake lock.
   8870          */
   8871         public static class Wakelock extends BatteryStats.Uid.Wakelock {
   8872             /**
   8873              * BatteryStatsImpl that we are associated with.
   8874              */
   8875             protected BatteryStatsImpl mBsi;
   8876 
   8877             /**
   8878              * BatteryStatsImpl that we are associated with.
   8879              */
   8880             protected Uid mUid;
   8881 
   8882             /**
   8883              * How long (in ms) this uid has been keeping the device partially awake.
   8884              * Tracks both the total time and the time while the app was in the background.
   8885              */
   8886             DualTimer mTimerPartial;
   8887 
   8888             /**
   8889              * How long (in ms) this uid has been keeping the device fully awake.
   8890              */
   8891             StopwatchTimer mTimerFull;
   8892 
   8893             /**
   8894              * How long (in ms) this uid has had a window keeping the device awake.
   8895              */
   8896             StopwatchTimer mTimerWindow;
   8897 
   8898             /**
   8899              * How long (in ms) this uid has had a draw wake lock.
   8900              */
   8901             StopwatchTimer mTimerDraw;
   8902 
   8903             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
   8904                 mBsi = bsi;
   8905                 mUid = uid;
   8906             }
   8907 
   8908             /**
   8909              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
   8910              * proper timer pool from the given BatteryStatsImpl object.
   8911              *
   8912              * @param in the Parcel to be read from.
   8913              * return a new Timer, or null.
   8914              */
   8915             private StopwatchTimer readStopwatchTimerFromParcel(int type,
   8916                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
   8917                 if (in.readInt() == 0) {
   8918                     return null;
   8919                 }
   8920 
   8921                 return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
   8922             }
   8923 
   8924             /**
   8925              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
   8926              * proper timer pool from the given BatteryStatsImpl object.
   8927              *
   8928              * @param in the Parcel to be read from.
   8929              * return a new Timer, or null.
   8930              */
   8931             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
   8932                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
   8933                 if (in.readInt() == 0) {
   8934                     return null;
   8935                 }
   8936 
   8937                 return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
   8938             }
   8939 
   8940             boolean reset() {
   8941                 boolean wlactive = false;
   8942                 if (mTimerFull != null) {
   8943                     wlactive |= !mTimerFull.reset(false);
   8944                 }
   8945                 if (mTimerPartial != null) {
   8946                     wlactive |= !mTimerPartial.reset(false);
   8947                 }
   8948                 if (mTimerWindow != null) {
   8949                     wlactive |= !mTimerWindow.reset(false);
   8950                 }
   8951                 if (mTimerDraw != null) {
   8952                     wlactive |= !mTimerDraw.reset(false);
   8953                 }
   8954                 if (!wlactive) {
   8955                     if (mTimerFull != null) {
   8956                         mTimerFull.detach();
   8957                         mTimerFull = null;
   8958                     }
   8959                     if (mTimerPartial != null) {
   8960                         mTimerPartial.detach();
   8961                         mTimerPartial = null;
   8962                     }
   8963                     if (mTimerWindow != null) {
   8964                         mTimerWindow.detach();
   8965                         mTimerWindow = null;
   8966                     }
   8967                     if (mTimerDraw != null) {
   8968                         mTimerDraw.detach();
   8969                         mTimerDraw = null;
   8970                     }
   8971                 }
   8972                 return !wlactive;
   8973             }
   8974 
   8975             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
   8976                     TimeBase screenOffBgTimeBase, Parcel in) {
   8977                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
   8978                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
   8979                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
   8980                         mBsi.mFullTimers, timeBase, in);
   8981                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
   8982                         mBsi.mWindowTimers, timeBase, in);
   8983                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
   8984                         mBsi.mDrawTimers, timeBase, in);
   8985             }
   8986 
   8987             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
   8988                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
   8989                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
   8990                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
   8991                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
   8992             }
   8993 
   8994             @Override
   8995             public Timer getWakeTime(int type) {
   8996                 switch (type) {
   8997                 case WAKE_TYPE_FULL: return mTimerFull;
   8998                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
   8999                 case WAKE_TYPE_WINDOW: return mTimerWindow;
   9000                 case WAKE_TYPE_DRAW: return mTimerDraw;
   9001                 default: throw new IllegalArgumentException("type = " + type);
   9002                 }
   9003             }
   9004         }
   9005 
   9006         public static class Sensor extends BatteryStats.Uid.Sensor {
   9007             /**
   9008              * BatteryStatsImpl that we are associated with.
   9009              */
   9010             protected BatteryStatsImpl mBsi;
   9011 
   9012             /**
   9013              * Uid that we are associated with.
   9014              */
   9015             protected Uid mUid;
   9016 
   9017             final int mHandle;
   9018             DualTimer mTimer;
   9019 
   9020             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
   9021                 mBsi = bsi;
   9022                 mUid = uid;
   9023                 mHandle = handle;
   9024             }
   9025 
   9026             private DualTimer readTimersFromParcel(
   9027                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
   9028                 if (in.readInt() == 0) {
   9029                     return null;
   9030                 }
   9031 
   9032                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
   9033                 if (pool == null) {
   9034                     pool = new ArrayList<StopwatchTimer>();
   9035                     mBsi.mSensorTimers.put(mHandle, pool);
   9036                 }
   9037                 return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
   9038             }
   9039 
   9040             boolean reset() {
   9041                 if (mTimer.reset(true)) {
   9042                     mTimer = null;
   9043                     return true;
   9044                 }
   9045                 return false;
   9046             }
   9047 
   9048             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
   9049                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
   9050             }
   9051 
   9052             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
   9053                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
   9054             }
   9055 
   9056             @Override
   9057             public Timer getSensorTime() {
   9058                 return mTimer;
   9059             }
   9060 
   9061             @Override
   9062             public Timer getSensorBackgroundTime() {
   9063                 if (mTimer == null) {
   9064                     return null;
   9065                 }
   9066                 return mTimer.getSubTimer();
   9067             }
   9068 
   9069             @Override
   9070             public int getHandle() {
   9071                 return mHandle;
   9072             }
   9073         }
   9074 
   9075         /**
   9076          * The statistics associated with a particular process.
   9077          */
   9078         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
   9079             /**
   9080              * BatteryStatsImpl that we are associated with.
   9081              */
   9082             protected BatteryStatsImpl mBsi;
   9083 
   9084             /**
   9085              * The name of this process.
   9086              */
   9087             final String mName;
   9088 
   9089             /**
   9090              * Remains true until removed from the stats.
   9091              */
   9092             boolean mActive = true;
   9093 
   9094             /**
   9095              * Total time (in ms) spent executing in user code.
   9096              */
   9097             long mUserTime;
   9098 
   9099             /**
   9100              * Total time (in ms) spent executing in kernel code.
   9101              */
   9102             long mSystemTime;
   9103 
   9104             /**
   9105              * Amount of time (in ms) the process was running in the foreground.
   9106              */
   9107             long mForegroundTime;
   9108 
   9109             /**
   9110              * Number of times the process has been started.
   9111              */
   9112             int mStarts;
   9113 
   9114             /**
   9115              * Number of times the process has crashed.
   9116              */
   9117             int mNumCrashes;
   9118 
   9119             /**
   9120              * Number of times the process has had an ANR.
   9121              */
   9122             int mNumAnrs;
   9123 
   9124             /**
   9125              * The amount of user time loaded from a previous save.
   9126              */
   9127             long mLoadedUserTime;
   9128 
   9129             /**
   9130              * The amount of system time loaded from a previous save.
   9131              */
   9132             long mLoadedSystemTime;
   9133 
   9134             /**
   9135              * The amount of foreground time loaded from a previous save.
   9136              */
   9137             long mLoadedForegroundTime;
   9138 
   9139             /**
   9140              * The number of times the process has started from a previous save.
   9141              */
   9142             int mLoadedStarts;
   9143 
   9144             /**
   9145              * Number of times the process has crashed from a previous save.
   9146              */
   9147             int mLoadedNumCrashes;
   9148 
   9149             /**
   9150              * Number of times the process has had an ANR from a previous save.
   9151              */
   9152             int mLoadedNumAnrs;
   9153 
   9154             /**
   9155              * The amount of user time when last unplugged.
   9156              */
   9157             long mUnpluggedUserTime;
   9158 
   9159             /**
   9160              * The amount of system time when last unplugged.
   9161              */
   9162             long mUnpluggedSystemTime;
   9163 
   9164             /**
   9165              * The amount of foreground time since unplugged.
   9166              */
   9167             long mUnpluggedForegroundTime;
   9168 
   9169             /**
   9170              * The number of times the process has started before unplugged.
   9171              */
   9172             int mUnpluggedStarts;
   9173 
   9174             /**
   9175              * Number of times the process has crashed before unplugged.
   9176              */
   9177             int mUnpluggedNumCrashes;
   9178 
   9179             /**
   9180              * Number of times the process has had an ANR before unplugged.
   9181              */
   9182             int mUnpluggedNumAnrs;
   9183 
   9184             ArrayList<ExcessivePower> mExcessivePower;
   9185 
   9186             public Proc(BatteryStatsImpl bsi, String name) {
   9187                 mBsi = bsi;
   9188                 mName = name;
   9189                 mBsi.mOnBatteryTimeBase.add(this);
   9190             }
   9191 
   9192             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   9193                 mUnpluggedUserTime = mUserTime;
   9194                 mUnpluggedSystemTime = mSystemTime;
   9195                 mUnpluggedForegroundTime = mForegroundTime;
   9196                 mUnpluggedStarts = mStarts;
   9197                 mUnpluggedNumCrashes = mNumCrashes;
   9198                 mUnpluggedNumAnrs = mNumAnrs;
   9199             }
   9200 
   9201             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   9202             }
   9203 
   9204             void detach() {
   9205                 mActive = false;
   9206                 mBsi.mOnBatteryTimeBase.remove(this);
   9207             }
   9208 
   9209             public int countExcessivePowers() {
   9210                 return mExcessivePower != null ? mExcessivePower.size() : 0;
   9211             }
   9212 
   9213             public ExcessivePower getExcessivePower(int i) {
   9214                 if (mExcessivePower != null) {
   9215                     return mExcessivePower.get(i);
   9216                 }
   9217                 return null;
   9218             }
   9219 
   9220             public void addExcessiveCpu(long overTime, long usedTime) {
   9221                 if (mExcessivePower == null) {
   9222                     mExcessivePower = new ArrayList<ExcessivePower>();
   9223                 }
   9224                 ExcessivePower ew = new ExcessivePower();
   9225                 ew.type = ExcessivePower.TYPE_CPU;
   9226                 ew.overTime = overTime;
   9227                 ew.usedTime = usedTime;
   9228                 mExcessivePower.add(ew);
   9229             }
   9230 
   9231             void writeExcessivePowerToParcelLocked(Parcel out) {
   9232                 if (mExcessivePower == null) {
   9233                     out.writeInt(0);
   9234                     return;
   9235                 }
   9236 
   9237                 final int N = mExcessivePower.size();
   9238                 out.writeInt(N);
   9239                 for (int i=0; i<N; i++) {
   9240                     ExcessivePower ew = mExcessivePower.get(i);
   9241                     out.writeInt(ew.type);
   9242                     out.writeLong(ew.overTime);
   9243                     out.writeLong(ew.usedTime);
   9244                 }
   9245             }
   9246 
   9247             void readExcessivePowerFromParcelLocked(Parcel in) {
   9248                 final int N = in.readInt();
   9249                 if (N == 0) {
   9250                     mExcessivePower = null;
   9251                     return;
   9252                 }
   9253 
   9254                 if (N > 10000) {
   9255                     throw new ParcelFormatException(
   9256                             "File corrupt: too many excessive power entries " + N);
   9257                 }
   9258 
   9259                 mExcessivePower = new ArrayList<>();
   9260                 for (int i=0; i<N; i++) {
   9261                     ExcessivePower ew = new ExcessivePower();
   9262                     ew.type = in.readInt();
   9263                     ew.overTime = in.readLong();
   9264                     ew.usedTime = in.readLong();
   9265                     mExcessivePower.add(ew);
   9266                 }
   9267             }
   9268 
   9269             void writeToParcelLocked(Parcel out) {
   9270                 out.writeLong(mUserTime);
   9271                 out.writeLong(mSystemTime);
   9272                 out.writeLong(mForegroundTime);
   9273                 out.writeInt(mStarts);
   9274                 out.writeInt(mNumCrashes);
   9275                 out.writeInt(mNumAnrs);
   9276                 out.writeLong(mLoadedUserTime);
   9277                 out.writeLong(mLoadedSystemTime);
   9278                 out.writeLong(mLoadedForegroundTime);
   9279                 out.writeInt(mLoadedStarts);
   9280                 out.writeInt(mLoadedNumCrashes);
   9281                 out.writeInt(mLoadedNumAnrs);
   9282                 out.writeLong(mUnpluggedUserTime);
   9283                 out.writeLong(mUnpluggedSystemTime);
   9284                 out.writeLong(mUnpluggedForegroundTime);
   9285                 out.writeInt(mUnpluggedStarts);
   9286                 out.writeInt(mUnpluggedNumCrashes);
   9287                 out.writeInt(mUnpluggedNumAnrs);
   9288                 writeExcessivePowerToParcelLocked(out);
   9289             }
   9290 
   9291             void readFromParcelLocked(Parcel in) {
   9292                 mUserTime = in.readLong();
   9293                 mSystemTime = in.readLong();
   9294                 mForegroundTime = in.readLong();
   9295                 mStarts = in.readInt();
   9296                 mNumCrashes = in.readInt();
   9297                 mNumAnrs = in.readInt();
   9298                 mLoadedUserTime = in.readLong();
   9299                 mLoadedSystemTime = in.readLong();
   9300                 mLoadedForegroundTime = in.readLong();
   9301                 mLoadedStarts = in.readInt();
   9302                 mLoadedNumCrashes = in.readInt();
   9303                 mLoadedNumAnrs = in.readInt();
   9304                 mUnpluggedUserTime = in.readLong();
   9305                 mUnpluggedSystemTime = in.readLong();
   9306                 mUnpluggedForegroundTime = in.readLong();
   9307                 mUnpluggedStarts = in.readInt();
   9308                 mUnpluggedNumCrashes = in.readInt();
   9309                 mUnpluggedNumAnrs = in.readInt();
   9310                 readExcessivePowerFromParcelLocked(in);
   9311             }
   9312 
   9313             public void addCpuTimeLocked(int utime, int stime) {
   9314                 addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
   9315             }
   9316 
   9317             public void addCpuTimeLocked(int utime, int stime, boolean isRunning) {
   9318                 if (isRunning) {
   9319                     mUserTime += utime;
   9320                     mSystemTime += stime;
   9321                 }
   9322             }
   9323 
   9324             public void addForegroundTimeLocked(long ttime) {
   9325                 mForegroundTime += ttime;
   9326             }
   9327 
   9328             public void incStartsLocked() {
   9329                 mStarts++;
   9330             }
   9331 
   9332             public void incNumCrashesLocked() {
   9333                 mNumCrashes++;
   9334             }
   9335 
   9336             public void incNumAnrsLocked() {
   9337                 mNumAnrs++;
   9338             }
   9339 
   9340             @Override
   9341             public boolean isActive() {
   9342                 return mActive;
   9343             }
   9344 
   9345             @Override
   9346             public long getUserTime(int which) {
   9347                 long val = mUserTime;
   9348                 if (which == STATS_CURRENT) {
   9349                     val -= mLoadedUserTime;
   9350                 } else if (which == STATS_SINCE_UNPLUGGED) {
   9351                     val -= mUnpluggedUserTime;
   9352                 }
   9353                 return val;
   9354             }
   9355 
   9356             @Override
   9357             public long getSystemTime(int which) {
   9358                 long val = mSystemTime;
   9359                 if (which == STATS_CURRENT) {
   9360                     val -= mLoadedSystemTime;
   9361                 } else if (which == STATS_SINCE_UNPLUGGED) {
   9362                     val -= mUnpluggedSystemTime;
   9363                 }
   9364                 return val;
   9365             }
   9366 
   9367             @Override
   9368             public long getForegroundTime(int which) {
   9369                 long val = mForegroundTime;
   9370                 if (which == STATS_CURRENT) {
   9371                     val -= mLoadedForegroundTime;
   9372                 } else if (which == STATS_SINCE_UNPLUGGED) {
   9373                     val -= mUnpluggedForegroundTime;
   9374                 }
   9375                 return val;
   9376             }
   9377 
   9378             @Override
   9379             public int getStarts(int which) {
   9380                 int val = mStarts;
   9381                 if (which == STATS_CURRENT) {
   9382                     val -= mLoadedStarts;
   9383                 } else if (which == STATS_SINCE_UNPLUGGED) {
   9384                     val -= mUnpluggedStarts;
   9385                 }
   9386                 return val;
   9387             }
   9388 
   9389             @Override
   9390             public int getNumCrashes(int which) {
   9391                 int val = mNumCrashes;
   9392                 if (which == STATS_CURRENT) {
   9393                     val -= mLoadedNumCrashes;
   9394                 } else if (which == STATS_SINCE_UNPLUGGED) {
   9395                     val -= mUnpluggedNumCrashes;
   9396                 }
   9397                 return val;
   9398             }
   9399 
   9400             @Override
   9401             public int getNumAnrs(int which) {
   9402                 int val = mNumAnrs;
   9403                 if (which == STATS_CURRENT) {
   9404                     val -= mLoadedNumAnrs;
   9405                 } else if (which == STATS_SINCE_UNPLUGGED) {
   9406                     val -= mUnpluggedNumAnrs;
   9407                 }
   9408                 return val;
   9409             }
   9410         }
   9411 
   9412         /**
   9413          * The statistics associated with a particular package.
   9414          */
   9415         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
   9416             /**
   9417              * BatteryStatsImpl that we are associated with.
   9418              */
   9419             protected BatteryStatsImpl mBsi;
   9420 
   9421             /**
   9422              * Number of times wakeup alarms have occurred for this app.
   9423              * On screen-off timebase starting in report v25.
   9424              */
   9425             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
   9426 
   9427             /**
   9428              * The statics we have collected for this package's services.
   9429              */
   9430             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
   9431 
   9432             public Pkg(BatteryStatsImpl bsi) {
   9433                 mBsi = bsi;
   9434                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
   9435             }
   9436 
   9437             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
   9438             }
   9439 
   9440             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
   9441             }
   9442 
   9443             void detach() {
   9444                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
   9445             }
   9446 
   9447             void readFromParcelLocked(Parcel in) {
   9448                 int numWA = in.readInt();
   9449                 mWakeupAlarms.clear();
   9450                 for (int i=0; i<numWA; i++) {
   9451                     String tag = in.readString();
   9452                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
   9453                 }
   9454 
   9455                 int numServs = in.readInt();
   9456                 mServiceStats.clear();
   9457                 for (int m = 0; m < numServs; m++) {
   9458                     String serviceName = in.readString();
   9459                     Uid.Pkg.Serv serv = new Serv(mBsi);
   9460                     mServiceStats.put(serviceName, serv);
   9461 
   9462                     serv.readFromParcelLocked(in);
   9463                 }
   9464             }
   9465 
   9466             void writeToParcelLocked(Parcel out) {
   9467                 int numWA = mWakeupAlarms.size();
   9468                 out.writeInt(numWA);
   9469                 for (int i=0; i<numWA; i++) {
   9470                     out.writeString(mWakeupAlarms.keyAt(i));
   9471                     mWakeupAlarms.valueAt(i).writeToParcel(out);
   9472                 }
   9473 
   9474                 final int NS = mServiceStats.size();
   9475                 out.writeInt(NS);
   9476                 for (int i=0; i<NS; i++) {
   9477                     out.writeString(mServiceStats.keyAt(i));
   9478                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
   9479                     serv.writeToParcelLocked(out);
   9480                 }
   9481             }
   9482 
   9483             @Override
   9484             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
   9485                 return mWakeupAlarms;
   9486             }
   9487 
   9488             public void noteWakeupAlarmLocked(String tag) {
   9489                 Counter c = mWakeupAlarms.get(tag);
   9490                 if (c == null) {
   9491                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
   9492                     mWakeupAlarms.put(tag, c);
   9493                 }
   9494                 c.stepAtomic();
   9495             }
   9496 
   9497             @Override
   9498             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
   9499                 return mServiceStats;
   9500             }
   9501 
   9502             /**
   9503              * The statistics associated with a particular service.
   9504              */
   9505             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
   9506                 /**
   9507                  * BatteryStatsImpl that we are associated with.
   9508                  */
   9509                 protected BatteryStatsImpl mBsi;
   9510 
   9511                 /**
   9512                  * The android package in which this service resides.
   9513                  */
   9514                 protected Pkg mPkg;
   9515 
   9516                 /**
   9517                  * Total time (ms in battery uptime) the service has been left started.
   9518                  */
   9519                 protected long mStartTime;
   9520 
   9521                 /**
   9522                  * If service has been started and not yet stopped, this is
   9523                  * when it was started.
   9524                  */
   9525                 protected long mRunningSince;
   9526 
   9527                 /**
   9528                  * True if we are currently running.
   9529                  */
   9530                 protected boolean mRunning;
   9531 
   9532                 /**
   9533                  * Total number of times startService() has been called.
   9534                  */
   9535                 protected int mStarts;
   9536 
   9537                 /**
   9538                  * Total time (ms in battery uptime) the service has been left launched.
   9539                  */
   9540                 protected long mLaunchedTime;
   9541 
   9542                 /**
   9543                  * If service has been launched and not yet exited, this is
   9544                  * when it was launched (ms in battery uptime).
   9545                  */
   9546                 protected long mLaunchedSince;
   9547 
   9548                 /**
   9549                  * True if we are currently launched.
   9550                  */
   9551                 protected boolean mLaunched;
   9552 
   9553                 /**
   9554                  * Total number times the service has been launched.
   9555                  */
   9556                 protected int mLaunches;
   9557 
   9558                 /**
   9559                  * The amount of time spent started loaded from a previous save
   9560                  * (ms in battery uptime).
   9561                  */
   9562                 protected long mLoadedStartTime;
   9563 
   9564                 /**
   9565                  * The number of starts loaded from a previous save.
   9566                  */
   9567                 protected int mLoadedStarts;
   9568 
   9569                 /**
   9570                  * The number of launches loaded from a previous save.
   9571                  */
   9572                 protected int mLoadedLaunches;
   9573 
   9574                 /**
   9575                  * The amount of time spent started as of the last run (ms
   9576                  * in battery uptime).
   9577                  */
   9578                 protected long mLastStartTime;
   9579 
   9580                 /**
   9581                  * The number of starts as of the last run.
   9582                  */
   9583                 protected int mLastStarts;
   9584 
   9585                 /**
   9586                  * The number of launches as of the last run.
   9587                  */
   9588                 protected int mLastLaunches;
   9589 
   9590                 /**
   9591                  * The amount of time spent started when last unplugged (ms
   9592                  * in battery uptime).
   9593                  */
   9594                 protected long mUnpluggedStartTime;
   9595 
   9596                 /**
   9597                  * The number of starts when last unplugged.
   9598                  */
   9599                 protected int mUnpluggedStarts;
   9600 
   9601                 /**
   9602                  * The number of launches when last unplugged.
   9603                  */
   9604                 protected int mUnpluggedLaunches;
   9605 
   9606                 /**
   9607                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
   9608                  */
   9609                 public Serv(BatteryStatsImpl bsi) {
   9610                     mBsi = bsi;
   9611                     mBsi.mOnBatteryTimeBase.add(this);
   9612                 }
   9613 
   9614                 public void onTimeStarted(long elapsedRealtime, long baseUptime,
   9615                         long baseRealtime) {
   9616                     mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
   9617                     mUnpluggedStarts = mStarts;
   9618                     mUnpluggedLaunches = mLaunches;
   9619                 }
   9620 
   9621                 public void onTimeStopped(long elapsedRealtime, long baseUptime,
   9622                         long baseRealtime) {
   9623                 }
   9624 
   9625                 /**
   9626                  * Remove this Serv as a listener from the time base.
   9627                  */
   9628                 public void detach() {
   9629                     mBsi.mOnBatteryTimeBase.remove(this);
   9630                 }
   9631 
   9632                 public void readFromParcelLocked(Parcel in) {
   9633                     mStartTime = in.readLong();
   9634                     mRunningSince = in.readLong();
   9635                     mRunning = in.readInt() != 0;
   9636                     mStarts = in.readInt();
   9637                     mLaunchedTime = in.readLong();
   9638                     mLaunchedSince = in.readLong();
   9639                     mLaunched = in.readInt() != 0;
   9640                     mLaunches = in.readInt();
   9641                     mLoadedStartTime = in.readLong();
   9642                     mLoadedStarts = in.readInt();
   9643                     mLoadedLaunches = in.readInt();
   9644                     mLastStartTime = 0;
   9645                     mLastStarts = 0;
   9646                     mLastLaunches = 0;
   9647                     mUnpluggedStartTime = in.readLong();
   9648                     mUnpluggedStarts = in.readInt();
   9649                     mUnpluggedLaunches = in.readInt();
   9650                 }
   9651 
   9652                 public void writeToParcelLocked(Parcel out) {
   9653                     out.writeLong(mStartTime);
   9654                     out.writeLong(mRunningSince);
   9655                     out.writeInt(mRunning ? 1 : 0);
   9656                     out.writeInt(mStarts);
   9657                     out.writeLong(mLaunchedTime);
   9658                     out.writeLong(mLaunchedSince);
   9659                     out.writeInt(mLaunched ? 1 : 0);
   9660                     out.writeInt(mLaunches);
   9661                     out.writeLong(mLoadedStartTime);
   9662                     out.writeInt(mLoadedStarts);
   9663                     out.writeInt(mLoadedLaunches);
   9664                     out.writeLong(mUnpluggedStartTime);
   9665                     out.writeInt(mUnpluggedStarts);
   9666                     out.writeInt(mUnpluggedLaunches);
   9667                 }
   9668 
   9669                 public long getLaunchTimeToNowLocked(long batteryUptime) {
   9670                     if (!mLaunched) return mLaunchedTime;
   9671                     return mLaunchedTime + batteryUptime - mLaunchedSince;
   9672                 }
   9673 
   9674                 public long getStartTimeToNowLocked(long batteryUptime) {
   9675                     if (!mRunning) return mStartTime;
   9676                     return mStartTime + batteryUptime - mRunningSince;
   9677                 }
   9678 
   9679                 public void startLaunchedLocked() {
   9680                     if (!mLaunched) {
   9681                         mLaunches++;
   9682                         mLaunchedSince = mBsi.getBatteryUptimeLocked();
   9683                         mLaunched = true;
   9684                     }
   9685                 }
   9686 
   9687                 public void stopLaunchedLocked() {
   9688                     if (mLaunched) {
   9689                         long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
   9690                         if (time > 0) {
   9691                             mLaunchedTime += time;
   9692                         } else {
   9693                             mLaunches--;
   9694                         }
   9695                         mLaunched = false;
   9696                     }
   9697                 }
   9698 
   9699                 public void startRunningLocked() {
   9700                     if (!mRunning) {
   9701                         mStarts++;
   9702                         mRunningSince = mBsi.getBatteryUptimeLocked();
   9703                         mRunning = true;
   9704                     }
   9705                 }
   9706 
   9707                 public void stopRunningLocked() {
   9708                     if (mRunning) {
   9709                         long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
   9710                         if (time > 0) {
   9711                             mStartTime += time;
   9712                         } else {
   9713                             mStarts--;
   9714                         }
   9715                         mRunning = false;
   9716                     }
   9717                 }
   9718 
   9719                 public BatteryStatsImpl getBatteryStats() {
   9720                     return mBsi;
   9721                 }
   9722 
   9723                 @Override
   9724                 public int getLaunches(int which) {
   9725                     int val = mLaunches;
   9726                     if (which == STATS_CURRENT) {
   9727                         val -= mLoadedLaunches;
   9728                     } else if (which == STATS_SINCE_UNPLUGGED) {
   9729                         val -= mUnpluggedLaunches;
   9730                     }
   9731                     return val;
   9732                 }
   9733 
   9734                 @Override
   9735                 public long getStartTime(long now, int which) {
   9736                     long val = getStartTimeToNowLocked(now);
   9737                     if (which == STATS_CURRENT) {
   9738                         val -= mLoadedStartTime;
   9739                     } else if (which == STATS_SINCE_UNPLUGGED) {
   9740                         val -= mUnpluggedStartTime;
   9741                     }
   9742                     return val;
   9743                 }
   9744 
   9745                 @Override
   9746                 public int getStarts(int which) {
   9747                     int val = mStarts;
   9748                     if (which == STATS_CURRENT) {
   9749                         val -= mLoadedStarts;
   9750                     } else if (which == STATS_SINCE_UNPLUGGED) {
   9751                         val -= mUnpluggedStarts;
   9752                     }
   9753 
   9754                     return val;
   9755                 }
   9756             }
   9757 
   9758             final Serv newServiceStatsLocked() {
   9759                 return new Serv(mBsi);
   9760             }
   9761         }
   9762 
   9763         /**
   9764          * Retrieve the statistics object for a particular process, creating
   9765          * if needed.
   9766          */
   9767         public Proc getProcessStatsLocked(String name) {
   9768             Proc ps = mProcessStats.get(name);
   9769             if (ps == null) {
   9770                 ps = new Proc(mBsi, name);
   9771                 mProcessStats.put(name, ps);
   9772             }
   9773 
   9774             return ps;
   9775         }
   9776 
   9777         @GuardedBy("mBsi")
   9778         public void updateUidProcessStateLocked(int procState) {
   9779             int uidRunningState;
   9780             // Make special note of Foreground Services
   9781             final boolean userAwareService =
   9782                     (procState == ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
   9783             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
   9784 
   9785             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
   9786                 return;
   9787             }
   9788 
   9789             final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
   9790             if (mProcessState != uidRunningState) {
   9791                 final long uptimeMs = mBsi.mClocks.uptimeMillis();
   9792 
   9793                 if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
   9794                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
   9795 
   9796                     if (mBsi.trackPerProcStateCpuTimes()) {
   9797                         if (mBsi.mPendingUids.size() == 0) {
   9798                             mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
   9799                                     mBsi.mOnBatteryTimeBase.isRunning(),
   9800                                     mBsi.mOnBatteryScreenOffTimeBase.isRunning(),
   9801                                     mBsi.mConstants.PROC_STATE_CPU_TIMES_READ_DELAY_MS);
   9802                             mBsi.mNumSingleUidCpuTimeReads++;
   9803                         } else {
   9804                             mBsi.mNumBatchedSingleUidCpuTimeReads++;
   9805                         }
   9806                         if (mBsi.mPendingUids.indexOfKey(mUid) < 0
   9807                                 || ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
   9808                             mBsi.mPendingUids.put(mUid, mProcessState);
   9809                         }
   9810                     } else {
   9811                         mBsi.mPendingUids.clear();
   9812                     }
   9813                 }
   9814                 mProcessState = uidRunningState;
   9815                 if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
   9816                     if (mProcessStateTimer[uidRunningState] == null) {
   9817                         makeProcessState(uidRunningState, null);
   9818                     }
   9819                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
   9820                 }
   9821 
   9822                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
   9823                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
   9824             }
   9825 
   9826             if (userAwareService != mInForegroundService) {
   9827                 if (userAwareService) {
   9828                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
   9829                 } else {
   9830                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
   9831                 }
   9832                 mInForegroundService = userAwareService;
   9833             }
   9834         }
   9835 
   9836         /** Whether to consider Uid to be in the background for background timebase purposes. */
   9837         public boolean isInBackground() {
   9838             // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
   9839             // also considered to be 'background' for our purposes, because it's not foreground.
   9840             return mProcessState >= PROCESS_STATE_BACKGROUND;
   9841         }
   9842 
   9843         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
   9844             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
   9845             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
   9846         }
   9847 
   9848         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
   9849             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
   9850             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
   9851         }
   9852 
   9853         public SparseArray<? extends Pid> getPidStats() {
   9854             return mPids;
   9855         }
   9856 
   9857         public Pid getPidStatsLocked(int pid) {
   9858             Pid p = mPids.get(pid);
   9859             if (p == null) {
   9860                 p = new Pid();
   9861                 mPids.put(pid, p);
   9862             }
   9863             return p;
   9864         }
   9865 
   9866         /**
   9867          * Retrieve the statistics object for a particular service, creating
   9868          * if needed.
   9869          */
   9870         public Pkg getPackageStatsLocked(String name) {
   9871             Pkg ps = mPackageStats.get(name);
   9872             if (ps == null) {
   9873                 ps = new Pkg(mBsi);
   9874                 mPackageStats.put(name, ps);
   9875             }
   9876 
   9877             return ps;
   9878         }
   9879 
   9880         /**
   9881          * Retrieve the statistics object for a particular service, creating
   9882          * if needed.
   9883          */
   9884         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
   9885             Pkg ps = getPackageStatsLocked(pkg);
   9886             Pkg.Serv ss = ps.mServiceStats.get(serv);
   9887             if (ss == null) {
   9888                 ss = ps.newServiceStatsLocked();
   9889                 ps.mServiceStats.put(serv, ss);
   9890             }
   9891 
   9892             return ss;
   9893         }
   9894 
   9895         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
   9896             DualTimer timer = mSyncStats.instantiateObject();
   9897             timer.readSummaryFromParcelLocked(in);
   9898             mSyncStats.add(name, timer);
   9899         }
   9900 
   9901         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
   9902             DualTimer timer = mJobStats.instantiateObject();
   9903             timer.readSummaryFromParcelLocked(in);
   9904             mJobStats.add(name, timer);
   9905         }
   9906 
   9907         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
   9908             Wakelock wl = new Wakelock(mBsi, this);
   9909             mWakelockStats.add(wlName, wl);
   9910             if (in.readInt() != 0) {
   9911                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
   9912             }
   9913             if (in.readInt() != 0) {
   9914                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
   9915             }
   9916             if (in.readInt() != 0) {
   9917                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
   9918             }
   9919             if (in.readInt() != 0) {
   9920                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
   9921             }
   9922         }
   9923 
   9924         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
   9925             Sensor se = mSensorStats.get(sensor);
   9926             if (se == null) {
   9927                 if (!create) {
   9928                     return null;
   9929                 }
   9930                 se = new Sensor(mBsi, this, sensor);
   9931                 mSensorStats.put(sensor, se);
   9932             }
   9933             DualTimer t = se.mTimer;
   9934             if (t != null) {
   9935                 return t;
   9936             }
   9937             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
   9938             if (timers == null) {
   9939                 timers = new ArrayList<StopwatchTimer>();
   9940                 mBsi.mSensorTimers.put(sensor, timers);
   9941             }
   9942             t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
   9943                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
   9944             se.mTimer = t;
   9945             return t;
   9946         }
   9947 
   9948         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
   9949             DualTimer t = mSyncStats.startObject(name);
   9950             if (t != null) {
   9951                 t.startRunningLocked(elapsedRealtimeMs);
   9952             }
   9953         }
   9954 
   9955         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
   9956             DualTimer t = mSyncStats.stopObject(name);
   9957             if (t != null) {
   9958                 t.stopRunningLocked(elapsedRealtimeMs);
   9959             }
   9960         }
   9961 
   9962         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
   9963             DualTimer t = mJobStats.startObject(name);
   9964             if (t != null) {
   9965                 t.startRunningLocked(elapsedRealtimeMs);
   9966             }
   9967         }
   9968 
   9969         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
   9970             DualTimer t = mJobStats.stopObject(name);
   9971             if (t != null) {
   9972                 t.stopRunningLocked(elapsedRealtimeMs);
   9973             }
   9974             if (mBsi.mOnBatteryTimeBase.isRunning()) {
   9975                 SparseIntArray types = mJobCompletions.get(name);
   9976                 if (types == null) {
   9977                     types = new SparseIntArray();
   9978                     mJobCompletions.put(name, types);
   9979                 }
   9980                 int last = types.get(stopReason, 0);
   9981                 types.put(stopReason, last + 1);
   9982             }
   9983         }
   9984 
   9985         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
   9986             if (wl == null) {
   9987                 return null;
   9988             }
   9989             switch (type) {
   9990                 case WAKE_TYPE_PARTIAL: {
   9991                     DualTimer t = wl.mTimerPartial;
   9992                     if (t == null) {
   9993                         t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
   9994                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
   9995                                 mOnBatteryScreenOffBackgroundTimeBase);
   9996                         wl.mTimerPartial = t;
   9997                     }
   9998                     return t;
   9999                 }
   10000                 case WAKE_TYPE_FULL: {
   10001                     StopwatchTimer t = wl.mTimerFull;
   10002                     if (t == null) {
   10003                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
   10004                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
   10005                         wl.mTimerFull = t;
   10006                     }
   10007                     return t;
   10008                 }
   10009                 case WAKE_TYPE_WINDOW: {
   10010                     StopwatchTimer t = wl.mTimerWindow;
   10011                     if (t == null) {
   10012                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
   10013                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
   10014                         wl.mTimerWindow = t;
   10015                     }
   10016                     return t;
   10017                 }
   10018                 case WAKE_TYPE_DRAW: {
   10019                     StopwatchTimer t = wl.mTimerDraw;
   10020                     if (t == null) {
   10021                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
   10022                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
   10023                         wl.mTimerDraw = t;
   10024                     }
   10025                     return t;
   10026                 }
   10027                 default:
   10028                     throw new IllegalArgumentException("type=" + type);
   10029             }
   10030         }
   10031 
   10032         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
   10033             Wakelock wl = mWakelockStats.startObject(name);
   10034             if (wl != null) {
   10035                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
   10036             }
   10037             if (type == WAKE_TYPE_PARTIAL) {
   10038                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
   10039                 if (pid >= 0) {
   10040                     Pid p = getPidStatsLocked(pid);
   10041                     if (p.mWakeNesting++ == 0) {
   10042                         p.mWakeStartMs = elapsedRealtimeMs;
   10043                     }
   10044                 }
   10045             }
   10046         }
   10047 
   10048         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
   10049             Wakelock wl = mWakelockStats.stopObject(name);
   10050             if (wl != null) {
   10051                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
   10052                 wlt.stopRunningLocked(elapsedRealtimeMs);
   10053             }
   10054             if (type == WAKE_TYPE_PARTIAL) {
   10055                 if (mAggregatedPartialWakelockTimer != null) {
   10056                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
   10057                 }
   10058                 if (pid >= 0) {
   10059                     Pid p = mPids.get(pid);
   10060                     if (p != null && p.mWakeNesting > 0) {
   10061                         if (p.mWakeNesting-- == 1) {
   10062                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
   10063                             p.mWakeStartMs = 0;
   10064                         }
   10065                     }
   10066                 }
   10067             }
   10068         }
   10069 
   10070         public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
   10071             Proc p = getProcessStatsLocked(proc);
   10072             if (p != null) {
   10073                 p.addExcessiveCpu(overTime, usedTime);
   10074             }
   10075         }
   10076 
   10077         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
   10078             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
   10079             t.startRunningLocked(elapsedRealtimeMs);
   10080         }
   10081 
   10082         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
   10083             // Don't create a timer if one doesn't already exist
   10084             DualTimer t = getSensorTimerLocked(sensor, false);
   10085             if (t != null) {
   10086                 t.stopRunningLocked(elapsedRealtimeMs);
   10087             }
   10088         }
   10089 
   10090         public void noteStartGps(long elapsedRealtimeMs) {
   10091             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
   10092         }
   10093 
   10094         public void noteStopGps(long elapsedRealtimeMs) {
   10095             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
   10096         }
   10097 
   10098         public BatteryStatsImpl getBatteryStats() {
   10099             return mBsi;
   10100         }
   10101     }
   10102 
   10103     public long[] getCpuFreqs() {
   10104         return mCpuFreqs;
   10105     }
   10106 
   10107     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
   10108             UserInfoProvider userInfoProvider) {
   10109         this(new SystemClocks(), systemDir, handler, cb, userInfoProvider);
   10110     }
   10111 
   10112     private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
   10113             PlatformIdleStateCallback cb,
   10114             UserInfoProvider userInfoProvider) {
   10115         init(clocks);
   10116 
   10117         if (systemDir != null) {
   10118             mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
   10119                     new File(systemDir, "batterystats.bin.tmp"));
   10120         } else {
   10121             mFile = null;
   10122         }
   10123         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
   10124         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
   10125         mHandler = new MyHandler(handler.getLooper());
   10126         mConstants = new Constants(mHandler);
   10127         mStartCount++;
   10128         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
   10129         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
   10130         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   10131             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
   10132                     mOnBatteryTimeBase);
   10133         }
   10134         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
   10135         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
   10136                 mOnBatteryTimeBase);
   10137         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
   10138                 mOnBatteryTimeBase);
   10139         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
   10140         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
   10141         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
   10142         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
   10143         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   10144             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
   10145                     mOnBatteryTimeBase);
   10146         }
   10147         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
   10148                 mOnBatteryTimeBase);
   10149         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   10150             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
   10151                     mOnBatteryTimeBase);
   10152         }
   10153         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   10154             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
   10155             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
   10156         }
   10157         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
   10158         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
   10159                 NUM_BT_TX_LEVELS);
   10160         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
   10161                 ModemActivityInfo.TX_POWER_LEVELS);
   10162         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
   10163         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
   10164                 mOnBatteryTimeBase);
   10165         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
   10166         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
   10167         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
   10168         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null,
   10169                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
   10170         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
   10171         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
   10172         for (int i=0; i<NUM_WIFI_STATES; i++) {
   10173             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
   10174                     mOnBatteryTimeBase);
   10175         }
   10176         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   10177             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
   10178                     mOnBatteryTimeBase);
   10179         }
   10180         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   10181             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
   10182                     mOnBatteryTimeBase);
   10183         }
   10184         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
   10185         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
   10186             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
   10187                 mOnBatteryTimeBase);
   10188         }
   10189         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
   10190         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
   10191         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
   10192         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
   10193         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
   10194         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
   10195         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
   10196         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
   10197         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
   10198         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
   10199         mOnBattery = mOnBatteryInternal = false;
   10200         long uptime = mClocks.uptimeMillis() * 1000;
   10201         long realtime = mClocks.elapsedRealtime() * 1000;
   10202         initTimes(uptime, realtime);
   10203         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
   10204         mDischargeStartLevel = 0;
   10205         mDischargeUnplugLevel = 0;
   10206         mDischargePlugLevel = -1;
   10207         mDischargeCurrentLevel = 0;
   10208         mCurrentBatteryLevel = 0;
   10209         initDischarge();
   10210         clearHistoryLocked();
   10211         updateDailyDeadlineLocked();
   10212         mPlatformIdleStateCallback = cb;
   10213         mUserInfoProvider = userInfoProvider;
   10214     }
   10215 
   10216     public BatteryStatsImpl(Parcel p) {
   10217         this(new SystemClocks(), p);
   10218     }
   10219 
   10220     public BatteryStatsImpl(Clocks clocks, Parcel p) {
   10221         init(clocks);
   10222         mFile = null;
   10223         mCheckinFile = null;
   10224         mDailyFile = null;
   10225         mHandler = null;
   10226         mExternalSync = null;
   10227         mConstants = new Constants(mHandler);
   10228         clearHistoryLocked();
   10229         readFromParcel(p);
   10230         mPlatformIdleStateCallback = null;
   10231     }
   10232 
   10233     public void setPowerProfileLocked(PowerProfile profile) {
   10234         mPowerProfile = profile;
   10235 
   10236         // We need to initialize the KernelCpuSpeedReaders to read from
   10237         // the first cpu of each core. Once we have the PowerProfile, we have access to this
   10238         // information.
   10239         final int numClusters = mPowerProfile.getNumCpuClusters();
   10240         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
   10241         int firstCpuOfCluster = 0;
   10242         for (int i = 0; i < numClusters; i++) {
   10243             final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
   10244             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
   10245                     numSpeedSteps);
   10246             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
   10247         }
   10248 
   10249         if (mEstimatedBatteryCapacity == -1) {
   10250             // Initialize the estimated battery capacity to a known preset one.
   10251             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
   10252         }
   10253     }
   10254 
   10255     public void setCallback(BatteryCallback cb) {
   10256         mCallback = cb;
   10257     }
   10258 
   10259     public void setRadioScanningTimeoutLocked(long timeout) {
   10260         if (mPhoneSignalScanningTimer != null) {
   10261             mPhoneSignalScanningTimer.setTimeout(timeout);
   10262         }
   10263     }
   10264 
   10265     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
   10266         mExternalSync = sync;
   10267     }
   10268 
   10269     public void updateDailyDeadlineLocked() {
   10270         // Get the current time.
   10271         long currentTime = mDailyStartTime = System.currentTimeMillis();
   10272         Calendar calDeadline = Calendar.getInstance();
   10273         calDeadline.setTimeInMillis(currentTime);
   10274 
   10275         // Move time up to the next day, ranging from 1am to 3pm.
   10276         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
   10277         calDeadline.set(Calendar.MILLISECOND, 0);
   10278         calDeadline.set(Calendar.SECOND, 0);
   10279         calDeadline.set(Calendar.MINUTE, 0);
   10280         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
   10281         mNextMinDailyDeadline = calDeadline.getTimeInMillis();
   10282         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
   10283         mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
   10284     }
   10285 
   10286     public void recordDailyStatsIfNeededLocked(boolean settled) {
   10287         long currentTime = System.currentTimeMillis();
   10288         if (currentTime >= mNextMaxDailyDeadline) {
   10289             recordDailyStatsLocked();
   10290         } else if (settled && currentTime >= mNextMinDailyDeadline) {
   10291             recordDailyStatsLocked();
   10292         } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
   10293             recordDailyStatsLocked();
   10294         }
   10295     }
   10296 
   10297     public void recordDailyStatsLocked() {
   10298         DailyItem item = new DailyItem();
   10299         item.mStartTime = mDailyStartTime;
   10300         item.mEndTime = System.currentTimeMillis();
   10301         boolean hasData = false;
   10302         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
   10303             hasData = true;
   10304             item.mDischargeSteps = new LevelStepTracker(
   10305                     mDailyDischargeStepTracker.mNumStepDurations,
   10306                     mDailyDischargeStepTracker.mStepDurations);
   10307         }
   10308         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
   10309             hasData = true;
   10310             item.mChargeSteps = new LevelStepTracker(
   10311                     mDailyChargeStepTracker.mNumStepDurations,
   10312                     mDailyChargeStepTracker.mStepDurations);
   10313         }
   10314         if (mDailyPackageChanges != null) {
   10315             hasData = true;
   10316             item.mPackageChanges = mDailyPackageChanges;
   10317             mDailyPackageChanges = null;
   10318         }
   10319         mDailyDischargeStepTracker.init();
   10320         mDailyChargeStepTracker.init();
   10321         updateDailyDeadlineLocked();
   10322 
   10323         if (hasData) {
   10324             final long startTime = SystemClock.uptimeMillis();
   10325             mDailyItems.add(item);
   10326             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
   10327                 mDailyItems.remove(0);
   10328             }
   10329             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
   10330             try {
   10331                 XmlSerializer out = new FastXmlSerializer();
   10332                 out.setOutput(memStream, StandardCharsets.UTF_8.name());
   10333                 writeDailyItemsLocked(out);
   10334                 final long initialTime = SystemClock.uptimeMillis() - startTime;
   10335                 BackgroundThread.getHandler().post(new Runnable() {
   10336                     @Override
   10337                     public void run() {
   10338                         synchronized (mCheckinFile) {
   10339                             final long startTime2 = SystemClock.uptimeMillis();
   10340                             FileOutputStream stream = null;
   10341                             try {
   10342                                 stream = mDailyFile.startWrite();
   10343                                 memStream.writeTo(stream);
   10344                                 stream.flush();
   10345                                 FileUtils.sync(stream);
   10346                                 stream.close();
   10347                                 mDailyFile.finishWrite(stream);
   10348                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
   10349                                         "batterystats-daily",
   10350                                         initialTime + SystemClock.uptimeMillis() - startTime2);
   10351                             } catch (IOException e) {
   10352                                 Slog.w("BatteryStats",
   10353                                         "Error writing battery daily items", e);
   10354                                 mDailyFile.failWrite(stream);
   10355                             }
   10356                         }
   10357                     }
   10358                 });
   10359             } catch (IOException e) {
   10360             }
   10361         }
   10362     }
   10363 
   10364     private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
   10365         StringBuilder sb = new StringBuilder(64);
   10366         out.startDocument(null, true);
   10367         out.startTag(null, "daily-items");
   10368         for (int i=0; i<mDailyItems.size(); i++) {
   10369             final DailyItem dit = mDailyItems.get(i);
   10370             out.startTag(null, "item");
   10371             out.attribute(null, "start", Long.toString(dit.mStartTime));
   10372             out.attribute(null, "end", Long.toString(dit.mEndTime));
   10373             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
   10374             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
   10375             if (dit.mPackageChanges != null) {
   10376                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
   10377                     PackageChange pc = dit.mPackageChanges.get(j);
   10378                     if (pc.mUpdate) {
   10379                         out.startTag(null, "upd");
   10380                         out.attribute(null, "pkg", pc.mPackageName);
   10381                         out.attribute(null, "ver", Long.toString(pc.mVersionCode));
   10382                         out.endTag(null, "upd");
   10383                     } else {
   10384                         out.startTag(null, "rem");
   10385                         out.attribute(null, "pkg", pc.mPackageName);
   10386                         out.endTag(null, "rem");
   10387                     }
   10388                 }
   10389             }
   10390             out.endTag(null, "item");
   10391         }
   10392         out.endTag(null, "daily-items");
   10393         out.endDocument();
   10394     }
   10395 
   10396     private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
   10397             StringBuilder tmpBuilder) throws IOException {
   10398         if (steps != null) {
   10399             out.startTag(null, tag);
   10400             out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
   10401             for (int i=0; i<steps.mNumStepDurations; i++) {
   10402                 out.startTag(null, "s");
   10403                 tmpBuilder.setLength(0);
   10404                 steps.encodeEntryAt(i, tmpBuilder);
   10405                 out.attribute(null, "v", tmpBuilder.toString());
   10406                 out.endTag(null, "s");
   10407             }
   10408             out.endTag(null, tag);
   10409         }
   10410     }
   10411 
   10412     public void readDailyStatsLocked() {
   10413         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
   10414         mDailyItems.clear();
   10415         FileInputStream stream;
   10416         try {
   10417             stream = mDailyFile.openRead();
   10418         } catch (FileNotFoundException e) {
   10419             return;
   10420         }
   10421         try {
   10422             XmlPullParser parser = Xml.newPullParser();
   10423             parser.setInput(stream, StandardCharsets.UTF_8.name());
   10424             readDailyItemsLocked(parser);
   10425         } catch (XmlPullParserException e) {
   10426         } finally {
   10427             try {
   10428                 stream.close();
   10429             } catch (IOException e) {
   10430             }
   10431         }
   10432     }
   10433 
   10434     private void readDailyItemsLocked(XmlPullParser parser) {
   10435         try {
   10436             int type;
   10437             while ((type = parser.next()) != XmlPullParser.START_TAG
   10438                     && type != XmlPullParser.END_DOCUMENT) {
   10439                 ;
   10440             }
   10441 
   10442             if (type != XmlPullParser.START_TAG) {
   10443                 throw new IllegalStateException("no start tag found");
   10444             }
   10445 
   10446             int outerDepth = parser.getDepth();
   10447             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   10448                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   10449                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   10450                     continue;
   10451                 }
   10452 
   10453                 String tagName = parser.getName();
   10454                 if (tagName.equals("item")) {
   10455                     readDailyItemTagLocked(parser);
   10456                 } else {
   10457                     Slog.w(TAG, "Unknown element under <daily-items>: "
   10458                             + parser.getName());
   10459                     XmlUtils.skipCurrentTag(parser);
   10460                 }
   10461             }
   10462 
   10463         } catch (IllegalStateException e) {
   10464             Slog.w(TAG, "Failed parsing daily " + e);
   10465         } catch (NullPointerException e) {
   10466             Slog.w(TAG, "Failed parsing daily " + e);
   10467         } catch (NumberFormatException e) {
   10468             Slog.w(TAG, "Failed parsing daily " + e);
   10469         } catch (XmlPullParserException e) {
   10470             Slog.w(TAG, "Failed parsing daily " + e);
   10471         } catch (IOException e) {
   10472             Slog.w(TAG, "Failed parsing daily " + e);
   10473         } catch (IndexOutOfBoundsException e) {
   10474             Slog.w(TAG, "Failed parsing daily " + e);
   10475         }
   10476     }
   10477 
   10478     void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
   10479             XmlPullParserException, IOException {
   10480         DailyItem dit = new DailyItem();
   10481         String attr = parser.getAttributeValue(null, "start");
   10482         if (attr != null) {
   10483             dit.mStartTime = Long.parseLong(attr);
   10484         }
   10485         attr = parser.getAttributeValue(null, "end");
   10486         if (attr != null) {
   10487             dit.mEndTime = Long.parseLong(attr);
   10488         }
   10489         int outerDepth = parser.getDepth();
   10490         int type;
   10491         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   10492                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   10493             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   10494                 continue;
   10495             }
   10496 
   10497             String tagName = parser.getName();
   10498             if (tagName.equals("dis")) {
   10499                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
   10500             } else if (tagName.equals("chg")) {
   10501                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
   10502             } else if (tagName.equals("upd")) {
   10503                 if (dit.mPackageChanges == null) {
   10504                     dit.mPackageChanges = new ArrayList<>();
   10505                 }
   10506                 PackageChange pc = new PackageChange();
   10507                 pc.mUpdate = true;
   10508                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
   10509                 String verStr = parser.getAttributeValue(null, "ver");
   10510                 pc.mVersionCode = verStr != null ? Long.parseLong(verStr) : 0;
   10511                 dit.mPackageChanges.add(pc);
   10512                 XmlUtils.skipCurrentTag(parser);
   10513             } else if (tagName.equals("rem")) {
   10514                 if (dit.mPackageChanges == null) {
   10515                     dit.mPackageChanges = new ArrayList<>();
   10516                 }
   10517                 PackageChange pc = new PackageChange();
   10518                 pc.mUpdate = false;
   10519                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
   10520                 dit.mPackageChanges.add(pc);
   10521                 XmlUtils.skipCurrentTag(parser);
   10522             } else {
   10523                 Slog.w(TAG, "Unknown element under <item>: "
   10524                         + parser.getName());
   10525                 XmlUtils.skipCurrentTag(parser);
   10526             }
   10527         }
   10528         mDailyItems.add(dit);
   10529     }
   10530 
   10531     void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
   10532             String tag)
   10533             throws NumberFormatException, XmlPullParserException, IOException {
   10534         final String numAttr = parser.getAttributeValue(null, "n");
   10535         if (numAttr == null) {
   10536             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
   10537             XmlUtils.skipCurrentTag(parser);
   10538             return;
   10539         }
   10540         final int num = Integer.parseInt(numAttr);
   10541         LevelStepTracker steps = new LevelStepTracker(num);
   10542         if (isCharge) {
   10543             dit.mChargeSteps = steps;
   10544         } else {
   10545             dit.mDischargeSteps = steps;
   10546         }
   10547         int i = 0;
   10548         int outerDepth = parser.getDepth();
   10549         int type;
   10550         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   10551                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   10552             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   10553                 continue;
   10554             }
   10555 
   10556             String tagName = parser.getName();
   10557             if ("s".equals(tagName)) {
   10558                 if (i < num) {
   10559                     String valueAttr = parser.getAttributeValue(null, "v");
   10560                     if (valueAttr != null) {
   10561                         steps.decodeEntryAt(i, valueAttr);
   10562                         i++;
   10563                     }
   10564                 }
   10565             } else {
   10566                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
   10567                         + parser.getName());
   10568                 XmlUtils.skipCurrentTag(parser);
   10569             }
   10570         }
   10571         steps.mNumStepDurations = i;
   10572     }
   10573 
   10574     @Override
   10575     public DailyItem getDailyItemLocked(int daysAgo) {
   10576         int index = mDailyItems.size()-1-daysAgo;
   10577         return index >= 0 ? mDailyItems.get(index) : null;
   10578     }
   10579 
   10580     @Override
   10581     public long getCurrentDailyStartTime() {
   10582         return mDailyStartTime;
   10583     }
   10584 
   10585     @Override
   10586     public long getNextMinDailyDeadline() {
   10587         return mNextMinDailyDeadline;
   10588     }
   10589 
   10590     @Override
   10591     public long getNextMaxDailyDeadline() {
   10592         return mNextMaxDailyDeadline;
   10593     }
   10594 
   10595     @Override
   10596     public boolean startIteratingOldHistoryLocked() {
   10597         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
   10598                 + " pos=" + mHistoryBuffer.dataPosition());
   10599         if ((mHistoryIterator = mHistory) == null) {
   10600             return false;
   10601         }
   10602         mHistoryBuffer.setDataPosition(0);
   10603         mHistoryReadTmp.clear();
   10604         mReadOverflow = false;
   10605         mIteratingHistory = true;
   10606         return true;
   10607     }
   10608 
   10609     @Override
   10610     public boolean getNextOldHistoryLocked(HistoryItem out) {
   10611         boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
   10612         if (!end) {
   10613             readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
   10614             mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
   10615         }
   10616         HistoryItem cur = mHistoryIterator;
   10617         if (cur == null) {
   10618             if (!mReadOverflow && !end) {
   10619                 Slog.w(TAG, "Old history ends before new history!");
   10620             }
   10621             return false;
   10622         }
   10623         out.setTo(cur);
   10624         mHistoryIterator = cur.next;
   10625         if (!mReadOverflow) {
   10626             if (end) {
   10627                 Slog.w(TAG, "New history ends before old history!");
   10628             } else if (!out.same(mHistoryReadTmp)) {
   10629                 PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
   10630                 pw.println("Histories differ!");
   10631                 pw.println("Old history:");
   10632                 (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
   10633                 pw.println("New history:");
   10634                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
   10635                         true);
   10636                 pw.flush();
   10637             }
   10638         }
   10639         return true;
   10640     }
   10641 
   10642     @Override
   10643     public void finishIteratingOldHistoryLocked() {
   10644         mIteratingHistory = false;
   10645         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
   10646         mHistoryIterator = null;
   10647     }
   10648 
   10649     public int getHistoryTotalSize() {
   10650         return MAX_HISTORY_BUFFER;
   10651     }
   10652 
   10653     public int getHistoryUsedSize() {
   10654         return mHistoryBuffer.dataSize();
   10655     }
   10656 
   10657     @Override
   10658     public boolean startIteratingHistoryLocked() {
   10659         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
   10660                 + " pos=" + mHistoryBuffer.dataPosition());
   10661         if (mHistoryBuffer.dataSize() <= 0) {
   10662             return false;
   10663         }
   10664         mHistoryBuffer.setDataPosition(0);
   10665         mReadOverflow = false;
   10666         mIteratingHistory = true;
   10667         mReadHistoryStrings = new String[mHistoryTagPool.size()];
   10668         mReadHistoryUids = new int[mHistoryTagPool.size()];
   10669         mReadHistoryChars = 0;
   10670         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
   10671             final HistoryTag tag = ent.getKey();
   10672             final int idx = ent.getValue();
   10673             mReadHistoryStrings[idx] = tag.string;
   10674             mReadHistoryUids[idx] = tag.uid;
   10675             mReadHistoryChars += tag.string.length() + 1;
   10676         }
   10677         return true;
   10678     }
   10679 
   10680     @Override
   10681     public int getHistoryStringPoolSize() {
   10682         return mReadHistoryStrings.length;
   10683     }
   10684 
   10685     @Override
   10686     public int getHistoryStringPoolBytes() {
   10687         // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
   10688         // Each string character is 2 bytes.
   10689         return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
   10690     }
   10691 
   10692     @Override
   10693     public String getHistoryTagPoolString(int index) {
   10694         return mReadHistoryStrings[index];
   10695     }
   10696 
   10697     @Override
   10698     public int getHistoryTagPoolUid(int index) {
   10699         return mReadHistoryUids[index];
   10700     }
   10701 
   10702     @Override
   10703     public boolean getNextHistoryLocked(HistoryItem out) {
   10704         final int pos = mHistoryBuffer.dataPosition();
   10705         if (pos == 0) {
   10706             out.clear();
   10707         }
   10708         boolean end = pos >= mHistoryBuffer.dataSize();
   10709         if (end) {
   10710             return false;
   10711         }
   10712 
   10713         final long lastRealtime = out.time;
   10714         final long lastWalltime = out.currentTime;
   10715         readHistoryDelta(mHistoryBuffer, out);
   10716         if (out.cmd != HistoryItem.CMD_CURRENT_TIME
   10717                 && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
   10718             out.currentTime = lastWalltime + (out.time - lastRealtime);
   10719         }
   10720         return true;
   10721     }
   10722 
   10723     @Override
   10724     public void finishIteratingHistoryLocked() {
   10725         mIteratingHistory = false;
   10726         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
   10727         mReadHistoryStrings = null;
   10728     }
   10729 
   10730     @Override
   10731     public long getHistoryBaseTime() {
   10732         return mHistoryBaseTime;
   10733     }
   10734 
   10735     @Override
   10736     public int getStartCount() {
   10737         return mStartCount;
   10738     }
   10739 
   10740     public boolean isOnBattery() {
   10741         return mOnBattery;
   10742     }
   10743 
   10744     public boolean isCharging() {
   10745         return mCharging;
   10746     }
   10747 
   10748     public boolean isScreenOn(int state) {
   10749         return state == Display.STATE_ON || state == Display.STATE_VR
   10750             || state == Display.STATE_ON_SUSPEND;
   10751     }
   10752 
   10753     public boolean isScreenOff(int state) {
   10754         return state == Display.STATE_OFF;
   10755     }
   10756 
   10757     public boolean isScreenDoze(int state) {
   10758         return state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND;
   10759     }
   10760 
   10761     void initTimes(long uptime, long realtime) {
   10762         mStartClockTime = System.currentTimeMillis();
   10763         mOnBatteryTimeBase.init(uptime, realtime);
   10764         mOnBatteryScreenOffTimeBase.init(uptime, realtime);
   10765         mRealtime = 0;
   10766         mUptime = 0;
   10767         mRealtimeStart = realtime;
   10768         mUptimeStart = uptime;
   10769     }
   10770 
   10771     void initDischarge() {
   10772         mLowDischargeAmountSinceCharge = 0;
   10773         mHighDischargeAmountSinceCharge = 0;
   10774         mDischargeAmountScreenOn = 0;
   10775         mDischargeAmountScreenOnSinceCharge = 0;
   10776         mDischargeAmountScreenOff = 0;
   10777         mDischargeAmountScreenOffSinceCharge = 0;
   10778         mDischargeAmountScreenDoze = 0;
   10779         mDischargeAmountScreenDozeSinceCharge = 0;
   10780         mDischargeStepTracker.init();
   10781         mChargeStepTracker.init();
   10782         mDischargeScreenOffCounter.reset(false);
   10783         mDischargeScreenDozeCounter.reset(false);
   10784         mDischargeLightDozeCounter.reset(false);
   10785         mDischargeDeepDozeCounter.reset(false);
   10786         mDischargeCounter.reset(false);
   10787     }
   10788 
   10789     public void resetAllStatsCmdLocked() {
   10790         resetAllStatsLocked();
   10791         final long mSecUptime = mClocks.uptimeMillis();
   10792         long uptime = mSecUptime * 1000;
   10793         long mSecRealtime = mClocks.elapsedRealtime();
   10794         long realtime = mSecRealtime * 1000;
   10795         mDischargeStartLevel = mHistoryCur.batteryLevel;
   10796         pullPendingStateUpdatesLocked();
   10797         addHistoryRecordLocked(mSecRealtime, mSecUptime);
   10798         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
   10799                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
   10800         mOnBatteryTimeBase.reset(uptime, realtime);
   10801         mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
   10802         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
   10803             if (isScreenOn(mScreenState)) {
   10804                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
   10805                 mDischargeScreenDozeUnplugLevel = 0;
   10806                 mDischargeScreenOffUnplugLevel = 0;
   10807             } else if (isScreenDoze(mScreenState)) {
   10808                 mDischargeScreenOnUnplugLevel = 0;
   10809                 mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
   10810                 mDischargeScreenOffUnplugLevel = 0;
   10811             } else {
   10812                 mDischargeScreenOnUnplugLevel = 0;
   10813                 mDischargeScreenDozeUnplugLevel = 0;
   10814                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
   10815             }
   10816             mDischargeAmountScreenOn = 0;
   10817             mDischargeAmountScreenOff = 0;
   10818             mDischargeAmountScreenDoze = 0;
   10819         }
   10820         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
   10821     }
   10822 
   10823     private void resetAllStatsLocked() {
   10824         final long uptimeMillis = mClocks.uptimeMillis();
   10825         final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
   10826         mStartCount = 0;
   10827         initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
   10828         mScreenOnTimer.reset(false);
   10829         mScreenDozeTimer.reset(false);
   10830         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   10831             mScreenBrightnessTimer[i].reset(false);
   10832         }
   10833 
   10834         if (mPowerProfile != null) {
   10835             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
   10836         } else {
   10837             mEstimatedBatteryCapacity = -1;
   10838         }
   10839         mMinLearnedBatteryCapacity = -1;
   10840         mMaxLearnedBatteryCapacity = -1;
   10841         mInteractiveTimer.reset(false);
   10842         mPowerSaveModeEnabledTimer.reset(false);
   10843         mLastIdleTimeStart = elapsedRealtimeMillis;
   10844         mLongestLightIdleTime = 0;
   10845         mLongestFullIdleTime = 0;
   10846         mDeviceIdleModeLightTimer.reset(false);
   10847         mDeviceIdleModeFullTimer.reset(false);
   10848         mDeviceLightIdlingTimer.reset(false);
   10849         mDeviceIdlingTimer.reset(false);
   10850         mPhoneOnTimer.reset(false);
   10851         mAudioOnTimer.reset(false);
   10852         mVideoOnTimer.reset(false);
   10853         mFlashlightOnTimer.reset(false);
   10854         mCameraOnTimer.reset(false);
   10855         mBluetoothScanTimer.reset(false);
   10856         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   10857             mPhoneSignalStrengthsTimer[i].reset(false);
   10858         }
   10859         mPhoneSignalScanningTimer.reset(false);
   10860         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   10861             mPhoneDataConnectionsTimer[i].reset(false);
   10862         }
   10863         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   10864             mNetworkByteActivityCounters[i].reset(false);
   10865             mNetworkPacketActivityCounters[i].reset(false);
   10866         }
   10867         mMobileRadioActiveTimer.reset(false);
   10868         mMobileRadioActivePerAppTimer.reset(false);
   10869         mMobileRadioActiveAdjustedTime.reset(false);
   10870         mMobileRadioActiveUnknownTime.reset(false);
   10871         mMobileRadioActiveUnknownCount.reset(false);
   10872         mWifiOnTimer.reset(false);
   10873         mGlobalWifiRunningTimer.reset(false);
   10874         for (int i=0; i<NUM_WIFI_STATES; i++) {
   10875             mWifiStateTimer[i].reset(false);
   10876         }
   10877         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   10878             mWifiSupplStateTimer[i].reset(false);
   10879         }
   10880         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   10881             mWifiSignalStrengthsTimer[i].reset(false);
   10882         }
   10883         mWifiMulticastWakelockTimer.reset(false);
   10884         mWifiActiveTimer.reset(false);
   10885         mWifiActivity.reset(false);
   10886         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
   10887             mGpsSignalQualityTimer[i].reset(false);
   10888         }
   10889         mBluetoothActivity.reset(false);
   10890         mModemActivity.reset(false);
   10891         mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
   10892 
   10893         for (int i=0; i<mUidStats.size(); i++) {
   10894             if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
   10895                 mUidStats.remove(mUidStats.keyAt(i));
   10896                 i--;
   10897             }
   10898         }
   10899 
   10900         if (mRpmStats.size() > 0) {
   10901             for (SamplingTimer timer : mRpmStats.values()) {
   10902                 mOnBatteryTimeBase.remove(timer);
   10903             }
   10904             mRpmStats.clear();
   10905         }
   10906         if (mScreenOffRpmStats.size() > 0) {
   10907             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
   10908                 mOnBatteryScreenOffTimeBase.remove(timer);
   10909             }
   10910             mScreenOffRpmStats.clear();
   10911         }
   10912 
   10913         if (mKernelWakelockStats.size() > 0) {
   10914             for (SamplingTimer timer : mKernelWakelockStats.values()) {
   10915                 mOnBatteryScreenOffTimeBase.remove(timer);
   10916             }
   10917             mKernelWakelockStats.clear();
   10918         }
   10919 
   10920         if (mKernelMemoryStats.size() > 0) {
   10921             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
   10922                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
   10923             }
   10924             mKernelMemoryStats.clear();
   10925         }
   10926 
   10927         if (mWakeupReasonStats.size() > 0) {
   10928             for (SamplingTimer timer : mWakeupReasonStats.values()) {
   10929                 mOnBatteryTimeBase.remove(timer);
   10930             }
   10931             mWakeupReasonStats.clear();
   10932         }
   10933 
   10934         mLastHistoryStepDetails = null;
   10935         mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
   10936         mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
   10937         mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
   10938         mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
   10939         mLastStepStatUserTime = mCurStepStatUserTime = 0;
   10940         mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
   10941         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
   10942         mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
   10943         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
   10944         mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
   10945 
   10946         mNumAllUidCpuTimeReads = 0;
   10947         mNumUidsRemoved = 0;
   10948 
   10949         initDischarge();
   10950 
   10951         clearHistoryLocked();
   10952         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
   10953     }
   10954 
   10955     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
   10956         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
   10957             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
   10958                 // Not recording process starts/stops.
   10959                 continue;
   10960             }
   10961             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
   10962             if (active == null) {
   10963                 continue;
   10964             }
   10965             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
   10966                 SparseIntArray uids = ent.getValue();
   10967                 for (int j=0; j<uids.size(); j++) {
   10968                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
   10969                             uids.keyAt(j));
   10970                 }
   10971             }
   10972         }
   10973     }
   10974 
   10975     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
   10976         updateOldDischargeScreenLevelLocked(oldState);
   10977         updateNewDischargeScreenLevelLocked(newState);
   10978     }
   10979 
   10980     private void updateOldDischargeScreenLevelLocked(int state) {
   10981         if (isScreenOn(state)) {
   10982             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
   10983             if (diff > 0) {
   10984                 mDischargeAmountScreenOn += diff;
   10985                 mDischargeAmountScreenOnSinceCharge += diff;
   10986             }
   10987         } else if (isScreenDoze(state)) {
   10988             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
   10989             if (diff > 0) {
   10990                 mDischargeAmountScreenDoze += diff;
   10991                 mDischargeAmountScreenDozeSinceCharge += diff;
   10992             }
   10993         } else if (isScreenOff(state)){
   10994             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
   10995             if (diff > 0) {
   10996                 mDischargeAmountScreenOff += diff;
   10997                 mDischargeAmountScreenOffSinceCharge += diff;
   10998             }
   10999         }
   11000     }
   11001 
   11002     private void updateNewDischargeScreenLevelLocked(int state) {
   11003         if (isScreenOn(state)) {
   11004             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
   11005             mDischargeScreenOffUnplugLevel = 0;
   11006             mDischargeScreenDozeUnplugLevel = 0;
   11007         } else if (isScreenDoze(state)){
   11008             mDischargeScreenOnUnplugLevel = 0;
   11009             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
   11010             mDischargeScreenOffUnplugLevel = 0;
   11011         } else if (isScreenOff(state)) {
   11012             mDischargeScreenOnUnplugLevel = 0;
   11013             mDischargeScreenDozeUnplugLevel = 0;
   11014             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
   11015         }
   11016     }
   11017 
   11018     public void pullPendingStateUpdatesLocked() {
   11019         if (mOnBatteryInternal) {
   11020             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
   11021         }
   11022     }
   11023 
   11024     private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
   11025     private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
   11026 
   11027     private final Object mWifiNetworkLock = new Object();
   11028 
   11029     @GuardedBy("mWifiNetworkLock")
   11030     private String[] mWifiIfaces = EmptyArray.STRING;
   11031 
   11032     @GuardedBy("mWifiNetworkLock")
   11033     private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
   11034 
   11035     private final Object mModemNetworkLock = new Object();
   11036 
   11037     @GuardedBy("mModemNetworkLock")
   11038     private String[] mModemIfaces = EmptyArray.STRING;
   11039 
   11040     @GuardedBy("mModemNetworkLock")
   11041     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
   11042 
   11043     private NetworkStats readNetworkStatsLocked(String[] ifaces) {
   11044         try {
   11045             if (!ArrayUtils.isEmpty(ifaces)) {
   11046                 return mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
   11047                         NetworkStats.TAG_NONE, mNetworkStatsPool.acquire());
   11048             }
   11049         } catch (IOException e) {
   11050             Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces));
   11051         }
   11052         return null;
   11053     }
   11054 
   11055    /**
   11056      * Distribute WiFi energy info and network traffic to apps.
   11057      * @param info The energy information from the WiFi controller.
   11058      */
   11059     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
   11060         if (DEBUG_ENERGY) {
   11061             Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
   11062         }
   11063 
   11064         // Grab a separate lock to acquire the network stats, which may do I/O.
   11065         NetworkStats delta = null;
   11066         synchronized (mWifiNetworkLock) {
   11067             final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
   11068             if (latestStats != null) {
   11069                 delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
   11070                         mNetworkStatsPool.acquire());
   11071                 mNetworkStatsPool.release(mLastWifiNetworkStats);
   11072                 mLastWifiNetworkStats = latestStats;
   11073             }
   11074         }
   11075 
   11076         synchronized (this) {
   11077             if (!mOnBatteryInternal) {
   11078                 if (delta != null) {
   11079                     mNetworkStatsPool.release(delta);
   11080                 }
   11081                 return;
   11082             }
   11083 
   11084             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
   11085             SparseLongArray rxPackets = new SparseLongArray();
   11086             SparseLongArray txPackets = new SparseLongArray();
   11087             long totalTxPackets = 0;
   11088             long totalRxPackets = 0;
   11089             if (delta != null) {
   11090                 NetworkStats.Entry entry = new NetworkStats.Entry();
   11091                 final int size = delta.size();
   11092                 for (int i = 0; i < size; i++) {
   11093                     entry = delta.getValues(i, entry);
   11094 
   11095                     if (DEBUG_ENERGY) {
   11096                         Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
   11097                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
   11098                                 + " txPackets=" + entry.txPackets);
   11099                     }
   11100 
   11101                     if (entry.rxBytes == 0 && entry.txBytes == 0) {
   11102                         // Skip the lookup below since there is no work to do.
   11103                         continue;
   11104                     }
   11105 
   11106                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
   11107                     if (entry.rxBytes != 0) {
   11108                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
   11109                                 entry.rxPackets);
   11110                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
   11111                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
   11112                                     entry.rxPackets);
   11113                         }
   11114                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
   11115                                 entry.rxBytes);
   11116                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
   11117                                 entry.rxPackets);
   11118 
   11119                         rxPackets.put(u.getUid(), entry.rxPackets);
   11120 
   11121                         // Sum the total number of packets so that the Rx Power can
   11122                         // be evenly distributed amongst the apps.
   11123                         totalRxPackets += entry.rxPackets;
   11124                     }
   11125 
   11126                     if (entry.txBytes != 0) {
   11127                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
   11128                                 entry.txPackets);
   11129                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
   11130                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
   11131                                     entry.txPackets);
   11132                         }
   11133                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
   11134                                 entry.txBytes);
   11135                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
   11136                                 entry.txPackets);
   11137 
   11138                         txPackets.put(u.getUid(), entry.txPackets);
   11139 
   11140                         // Sum the total number of packets so that the Tx Power can
   11141                         // be evenly distributed amongst the apps.
   11142                         totalTxPackets += entry.txPackets;
   11143                     }
   11144                 }
   11145                 mNetworkStatsPool.release(delta);
   11146                 delta = null;
   11147             }
   11148 
   11149             if (info != null) {
   11150                 mHasWifiReporting = true;
   11151 
   11152                 // Measured in mAms
   11153                 final long txTimeMs = info.getControllerTxTimeMillis();
   11154                 final long rxTimeMs = info.getControllerRxTimeMillis();
   11155                 final long scanTimeMs = info.getControllerScanTimeMillis();
   11156                 final long idleTimeMs = info.getControllerIdleTimeMillis();
   11157                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
   11158 
   11159                 long leftOverRxTimeMs = rxTimeMs;
   11160                 long leftOverTxTimeMs = txTimeMs;
   11161 
   11162                 if (DEBUG_ENERGY) {
   11163                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
   11164                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
   11165                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
   11166                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
   11167                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
   11168                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
   11169                 }
   11170 
   11171                 long totalWifiLockTimeMs = 0;
   11172                 long totalScanTimeMs = 0;
   11173 
   11174                 // On the first pass, collect some totals so that we can normalize power
   11175                 // calculations if we need to.
   11176                 final int uidStatsSize = mUidStats.size();
   11177                 for (int i = 0; i < uidStatsSize; i++) {
   11178                     final Uid uid = mUidStats.valueAt(i);
   11179 
   11180                     // Sum the total scan power for all apps.
   11181                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
   11182                             elapsedRealtimeMs * 1000) / 1000;
   11183 
   11184                     // Sum the total time holding wifi lock for all apps.
   11185                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
   11186                             elapsedRealtimeMs * 1000) / 1000;
   11187                 }
   11188 
   11189                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
   11190                     Slog.d(TAG,
   11191                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
   11192                                     + rxTimeMs + " ms). Normalizing scan time.");
   11193                 }
   11194                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
   11195                     Slog.d(TAG,
   11196                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
   11197                                     + txTimeMs + " ms). Normalizing scan time.");
   11198                 }
   11199 
   11200                 // Actually assign and distribute power usage to apps.
   11201                 for (int i = 0; i < uidStatsSize; i++) {
   11202                     final Uid uid = mUidStats.valueAt(i);
   11203 
   11204                     long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
   11205                             elapsedRealtimeMs * 1000) / 1000;
   11206                     if (scanTimeSinceMarkMs > 0) {
   11207                         // Set the new mark so that next time we get new data since this point.
   11208                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
   11209 
   11210                         long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
   11211                         long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
   11212 
   11213                         // Our total scan time is more than the reported Tx/Rx time.
   11214                         // This is possible because the cost of a scan is approximate.
   11215                         // Let's normalize the result so that we evenly blame each app
   11216                         // scanning.
   11217                         //
   11218                         // This means that we may have apps that transmitted/received packets not be
   11219                         // blamed for this, but this is fine as scans are relatively more expensive.
   11220                         if (totalScanTimeMs > rxTimeMs) {
   11221                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
   11222                                     totalScanTimeMs;
   11223                         }
   11224                         if (totalScanTimeMs > txTimeMs) {
   11225                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
   11226                                     totalScanTimeMs;
   11227                         }
   11228 
   11229                         if (DEBUG_ENERGY) {
   11230                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
   11231                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
   11232                                     + scanTxTimeSinceMarkMs + " ms)");
   11233                         }
   11234 
   11235                         ControllerActivityCounterImpl activityCounter =
   11236                                 uid.getOrCreateWifiControllerActivityLocked();
   11237                         activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
   11238                         activityCounter.getTxTimeCounters()[0].addCountLocked(
   11239                                 scanTxTimeSinceMarkMs);
   11240                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
   11241                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
   11242                     }
   11243 
   11244                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
   11245                     // lock.
   11246                     final long wifiLockTimeSinceMarkMs =
   11247                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
   11248                                     elapsedRealtimeMs * 1000) / 1000;
   11249                     if (wifiLockTimeSinceMarkMs > 0) {
   11250                         // Set the new mark so that next time we get new data since this point.
   11251                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
   11252 
   11253                         final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
   11254                                 / totalWifiLockTimeMs;
   11255                         if (DEBUG_ENERGY) {
   11256                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
   11257                                     + myIdleTimeMs + " ms");
   11258                         }
   11259                         uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
   11260                                 .addCountLocked(myIdleTimeMs);
   11261                     }
   11262                 }
   11263 
   11264                 if (DEBUG_ENERGY) {
   11265                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
   11266                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
   11267                 }
   11268 
   11269                 // Distribute the remaining Tx power appropriately between all apps that transmitted
   11270                 // packets.
   11271                 for (int i = 0; i < txPackets.size(); i++) {
   11272                     final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
   11273                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
   11274                             / totalTxPackets;
   11275                     if (DEBUG_ENERGY) {
   11276                         Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
   11277                     }
   11278                     uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
   11279                             .addCountLocked(myTxTimeMs);
   11280                 }
   11281 
   11282                 // Distribute the remaining Rx power appropriately between all apps that received
   11283                 // packets.
   11284                 for (int i = 0; i < rxPackets.size(); i++) {
   11285                     final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
   11286                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
   11287                             / totalRxPackets;
   11288                     if (DEBUG_ENERGY) {
   11289                         Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
   11290                     }
   11291                     uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
   11292                             .addCountLocked(myRxTimeMs);
   11293                 }
   11294 
   11295                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
   11296 
   11297 
   11298                 // Update WiFi controller stats.
   11299                 mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
   11300                 mWifiActivity.getTxTimeCounters()[0].addCountLocked(
   11301                         info.getControllerTxTimeMillis());
   11302                 mWifiActivity.getScanTimeCounter().addCountLocked(
   11303                     info.getControllerScanTimeMillis());
   11304                 mWifiActivity.getIdleTimeCounter().addCountLocked(
   11305                         info.getControllerIdleTimeMillis());
   11306 
   11307                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
   11308                 final double opVolt = mPowerProfile.getAveragePower(
   11309                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
   11310                 if (opVolt != 0) {
   11311                     // We store the power drain as mAms.
   11312                     mWifiActivity.getPowerCounter().addCountLocked(
   11313                             (long) (info.getControllerEnergyUsed() / opVolt));
   11314                 }
   11315             }
   11316         }
   11317     }
   11318 
   11319     private ModemActivityInfo mLastModemActivityInfo =
   11320             new ModemActivityInfo(0, 0, 0, new int[0], 0, 0);
   11321 
   11322     private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
   11323         if (activityInfo == null) {
   11324             return null;
   11325         }
   11326         int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
   11327         for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
   11328             txTimeMs[i] = activityInfo.getTxTimeMillis()[i]
   11329                     - mLastModemActivityInfo.getTxTimeMillis()[i];
   11330         }
   11331         ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
   11332                 activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
   11333                 activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
   11334                 txTimeMs,
   11335                 activityInfo.getRxTimeMillis() - mLastModemActivityInfo.getRxTimeMillis(),
   11336                 activityInfo.getEnergyUsed() - mLastModemActivityInfo.getEnergyUsed());
   11337         mLastModemActivityInfo = activityInfo;
   11338         return deltaInfo;
   11339     }
   11340 
   11341     /**
   11342      * Distribute Cell radio energy info and network traffic to apps.
   11343      */
   11344     public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
   11345         if (DEBUG_ENERGY) {
   11346             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
   11347         }
   11348         ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
   11349 
   11350         // Add modem tx power to history.
   11351         addModemTxPowerToHistory(deltaInfo);
   11352 
   11353         // Grab a separate lock to acquire the network stats, which may do I/O.
   11354         NetworkStats delta = null;
   11355         synchronized (mModemNetworkLock) {
   11356             final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
   11357             if (latestStats != null) {
   11358                 delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
   11359                         mNetworkStatsPool.acquire());
   11360                 mNetworkStatsPool.release(mLastModemNetworkStats);
   11361                 mLastModemNetworkStats = latestStats;
   11362             }
   11363         }
   11364 
   11365         synchronized (this) {
   11366             if (!mOnBatteryInternal) {
   11367                 if (delta != null) {
   11368                     mNetworkStatsPool.release(delta);
   11369                 }
   11370                 return;
   11371             }
   11372 
   11373             if (deltaInfo != null) {
   11374                 mHasModemReporting = true;
   11375                 mModemActivity.getIdleTimeCounter().addCountLocked(
   11376                         deltaInfo.getIdleTimeMillis());
   11377                 mModemActivity.getSleepTimeCounter().addCountLocked(
   11378                         deltaInfo.getSleepTimeMillis());
   11379                 mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getRxTimeMillis());
   11380                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
   11381                     mModemActivity.getTxTimeCounters()[lvl]
   11382                         .addCountLocked(deltaInfo.getTxTimeMillis()[lvl]);
   11383                 }
   11384 
   11385                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
   11386                 final double opVolt = mPowerProfile.getAveragePower(
   11387                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
   11388                 if (opVolt != 0) {
   11389                     double energyUsed =
   11390                             deltaInfo.getSleepTimeMillis() *
   11391                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
   11392                             + deltaInfo.getIdleTimeMillis() *
   11393                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
   11394                             + deltaInfo.getRxTimeMillis() *
   11395                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
   11396                     int[] txTimeMs = deltaInfo.getTxTimeMillis();
   11397                     for (int i = 0; i < Math.min(txTimeMs.length,
   11398                             SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
   11399                         energyUsed += txTimeMs[i] * mPowerProfile.getAveragePower(
   11400                                 PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
   11401                     }
   11402 
   11403                     // We store the power drain as mAms.
   11404                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
   11405                 }
   11406             }
   11407 
   11408             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
   11409             long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
   11410                     elapsedRealtimeMs * 1000);
   11411             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
   11412 
   11413             long totalRxPackets = 0;
   11414             long totalTxPackets = 0;
   11415             if (delta != null) {
   11416                 NetworkStats.Entry entry = new NetworkStats.Entry();
   11417                 final int size = delta.size();
   11418                 for (int i = 0; i < size; i++) {
   11419                     entry = delta.getValues(i, entry);
   11420                     if (entry.rxPackets == 0 && entry.txPackets == 0) {
   11421                         continue;
   11422                     }
   11423 
   11424                     if (DEBUG_ENERGY) {
   11425                         Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
   11426                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
   11427                                 + " txPackets=" + entry.txPackets);
   11428                     }
   11429 
   11430                     totalRxPackets += entry.rxPackets;
   11431                     totalTxPackets += entry.txPackets;
   11432 
   11433                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
   11434                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
   11435                             entry.rxPackets);
   11436                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
   11437                             entry.txPackets);
   11438                     if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
   11439                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
   11440                                 entry.rxBytes, entry.rxPackets);
   11441                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
   11442                                 entry.txBytes, entry.txPackets);
   11443                     }
   11444 
   11445                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
   11446                             entry.rxBytes);
   11447                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
   11448                             entry.txBytes);
   11449                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
   11450                             entry.rxPackets);
   11451                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
   11452                             entry.txPackets);
   11453                 }
   11454 
   11455                 // Now distribute proportional blame to the apps that did networking.
   11456                 long totalPackets = totalRxPackets + totalTxPackets;
   11457                 if (totalPackets > 0) {
   11458                     for (int i = 0; i < size; i++) {
   11459                         entry = delta.getValues(i, entry);
   11460                         if (entry.rxPackets == 0 && entry.txPackets == 0) {
   11461                             continue;
   11462                         }
   11463 
   11464                         final Uid u = getUidStatsLocked(mapUid(entry.uid));
   11465 
   11466                         // Distribute total radio active time in to this app.
   11467                         final long appPackets = entry.rxPackets + entry.txPackets;
   11468                         final long appRadioTime = (radioTime * appPackets) / totalPackets;
   11469                         u.noteMobileRadioActiveTimeLocked(appRadioTime);
   11470 
   11471                         // Remove this app from the totals, so that we don't lose any time
   11472                         // due to rounding.
   11473                         radioTime -= appRadioTime;
   11474                         totalPackets -= appPackets;
   11475 
   11476                         if (deltaInfo != null) {
   11477                             ControllerActivityCounterImpl activityCounter =
   11478                                     u.getOrCreateModemControllerActivityLocked();
   11479                             if (totalRxPackets > 0 && entry.rxPackets > 0) {
   11480                                 final long rxMs = (entry.rxPackets * deltaInfo.getRxTimeMillis())
   11481                                         / totalRxPackets;
   11482                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
   11483                             }
   11484 
   11485                             if (totalTxPackets > 0 && entry.txPackets > 0) {
   11486                                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
   11487                                     long txMs =
   11488                                             entry.txPackets * deltaInfo.getTxTimeMillis()[lvl];
   11489                                     txMs /= totalTxPackets;
   11490                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
   11491                                 }
   11492                             }
   11493                         }
   11494                     }
   11495                 }
   11496 
   11497                 if (radioTime > 0) {
   11498                     // Whoops, there is some radio time we can't blame on an app!
   11499                     mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
   11500                     mMobileRadioActiveUnknownCount.addCountLocked(1);
   11501                 }
   11502 
   11503                 mNetworkStatsPool.release(delta);
   11504                 delta = null;
   11505             }
   11506         }
   11507     }
   11508 
   11509     /**
   11510      * Add modem tx power to history
   11511      * Device is said to be in high cellular transmit power when it has spent most of the transmit
   11512      * time at the highest power level.
   11513      * @param activityInfo
   11514      */
   11515     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo) {
   11516         if (activityInfo == null) {
   11517             return;
   11518         }
   11519         int[] txTimeMs = activityInfo.getTxTimeMillis();
   11520         if (txTimeMs == null || txTimeMs.length != ModemActivityInfo.TX_POWER_LEVELS) {
   11521             return;
   11522         }
   11523         final long elapsedRealtime = mClocks.elapsedRealtime();
   11524         final long uptime = mClocks.uptimeMillis();
   11525         int levelMaxTimeSpent = 0;
   11526         for (int i = 1; i < txTimeMs.length; i++) {
   11527             if (txTimeMs[i] > txTimeMs[levelMaxTimeSpent]) {
   11528                 levelMaxTimeSpent = i;
   11529             }
   11530         }
   11531         if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
   11532             if (!mIsCellularTxPowerHigh) {
   11533                 mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
   11534                 addHistoryRecordLocked(elapsedRealtime, uptime);
   11535                 mIsCellularTxPowerHigh = true;
   11536             }
   11537             return;
   11538         }
   11539         if (mIsCellularTxPowerHigh) {
   11540             mHistoryCur.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
   11541             addHistoryRecordLocked(elapsedRealtime, uptime);
   11542             mIsCellularTxPowerHigh = false;
   11543         }
   11544         return;
   11545     }
   11546 
   11547     private final class BluetoothActivityInfoCache {
   11548         long idleTimeMs;
   11549         long rxTimeMs;
   11550         long txTimeMs;
   11551         long energy;
   11552 
   11553         SparseLongArray uidRxBytes = new SparseLongArray();
   11554         SparseLongArray uidTxBytes = new SparseLongArray();
   11555 
   11556         void set(BluetoothActivityEnergyInfo info) {
   11557             idleTimeMs = info.getControllerIdleTimeMillis();
   11558             rxTimeMs = info.getControllerRxTimeMillis();
   11559             txTimeMs = info.getControllerTxTimeMillis();
   11560             energy = info.getControllerEnergyUsed();
   11561             if (info.getUidTraffic() != null) {
   11562                 for (UidTraffic traffic : info.getUidTraffic()) {
   11563                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
   11564                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
   11565                 }
   11566             }
   11567         }
   11568     }
   11569 
   11570     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
   11571             = new BluetoothActivityInfoCache();
   11572 
   11573     /**
   11574      * Distribute Bluetooth energy info and network traffic to apps.
   11575      *
   11576      * @param info The energy information from the bluetooth controller.
   11577      */
   11578     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
   11579         if (DEBUG_ENERGY) {
   11580             Slog.d(TAG, "Updating bluetooth stats: " + info);
   11581         }
   11582 
   11583         if (info == null || !mOnBatteryInternal) {
   11584             return;
   11585         }
   11586 
   11587         mHasBluetoothReporting = true;
   11588 
   11589         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
   11590         final long rxTimeMs =
   11591                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
   11592         final long txTimeMs =
   11593                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
   11594         final long idleTimeMs =
   11595                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
   11596 
   11597         if (DEBUG_ENERGY) {
   11598             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
   11599             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
   11600             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
   11601             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
   11602         }
   11603 
   11604         long totalScanTimeMs = 0;
   11605 
   11606         final int uidCount = mUidStats.size();
   11607         for (int i = 0; i < uidCount; i++) {
   11608             final Uid u = mUidStats.valueAt(i);
   11609             if (u.mBluetoothScanTimer == null) {
   11610                 continue;
   11611             }
   11612 
   11613             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
   11614                     elapsedRealtimeMs * 1000) / 1000;
   11615         }
   11616 
   11617         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
   11618         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
   11619 
   11620         if (DEBUG_ENERGY) {
   11621             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
   11622                     + " TX=" + normalizeScanTxTime);
   11623         }
   11624 
   11625         long leftOverRxTimeMs = rxTimeMs;
   11626         long leftOverTxTimeMs = txTimeMs;
   11627 
   11628         for (int i = 0; i < uidCount; i++) {
   11629             final Uid u = mUidStats.valueAt(i);
   11630             if (u.mBluetoothScanTimer == null) {
   11631                 continue;
   11632             }
   11633 
   11634             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
   11635                     elapsedRealtimeMs * 1000) / 1000;
   11636             if (scanTimeSinceMarkMs > 0) {
   11637                 // Set the new mark so that next time we get new data since this point.
   11638                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
   11639 
   11640                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
   11641                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
   11642 
   11643                 if (normalizeScanRxTime) {
   11644                     // Scan time is longer than the total rx time in the controller,
   11645                     // so distribute the scan time proportionately. This means regular traffic
   11646                     // will not blamed, but scans are more expensive anyways.
   11647                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
   11648                 }
   11649 
   11650                 if (normalizeScanTxTime) {
   11651                     // Scan time is longer than the total tx time in the controller,
   11652                     // so distribute the scan time proportionately. This means regular traffic
   11653                     // will not blamed, but scans are more expensive anyways.
   11654                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
   11655                 }
   11656 
   11657                 final ControllerActivityCounterImpl counter =
   11658                         u.getOrCreateBluetoothControllerActivityLocked();
   11659                 counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
   11660                 counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
   11661 
   11662                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
   11663                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
   11664             }
   11665         }
   11666 
   11667         if (DEBUG_ENERGY) {
   11668             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
   11669                     + leftOverTxTimeMs);
   11670         }
   11671 
   11672         //
   11673         // Now distribute blame to apps that did bluetooth traffic.
   11674         //
   11675 
   11676         long totalTxBytes = 0;
   11677         long totalRxBytes = 0;
   11678 
   11679         final UidTraffic[] uidTraffic = info.getUidTraffic();
   11680         final int numUids = uidTraffic != null ? uidTraffic.length : 0;
   11681         for (int i = 0; i < numUids; i++) {
   11682             final UidTraffic traffic = uidTraffic[i];
   11683             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
   11684                     traffic.getUid());
   11685             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
   11686                     traffic.getUid());
   11687 
   11688             // Add to the global counters.
   11689             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
   11690             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
   11691 
   11692             // Add to the UID counters.
   11693             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
   11694             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
   11695             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
   11696 
   11697             // Calculate the total traffic.
   11698             totalRxBytes += rxBytes;
   11699             totalTxBytes += txBytes;
   11700         }
   11701 
   11702         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
   11703                 || leftOverTxTimeMs != 0)) {
   11704             for (int i = 0; i < numUids; i++) {
   11705                 final UidTraffic traffic = uidTraffic[i];
   11706                 final int uid = traffic.getUid();
   11707                 final long rxBytes =
   11708                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
   11709                 final long txBytes =
   11710                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
   11711 
   11712                 final Uid u = getUidStatsLocked(mapUid(uid));
   11713                 final ControllerActivityCounterImpl counter =
   11714                         u.getOrCreateBluetoothControllerActivityLocked();
   11715 
   11716                 if (totalRxBytes > 0 && rxBytes > 0) {
   11717                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
   11718                     if (DEBUG_ENERGY) {
   11719                         Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
   11720                     }
   11721                     counter.getRxTimeCounter().addCountLocked(timeRxMs);
   11722                     leftOverRxTimeMs -= timeRxMs;
   11723                 }
   11724 
   11725                 if (totalTxBytes > 0 && txBytes > 0) {
   11726                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
   11727                     if (DEBUG_ENERGY) {
   11728                         Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
   11729                     }
   11730                     counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
   11731                     leftOverTxTimeMs -= timeTxMs;
   11732                 }
   11733             }
   11734         }
   11735 
   11736         mBluetoothActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
   11737         mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(txTimeMs);
   11738         mBluetoothActivity.getIdleTimeCounter().addCountLocked(idleTimeMs);
   11739 
   11740         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
   11741         final double opVolt = mPowerProfile.getAveragePower(
   11742                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
   11743         if (opVolt != 0) {
   11744             // We store the power drain as mAms.
   11745             mBluetoothActivity.getPowerCounter().addCountLocked(
   11746                     (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
   11747                             / opVolt));
   11748         }
   11749         mLastBluetoothActivityInfo.set(info);
   11750     }
   11751 
   11752     /**
   11753      * Read and record Resource Power Manager (RPM) state and voter times.
   11754      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
   11755      * instead of fetching it anew.
   11756      */
   11757     public void updateRpmStatsLocked() {
   11758         if (mPlatformIdleStateCallback == null) return;
   11759         long now = SystemClock.elapsedRealtime();
   11760         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
   11761             mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats);
   11762             mLastRpmStatsUpdateTimeMs = now;
   11763         }
   11764 
   11765         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
   11766                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
   11767 
   11768             // Update values for this platform state.
   11769             final String pName = pstate.getKey();
   11770             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
   11771             final int pCount = pstate.getValue().mCount;
   11772             getRpmTimerLocked(pName).update(pTimeUs, pCount);
   11773             if (SCREEN_OFF_RPM_STATS_ENABLED) {
   11774                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount);
   11775             }
   11776 
   11777             // Update values for each voter of this platform state.
   11778             for (Map.Entry<String, RpmStats.PowerStateElement> voter
   11779                     : pstate.getValue().mVoters.entrySet()) {
   11780                 final String vName = pName + "." + voter.getKey();
   11781                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
   11782                 final int vCount = voter.getValue().mCount;
   11783                 getRpmTimerLocked(vName).update(vTimeUs, vCount);
   11784                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
   11785                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount);
   11786                 }
   11787             }
   11788         }
   11789 
   11790         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
   11791                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
   11792 
   11793             final String subsysName = subsys.getKey();
   11794             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
   11795                     : subsys.getValue().mStates.entrySet()) {
   11796                 final String name = subsysName + "." + sstate.getKey();
   11797                 final long timeUs = sstate.getValue().mTimeMs * 1000;
   11798                 final int count = sstate.getValue().mCount;
   11799                 getRpmTimerLocked(name).update(timeUs, count);
   11800                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
   11801                     getScreenOffRpmTimerLocked(name).update(timeUs, count);
   11802                 }
   11803             }
   11804         }
   11805     }
   11806 
   11807     /**
   11808      * Read and distribute kernel wake lock use across apps.
   11809      */
   11810     public void updateKernelWakelocksLocked() {
   11811         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
   11812                 mTmpWakelockStats);
   11813         if (wakelockStats == null) {
   11814             // Not crashing might make board bringup easier.
   11815             Slog.w(TAG, "Couldn't get kernel wake lock stats");
   11816             return;
   11817         }
   11818 
   11819         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
   11820             String name = ent.getKey();
   11821             KernelWakelockStats.Entry kws = ent.getValue();
   11822 
   11823             SamplingTimer kwlt = mKernelWakelockStats.get(name);
   11824             if (kwlt == null) {
   11825                 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
   11826                 mKernelWakelockStats.put(name, kwlt);
   11827             }
   11828 
   11829             kwlt.update(kws.mTotalTime, kws.mCount);
   11830             kwlt.setUpdateVersion(kws.mVersion);
   11831         }
   11832 
   11833         int numWakelocksSetStale = 0;
   11834         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
   11835         // this time.
   11836         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
   11837             SamplingTimer st = ent.getValue();
   11838             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
   11839                 st.endSample();
   11840                 numWakelocksSetStale++;
   11841             }
   11842         }
   11843 
   11844         // Record whether we've seen a non-zero time (for debugging b/22716723).
   11845         if (wakelockStats.isEmpty()) {
   11846             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
   11847         }
   11848 
   11849         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
   11850             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
   11851                     wakelockStats.kernelWakelockVersion);
   11852         }
   11853     }
   11854 
   11855     // We use an anonymous class to access these variables,
   11856     // so they can't live on the stack or they'd have to be
   11857     // final MutableLong objects (more allocations).
   11858     // Used in updateCpuTimeLocked().
   11859     long mTempTotalCpuUserTimeUs;
   11860     long mTempTotalCpuSystemTimeUs;
   11861     long[][] mWakeLockAllocationsUs;
   11862 
   11863     /**
   11864      * Reads the newest memory stats from the kernel.
   11865      */
   11866     public void updateKernelMemoryBandwidthLocked() {
   11867         mKernelMemoryBandwidthStats.updateStats();
   11868         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
   11869         final int bandwidthEntryCount = bandwidthEntries.size();
   11870         int index;
   11871         for (int i = 0; i < bandwidthEntryCount; i++) {
   11872             SamplingTimer timer;
   11873             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
   11874                 timer = mKernelMemoryStats.valueAt(index);
   11875             } else {
   11876                 timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
   11877                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
   11878             }
   11879             timer.update(bandwidthEntries.valueAt(i), 1);
   11880             if (DEBUG_MEMORY) {
   11881                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
   11882                         + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i),
   11883                         mKernelMemoryStats.get(
   11884                                 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime,
   11885                         mKernelMemoryStats.size()));
   11886             }
   11887         }
   11888     }
   11889 
   11890     public boolean isOnBatteryLocked() {
   11891         return mOnBatteryTimeBase.isRunning();
   11892     }
   11893 
   11894     public boolean isOnBatteryScreenOffLocked() {
   11895         return mOnBatteryScreenOffTimeBase.isRunning();
   11896     }
   11897 
   11898     /**
   11899      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
   11900      * and we are on battery with screen off, we give more of the cpu time to those apps holding
   11901      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
   11902      * It's possible this will be invoked after the internal battery/screen states are updated, so
   11903      * passing the appropriate battery/screen states to try attribute the cpu times to correct
   11904      * buckets.
   11905      */
   11906     @GuardedBy("this")
   11907     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) {
   11908         if (mPowerProfile == null) {
   11909             return;
   11910         }
   11911 
   11912         if (DEBUG_ENERGY_CPU) {
   11913             Slog.d(TAG, "!Cpu updating!");
   11914         }
   11915 
   11916         if (mCpuFreqs == null) {
   11917             mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
   11918         }
   11919 
   11920         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
   11921         // usually holding the wakelock on behalf of an app.
   11922         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
   11923         ArrayList<StopwatchTimer> partialTimersToConsider = null;
   11924         if (onBatteryScreenOff) {
   11925             partialTimersToConsider = new ArrayList<>();
   11926             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
   11927                 final StopwatchTimer timer = mPartialTimers.get(i);
   11928                 // Since the collection and blaming of wakelocks can be scheduled to run after
   11929                 // some delay, the mPartialTimers list may have new entries. We can't blame
   11930                 // the newly added timer for past cpu time, so we only consider timers that
   11931                 // were present for one round of collection. Once a timer has gone through
   11932                 // a round of collection, its mInList field is set to true.
   11933                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
   11934                     partialTimersToConsider.add(timer);
   11935                 }
   11936             }
   11937         }
   11938         markPartialTimersAsEligible();
   11939 
   11940         // When the battery is not on, we don't attribute the cpu times to any timers but we still
   11941         // need to take the snapshots.
   11942         if (!onBattery) {
   11943             mKernelUidCpuTimeReader.readDelta(null);
   11944             mKernelUidCpuFreqTimeReader.readDelta(null);
   11945             mNumAllUidCpuTimeReads += 2;
   11946             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
   11947                 mKernelUidCpuActiveTimeReader.readDelta(null);
   11948                 mKernelUidCpuClusterTimeReader.readDelta(null);
   11949                 mNumAllUidCpuTimeReads += 2;
   11950             }
   11951             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
   11952                 mKernelCpuSpeedReaders[cluster].readDelta();
   11953             }
   11954             return;
   11955         }
   11956 
   11957         mUserInfoProvider.refreshUserIds();
   11958         final SparseLongArray updatedUids = mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()
   11959                 ? null : new SparseLongArray();
   11960         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
   11961         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
   11962         // freqs, so no need to approximate these values.
   11963         if (updatedUids != null) {
   11964             updateClusterSpeedTimes(updatedUids, onBattery);
   11965         }
   11966         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff);
   11967         mNumAllUidCpuTimeReads += 2;
   11968         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
   11969             readKernelUidCpuActiveTimesLocked(onBattery);
   11970             readKernelUidCpuClusterTimesLocked(onBattery);
   11971             mNumAllUidCpuTimeReads += 2;
   11972         }
   11973     }
   11974 
   11975     /**
   11976      * Mark the current partial timers as gone through a collection so that they will be
   11977      * considered in the next cpu times distribution to wakelock holders.
   11978      */
   11979     @VisibleForTesting
   11980     public void markPartialTimersAsEligible() {
   11981         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
   11982             // No difference, so each timer is now considered for the next collection.
   11983             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
   11984                 mPartialTimers.get(i).mInList = true;
   11985             }
   11986         } else {
   11987             // The lists are different, meaning we added (or removed a timer) since the last
   11988             // collection.
   11989             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
   11990                 mLastPartialTimers.get(i).mInList = false;
   11991             }
   11992             mLastPartialTimers.clear();
   11993 
   11994             // Mark the current timers as gone through a collection.
   11995             final int numPartialTimers = mPartialTimers.size();
   11996             for (int i = 0; i < numPartialTimers; ++i) {
   11997                 final StopwatchTimer timer = mPartialTimers.get(i);
   11998                 timer.mInList = true;
   11999                 mLastPartialTimers.add(timer);
   12000             }
   12001         }
   12002     }
   12003 
   12004     /**
   12005      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
   12006      * calculate cpu times spent by each uid at different frequencies.
   12007      *
   12008      * @param updatedUids The uids for which times spent at different frequencies are calculated.
   12009      */
   12010     @VisibleForTesting
   12011     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) {
   12012         long totalCpuClustersTimeMs = 0;
   12013         // Read the time spent for each cluster at various cpu frequencies.
   12014         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
   12015         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
   12016             clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
   12017             if (clusterSpeedTimesMs[cluster] != null) {
   12018                 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
   12019                     totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
   12020                 }
   12021             }
   12022         }
   12023         if (totalCpuClustersTimeMs != 0) {
   12024             // We have cpu times per freq aggregated over all uids but we need the times per uid.
   12025             // So, we distribute total time spent by an uid to different cpu freqs based on the
   12026             // amount of time cpu was running at that freq.
   12027             final int updatedUidsCount = updatedUids.size();
   12028             for (int i = 0; i < updatedUidsCount; ++i) {
   12029                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
   12030                 final long appCpuTimeUs = updatedUids.valueAt(i);
   12031                 // Add the cpu speeds to this UID.
   12032                 final int numClusters = mPowerProfile.getNumCpuClusters();
   12033                 if (u.mCpuClusterSpeedTimesUs == null ||
   12034                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
   12035                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
   12036                 }
   12037 
   12038                 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
   12039                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
   12040                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
   12041                             u.mCpuClusterSpeedTimesUs[cluster].length) {
   12042                         u.mCpuClusterSpeedTimesUs[cluster]
   12043                                 = new LongSamplingCounter[speedsInCluster];
   12044                     }
   12045 
   12046                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
   12047                     for (int speed = 0; speed < speedsInCluster; speed++) {
   12048                         if (cpuSpeeds[speed] == null) {
   12049                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
   12050                         }
   12051                         cpuSpeeds[speed].addCountLocked(appCpuTimeUs
   12052                                 * clusterSpeedTimesMs[cluster][speed]
   12053                                 / totalCpuClustersTimeMs, onBattery);
   12054                     }
   12055                 }
   12056             }
   12057         }
   12058     }
   12059 
   12060     /**
   12061      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
   12062      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
   12063      * wakelock holders.
   12064      *
   12065      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
   12066      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
   12067      */
   12068     @VisibleForTesting
   12069     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
   12070             @Nullable SparseLongArray updatedUids, boolean onBattery) {
   12071         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
   12072         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
   12073         final long startTimeMs = mClocks.uptimeMillis();
   12074 
   12075         mKernelUidCpuTimeReader.readDelta((uid, userTimeUs, systemTimeUs) -> {
   12076             uid = mapUid(uid);
   12077             if (Process.isIsolated(uid)) {
   12078                 // This could happen if the isolated uid mapping was removed before that process
   12079                 // was actually killed.
   12080                 mKernelUidCpuTimeReader.removeUid(uid);
   12081                 Slog.d(TAG, "Got readings for an isolated uid with no mapping: " + uid);
   12082                 return;
   12083             }
   12084             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
   12085                 Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
   12086                 mKernelUidCpuTimeReader.removeUid(uid);
   12087                 return;
   12088             }
   12089             final Uid u = getUidStatsLocked(uid);
   12090 
   12091             // Accumulate the total system and user time.
   12092             mTempTotalCpuUserTimeUs += userTimeUs;
   12093             mTempTotalCpuSystemTimeUs += systemTimeUs;
   12094 
   12095             StringBuilder sb = null;
   12096             if (DEBUG_ENERGY_CPU) {
   12097                 sb = new StringBuilder();
   12098                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
   12099                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
   12100                 sb.append(" s=");
   12101                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
   12102                 sb.append("\n");
   12103             }
   12104 
   12105             if (numWakelocks > 0) {
   12106                 // We have wakelocks being held, so only give a portion of the
   12107                 // time to the process. The rest will be distributed among wakelock
   12108                 // holders.
   12109                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
   12110                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
   12111             }
   12112 
   12113             if (sb != null) {
   12114                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
   12115                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
   12116                 sb.append(" s=");
   12117                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
   12118                 Slog.d(TAG, sb.toString());
   12119             }
   12120 
   12121             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
   12122             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
   12123             if (updatedUids != null) {
   12124                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
   12125             }
   12126         });
   12127 
   12128         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
   12129         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
   12130             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
   12131         }
   12132 
   12133         if (numWakelocks > 0) {
   12134             // Distribute a portion of the total cpu time to wakelock holders.
   12135             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
   12136             mTempTotalCpuSystemTimeUs =
   12137                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
   12138 
   12139             for (int i = 0; i < numWakelocks; ++i) {
   12140                 final StopwatchTimer timer = partialTimers.get(i);
   12141                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
   12142                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
   12143 
   12144                 if (DEBUG_ENERGY_CPU) {
   12145                     final StringBuilder sb = new StringBuilder();
   12146                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
   12147                             .append(": u=");
   12148                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
   12149                     sb.append(" s=");
   12150                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
   12151                     Slog.d(TAG, sb.toString());
   12152                 }
   12153 
   12154                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
   12155                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
   12156                 if (updatedUids != null) {
   12157                     final int uid = timer.mUid.getUid();
   12158                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
   12159                 }
   12160 
   12161                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
   12162                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
   12163 
   12164                 mTempTotalCpuUserTimeUs -= userTimeUs;
   12165                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
   12166             }
   12167         }
   12168     }
   12169 
   12170     /**
   12171      * Take a snapshot of the cpu times spent by each uid in each freq and update the
   12172      * corresponding counters.
   12173      *
   12174      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
   12175      */
   12176     @VisibleForTesting
   12177     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
   12178             boolean onBattery, boolean onBatteryScreenOff) {
   12179         final boolean perClusterTimesAvailable =
   12180                 mKernelUidCpuFreqTimeReader.perClusterTimesAvailable();
   12181         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
   12182         final int numClusters = mPowerProfile.getNumCpuClusters();
   12183         mWakeLockAllocationsUs = null;
   12184         final long startTimeMs = mClocks.uptimeMillis();
   12185         mKernelUidCpuFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
   12186             uid = mapUid(uid);
   12187             if (Process.isIsolated(uid)) {
   12188                 mKernelUidCpuFreqTimeReader.removeUid(uid);
   12189                 Slog.d(TAG, "Got freq readings for an isolated uid with no mapping: " + uid);
   12190                 return;
   12191             }
   12192             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
   12193                 Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
   12194                 mKernelUidCpuFreqTimeReader.removeUid(uid);
   12195                 return;
   12196             }
   12197             final Uid u = getUidStatsLocked(uid);
   12198             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
   12199                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
   12200             }
   12201             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
   12202             if (u.mScreenOffCpuFreqTimeMs == null ||
   12203                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
   12204                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
   12205                         mOnBatteryScreenOffTimeBase);
   12206             }
   12207             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
   12208 
   12209             if (perClusterTimesAvailable) {
   12210                 if (u.mCpuClusterSpeedTimesUs == null ||
   12211                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
   12212                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
   12213                 }
   12214                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
   12215                     mWakeLockAllocationsUs = new long[numClusters][];
   12216                 }
   12217 
   12218                 int freqIndex = 0;
   12219                 for (int cluster = 0; cluster < numClusters; ++cluster) {
   12220                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
   12221                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
   12222                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
   12223                         u.mCpuClusterSpeedTimesUs[cluster]
   12224                                 = new LongSamplingCounter[speedsInCluster];
   12225                     }
   12226                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
   12227                         mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
   12228                     }
   12229                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
   12230                     for (int speed = 0; speed < speedsInCluster; ++speed) {
   12231                         if (cpuTimesUs[speed] == null) {
   12232                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
   12233                         }
   12234                         final long appAllocationUs;
   12235                         if (mWakeLockAllocationsUs != null) {
   12236                             appAllocationUs =
   12237                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
   12238                             mWakeLockAllocationsUs[cluster][speed] +=
   12239                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
   12240                         } else {
   12241                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
   12242                         }
   12243                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
   12244                         freqIndex++;
   12245                     }
   12246                 }
   12247             }
   12248         });
   12249 
   12250         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
   12251         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
   12252             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
   12253         }
   12254 
   12255         if (mWakeLockAllocationsUs != null) {
   12256             for (int i = 0; i < numWakelocks; ++i) {
   12257                 final Uid u = partialTimers.get(i).mUid;
   12258                 if (u.mCpuClusterSpeedTimesUs == null ||
   12259                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
   12260                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
   12261                 }
   12262 
   12263                 for (int cluster = 0; cluster < numClusters; ++cluster) {
   12264                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
   12265                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
   12266                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
   12267                         u.mCpuClusterSpeedTimesUs[cluster]
   12268                                 = new LongSamplingCounter[speedsInCluster];
   12269                     }
   12270                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
   12271                     for (int speed = 0; speed < speedsInCluster; ++speed) {
   12272                         if (cpuTimeUs[speed] == null) {
   12273                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
   12274                         }
   12275                         final long allocationUs =
   12276                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
   12277                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
   12278                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
   12279                     }
   12280                 }
   12281             }
   12282         }
   12283     }
   12284 
   12285     /**
   12286      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
   12287      * counters.
   12288      */
   12289     @VisibleForTesting
   12290     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
   12291         final long startTimeMs = mClocks.uptimeMillis();
   12292         mKernelUidCpuActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> {
   12293             uid = mapUid(uid);
   12294             if (Process.isIsolated(uid)) {
   12295                 mKernelUidCpuActiveTimeReader.removeUid(uid);
   12296                 Slog.w(TAG, "Got active times for an isolated uid with no mapping: " + uid);
   12297                 return;
   12298             }
   12299             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
   12300                 Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
   12301                 mKernelUidCpuActiveTimeReader.removeUid(uid);
   12302                 return;
   12303             }
   12304             final Uid u = getUidStatsLocked(uid);
   12305             u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery);
   12306         });
   12307 
   12308         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
   12309         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
   12310             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
   12311         }
   12312     }
   12313 
   12314     /**
   12315      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
   12316      * counters.
   12317      */
   12318     @VisibleForTesting
   12319     public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
   12320         final long startTimeMs = mClocks.uptimeMillis();
   12321         mKernelUidCpuClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> {
   12322             uid = mapUid(uid);
   12323             if (Process.isIsolated(uid)) {
   12324                 mKernelUidCpuClusterTimeReader.removeUid(uid);
   12325                 Slog.w(TAG, "Got cluster times for an isolated uid with no mapping: " + uid);
   12326                 return;
   12327             }
   12328             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
   12329                 Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
   12330                 mKernelUidCpuClusterTimeReader.removeUid(uid);
   12331                 return;
   12332             }
   12333             final Uid u = getUidStatsLocked(uid);
   12334             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
   12335         });
   12336 
   12337         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
   12338         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
   12339             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
   12340         }
   12341     }
   12342 
   12343     boolean setChargingLocked(boolean charging) {
   12344         if (mCharging != charging) {
   12345             mCharging = charging;
   12346             if (charging) {
   12347                 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
   12348             } else {
   12349                 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
   12350             }
   12351             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
   12352             return true;
   12353         }
   12354         return false;
   12355     }
   12356 
   12357     @GuardedBy("this")
   12358     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
   12359             final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
   12360         boolean doWrite = false;
   12361         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
   12362         m.arg1 = onBattery ? 1 : 0;
   12363         mHandler.sendMessage(m);
   12364 
   12365         final long uptime = mSecUptime * 1000;
   12366         final long realtime = mSecRealtime * 1000;
   12367         final int screenState = mScreenState;
   12368         if (onBattery) {
   12369             // We will reset our status if we are unplugging after the
   12370             // battery was last full, or the level is at 100, or
   12371             // we have gone through a significant charge (from a very low
   12372             // level to a now very high level).
   12373             boolean reset = false;
   12374             if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
   12375                     || level >= 90
   12376                     || (mDischargeCurrentLevel < 20 && level >= 80)
   12377                     || (getHighDischargeAmountSinceCharge() >= 200
   12378                             && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
   12379                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
   12380                         + " dischargeLevel=" + mDischargeCurrentLevel
   12381                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
   12382                         + " highAmount=" + getHighDischargeAmountSinceCharge());
   12383                 // Before we write, collect a snapshot of the final aggregated
   12384                 // stats to be reported in the next checkin.  Only do this if we have
   12385                 // a sufficient amount of data to make it interesting.
   12386                 if (getLowDischargeAmountSinceCharge() >= 20) {
   12387                     final long startTime = SystemClock.uptimeMillis();
   12388                     final Parcel parcel = Parcel.obtain();
   12389                     writeSummaryToParcel(parcel, true);
   12390                     final long initialTime = SystemClock.uptimeMillis() - startTime;
   12391                     BackgroundThread.getHandler().post(new Runnable() {
   12392                         @Override public void run() {
   12393                             synchronized (mCheckinFile) {
   12394                                 final long startTime2 = SystemClock.uptimeMillis();
   12395                                 FileOutputStream stream = null;
   12396                                 try {
   12397                                     stream = mCheckinFile.startWrite();
   12398                                     stream.write(parcel.marshall());
   12399                                     stream.flush();
   12400                                     FileUtils.sync(stream);
   12401                                     stream.close();
   12402                                     mCheckinFile.finishWrite(stream);
   12403                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
   12404                                             "batterystats-checkin",
   12405                                             initialTime + SystemClock.uptimeMillis() - startTime2);
   12406                                 } catch (IOException e) {
   12407                                     Slog.w("BatteryStats",
   12408                                             "Error writing checkin battery statistics", e);
   12409                                     mCheckinFile.failWrite(stream);
   12410                                 } finally {
   12411                                     parcel.recycle();
   12412                                 }
   12413                             }
   12414                         }
   12415                     });
   12416                 }
   12417                 doWrite = true;
   12418                 resetAllStatsLocked();
   12419                 if (chargeUAh > 0 && level > 0) {
   12420                     // Only use the reported coulomb charge value if it is supported and reported.
   12421                     mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
   12422                 }
   12423                 mDischargeStartLevel = level;
   12424                 reset = true;
   12425                 mDischargeStepTracker.init();
   12426             }
   12427             if (mCharging) {
   12428                 setChargingLocked(false);
   12429             }
   12430             mLastChargingStateLevel = level;
   12431             mOnBattery = mOnBatteryInternal = true;
   12432             mLastDischargeStepLevel = level;
   12433             mMinDischargeStepLevel = level;
   12434             mDischargeStepTracker.clearTime();
   12435             mDailyDischargeStepTracker.clearTime();
   12436             mInitStepMode = mCurStepMode;
   12437             mModStepMode = 0;
   12438             pullPendingStateUpdatesLocked();
   12439             mHistoryCur.batteryLevel = (byte)level;
   12440             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   12441             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
   12442                     + Integer.toHexString(mHistoryCur.states));
   12443             if (reset) {
   12444                 mRecordingHistory = true;
   12445                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
   12446             }
   12447             addHistoryRecordLocked(mSecRealtime, mSecUptime);
   12448             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
   12449             if (isScreenOn(screenState)) {
   12450                 mDischargeScreenOnUnplugLevel = level;
   12451                 mDischargeScreenDozeUnplugLevel = 0;
   12452                 mDischargeScreenOffUnplugLevel = 0;
   12453             } else if (isScreenDoze(screenState)) {
   12454                 mDischargeScreenOnUnplugLevel = 0;
   12455                 mDischargeScreenDozeUnplugLevel = level;
   12456                 mDischargeScreenOffUnplugLevel = 0;
   12457             } else {
   12458                 mDischargeScreenOnUnplugLevel = 0;
   12459                 mDischargeScreenDozeUnplugLevel = 0;
   12460                 mDischargeScreenOffUnplugLevel = level;
   12461             }
   12462             mDischargeAmountScreenOn = 0;
   12463             mDischargeAmountScreenDoze = 0;
   12464             mDischargeAmountScreenOff = 0;
   12465             updateTimeBasesLocked(true, screenState, uptime, realtime);
   12466         } else {
   12467             mLastChargingStateLevel = level;
   12468             mOnBattery = mOnBatteryInternal = false;
   12469             pullPendingStateUpdatesLocked();
   12470             mHistoryCur.batteryLevel = (byte)level;
   12471             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   12472             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
   12473                     + Integer.toHexString(mHistoryCur.states));
   12474             addHistoryRecordLocked(mSecRealtime, mSecUptime);
   12475             mDischargeCurrentLevel = mDischargePlugLevel = level;
   12476             if (level < mDischargeUnplugLevel) {
   12477                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
   12478                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
   12479             }
   12480             updateDischargeScreenLevelsLocked(screenState, screenState);
   12481             updateTimeBasesLocked(false, screenState, uptime, realtime);
   12482             mChargeStepTracker.init();
   12483             mLastChargeStepLevel = level;
   12484             mMaxChargeStepLevel = level;
   12485             mInitStepMode = mCurStepMode;
   12486             mModStepMode = 0;
   12487         }
   12488         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
   12489             if (mFile != null) {
   12490                 writeAsyncLocked();
   12491             }
   12492         }
   12493     }
   12494 
   12495     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
   12496             boolean reset) {
   12497         mRecordingHistory = true;
   12498         mHistoryCur.currentTime = System.currentTimeMillis();
   12499         addHistoryBufferLocked(elapsedRealtimeMs,
   12500                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
   12501                 mHistoryCur);
   12502         mHistoryCur.currentTime = 0;
   12503         if (reset) {
   12504             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
   12505         }
   12506     }
   12507 
   12508     private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
   12509             final long uptimeMs) {
   12510         if (mRecordingHistory) {
   12511             mHistoryCur.currentTime = currentTime;
   12512             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
   12513             mHistoryCur.currentTime = 0;
   12514         }
   12515     }
   12516 
   12517     private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
   12518         if (mRecordingHistory) {
   12519             mHistoryCur.currentTime = System.currentTimeMillis();
   12520             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
   12521             mHistoryCur.currentTime = 0;
   12522         }
   12523     }
   12524 
   12525     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
   12526         if (mExternalSync != null) {
   12527             mExternalSync.scheduleSync(reason, updateFlags);
   12528         }
   12529     }
   12530 
   12531     // This should probably be exposed in the API, though it's not critical
   12532     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
   12533 
   12534     @GuardedBy("this")
   12535     public void setBatteryStateLocked(final int status, final int health, final int plugType,
   12536             final int level, /* not final */ int temp, final int volt, final int chargeUAh,
   12537             final int chargeFullUAh) {
   12538         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
   12539         temp = Math.max(0, temp);
   12540 
   12541         reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
   12542                 status, plugType, level);
   12543 
   12544         final boolean onBattery = isOnBattery(plugType, status);
   12545         final long uptime = mClocks.uptimeMillis();
   12546         final long elapsedRealtime = mClocks.elapsedRealtime();
   12547         if (!mHaveBatteryLevel) {
   12548             mHaveBatteryLevel = true;
   12549             // We start out assuming that the device is plugged in (not
   12550             // on battery).  If our first report is now that we are indeed
   12551             // plugged in, then twiddle our state to correctly reflect that
   12552             // since we won't be going through the full setOnBattery().
   12553             if (onBattery == mOnBattery) {
   12554                 if (onBattery) {
   12555                     mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   12556                 } else {
   12557                     mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
   12558                 }
   12559             }
   12560             // Always start out assuming charging, that will be updated later.
   12561             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
   12562             mHistoryCur.batteryStatus = (byte)status;
   12563             mHistoryCur.batteryLevel = (byte)level;
   12564             mHistoryCur.batteryChargeUAh = chargeUAh;
   12565             mMaxChargeStepLevel = mMinDischargeStepLevel =
   12566                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
   12567             mLastChargingStateLevel = level;
   12568         } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
   12569             recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
   12570         }
   12571         int oldStatus = mHistoryCur.batteryStatus;
   12572         if (onBattery) {
   12573             mDischargeCurrentLevel = level;
   12574             if (!mRecordingHistory) {
   12575                 mRecordingHistory = true;
   12576                 startRecordingHistory(elapsedRealtime, uptime, true);
   12577             }
   12578         } else if (level < 96 &&
   12579             status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
   12580             if (!mRecordingHistory) {
   12581                 mRecordingHistory = true;
   12582                 startRecordingHistory(elapsedRealtime, uptime, true);
   12583             }
   12584         }
   12585         mCurrentBatteryLevel = level;
   12586         if (mDischargePlugLevel < 0) {
   12587             mDischargePlugLevel = level;
   12588         }
   12589 
   12590         if (onBattery != mOnBattery) {
   12591             mHistoryCur.batteryLevel = (byte)level;
   12592             mHistoryCur.batteryStatus = (byte)status;
   12593             mHistoryCur.batteryHealth = (byte)health;
   12594             mHistoryCur.batteryPlugType = (byte)plugType;
   12595             mHistoryCur.batteryTemperature = (short)temp;
   12596             mHistoryCur.batteryVoltage = (char)volt;
   12597             if (chargeUAh < mHistoryCur.batteryChargeUAh) {
   12598                 // Only record discharges
   12599                 final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
   12600                 mDischargeCounter.addCountLocked(chargeDiff);
   12601                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
   12602                 if (isScreenDoze(mScreenState)) {
   12603                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
   12604                 }
   12605                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
   12606                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
   12607                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
   12608                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
   12609                 }
   12610             }
   12611             mHistoryCur.batteryChargeUAh = chargeUAh;
   12612             setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
   12613         } else {
   12614             boolean changed = false;
   12615             if (mHistoryCur.batteryLevel != level) {
   12616                 mHistoryCur.batteryLevel = (byte)level;
   12617                 changed = true;
   12618 
   12619                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
   12620                 // which will pull external stats.
   12621                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
   12622                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
   12623             }
   12624             if (mHistoryCur.batteryStatus != status) {
   12625                 mHistoryCur.batteryStatus = (byte)status;
   12626                 changed = true;
   12627             }
   12628             if (mHistoryCur.batteryHealth != health) {
   12629                 mHistoryCur.batteryHealth = (byte)health;
   12630                 changed = true;
   12631             }
   12632             if (mHistoryCur.batteryPlugType != plugType) {
   12633                 mHistoryCur.batteryPlugType = (byte)plugType;
   12634                 changed = true;
   12635             }
   12636             if (temp >= (mHistoryCur.batteryTemperature+10)
   12637                     || temp <= (mHistoryCur.batteryTemperature-10)) {
   12638                 mHistoryCur.batteryTemperature = (short)temp;
   12639                 changed = true;
   12640             }
   12641             if (volt > (mHistoryCur.batteryVoltage+20)
   12642                     || volt < (mHistoryCur.batteryVoltage-20)) {
   12643                 mHistoryCur.batteryVoltage = (char)volt;
   12644                 changed = true;
   12645             }
   12646             if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
   12647                     || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
   12648                 if (chargeUAh < mHistoryCur.batteryChargeUAh) {
   12649                     // Only record discharges
   12650                     final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
   12651                     mDischargeCounter.addCountLocked(chargeDiff);
   12652                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
   12653                     if (isScreenDoze(mScreenState)) {
   12654                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
   12655                     }
   12656                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
   12657                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
   12658                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
   12659                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
   12660                     }
   12661                 }
   12662                 mHistoryCur.batteryChargeUAh = chargeUAh;
   12663                 changed = true;
   12664             }
   12665             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
   12666                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
   12667                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
   12668             if (onBattery) {
   12669                 changed |= setChargingLocked(false);
   12670                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
   12671                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
   12672                             modeBits, elapsedRealtime);
   12673                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
   12674                             modeBits, elapsedRealtime);
   12675                     mLastDischargeStepLevel = level;
   12676                     mMinDischargeStepLevel = level;
   12677                     mInitStepMode = mCurStepMode;
   12678                     mModStepMode = 0;
   12679                 }
   12680             } else {
   12681                 if (level >= 90) {
   12682                     // If the battery level is at least 90%, always consider the device to be
   12683                     // charging even if it happens to go down a level.
   12684                     changed |= setChargingLocked(true);
   12685                     mLastChargeStepLevel = level;
   12686                 } if (!mCharging) {
   12687                     if (mLastChargeStepLevel < level) {
   12688                         // We have not reporting that we are charging, but the level has now
   12689                         // gone up, so consider the state to be charging.
   12690                         changed |= setChargingLocked(true);
   12691                         mLastChargeStepLevel = level;
   12692                     }
   12693                 } else {
   12694                     if (mLastChargeStepLevel > level) {
   12695                         // We had reported that the device was charging, but here we are with
   12696                         // power connected and the level going down.  Looks like the current
   12697                         // power supplied isn't enough, so consider the device to now be
   12698                         // discharging.
   12699                         changed |= setChargingLocked(false);
   12700                         mLastChargeStepLevel = level;
   12701                     }
   12702                 }
   12703                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
   12704                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
   12705                             modeBits, elapsedRealtime);
   12706                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
   12707                             modeBits, elapsedRealtime);
   12708                     mLastChargeStepLevel = level;
   12709                     mMaxChargeStepLevel = level;
   12710                     mInitStepMode = mCurStepMode;
   12711                     mModStepMode = 0;
   12712                 }
   12713             }
   12714             if (changed) {
   12715                 addHistoryRecordLocked(elapsedRealtime, uptime);
   12716             }
   12717         }
   12718         if (!onBattery &&
   12719             (status == BatteryManager.BATTERY_STATUS_FULL ||
   12720              status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
   12721             // We don't record history while we are plugged in and fully charged
   12722             // (or when battery is not present).  The next time we are
   12723             // unplugged, history will be cleared.
   12724             mRecordingHistory = DEBUG;
   12725         }
   12726 
   12727         if (mMinLearnedBatteryCapacity == -1) {
   12728             mMinLearnedBatteryCapacity = chargeFullUAh;
   12729         } else {
   12730             Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
   12731         }
   12732         mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
   12733     }
   12734 
   12735     public static boolean isOnBattery(int plugType, int status) {
   12736         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
   12737     }
   12738 
   12739     // Inform StatsLog of setBatteryState changes.
   12740     // If this is the first reporting, pass in recentPast == null.
   12741     private void reportChangesToStatsLog(HistoryItem recentPast,
   12742             final int status, final int plugType, final int level) {
   12743 
   12744         if (recentPast == null || recentPast.batteryStatus != status) {
   12745             StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, status);
   12746         }
   12747         if (recentPast == null || recentPast.batteryPlugType != plugType) {
   12748             StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, plugType);
   12749         }
   12750         if (recentPast == null || recentPast.batteryLevel != level) {
   12751             StatsLog.write(StatsLog.BATTERY_LEVEL_CHANGED, level);
   12752         }
   12753     }
   12754 
   12755     public long getAwakeTimeBattery() {
   12756         return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
   12757     }
   12758 
   12759     public long getAwakeTimePlugged() {
   12760         return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
   12761     }
   12762 
   12763     @Override
   12764     public long computeUptime(long curTime, int which) {
   12765         switch (which) {
   12766             case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
   12767             case STATS_CURRENT: return (curTime-mUptimeStart);
   12768             case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
   12769         }
   12770         return 0;
   12771     }
   12772 
   12773     @Override
   12774     public long computeRealtime(long curTime, int which) {
   12775         switch (which) {
   12776             case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
   12777             case STATS_CURRENT: return (curTime-mRealtimeStart);
   12778             case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
   12779         }
   12780         return 0;
   12781     }
   12782 
   12783     @Override
   12784     public long computeBatteryUptime(long curTime, int which) {
   12785         return mOnBatteryTimeBase.computeUptime(curTime, which);
   12786     }
   12787 
   12788     @Override
   12789     public long computeBatteryRealtime(long curTime, int which) {
   12790         return mOnBatteryTimeBase.computeRealtime(curTime, which);
   12791     }
   12792 
   12793     @Override
   12794     public long computeBatteryScreenOffUptime(long curTime, int which) {
   12795         return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
   12796     }
   12797 
   12798     @Override
   12799     public long computeBatteryScreenOffRealtime(long curTime, int which) {
   12800         return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
   12801     }
   12802 
   12803     private long computeTimePerLevel(long[] steps, int numSteps) {
   12804         // For now we'll do a simple average across all steps.
   12805         if (numSteps <= 0) {
   12806             return -1;
   12807         }
   12808         long total = 0;
   12809         for (int i=0; i<numSteps; i++) {
   12810             total += steps[i] & STEP_LEVEL_TIME_MASK;
   12811         }
   12812         return total / numSteps;
   12813         /*
   12814         long[] buckets = new long[numSteps];
   12815         int numBuckets = 0;
   12816         int numToAverage = 4;
   12817         int i = 0;
   12818         while (i < numSteps) {
   12819             long totalTime = 0;
   12820             int num = 0;
   12821             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
   12822                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
   12823                 num++;
   12824             }
   12825             buckets[numBuckets] = totalTime / num;
   12826             numBuckets++;
   12827             numToAverage *= 2;
   12828             i += num;
   12829         }
   12830         if (numBuckets < 1) {
   12831             return -1;
   12832         }
   12833         long averageTime = buckets[numBuckets-1];
   12834         for (i=numBuckets-2; i>=0; i--) {
   12835             averageTime = (averageTime + buckets[i]) / 2;
   12836         }
   12837         return averageTime;
   12838         */
   12839     }
   12840 
   12841     @Override
   12842     public long computeBatteryTimeRemaining(long curTime) {
   12843         if (!mOnBattery) {
   12844             return -1;
   12845         }
   12846         /* Simple implementation just looks at the average discharge per level across the
   12847            entire sample period.
   12848         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
   12849         if (discharge < 2) {
   12850             return -1;
   12851         }
   12852         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
   12853         if (duration < 1000*1000) {
   12854             return -1;
   12855         }
   12856         long usPerLevel = duration/discharge;
   12857         return usPerLevel * mCurrentBatteryLevel;
   12858         */
   12859         if (mDischargeStepTracker.mNumStepDurations < 1) {
   12860             return -1;
   12861         }
   12862         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
   12863         if (msPerLevel <= 0) {
   12864             return -1;
   12865         }
   12866         return (msPerLevel * mCurrentBatteryLevel) * 1000;
   12867     }
   12868 
   12869     @Override
   12870     public LevelStepTracker getDischargeLevelStepTracker() {
   12871         return mDischargeStepTracker;
   12872     }
   12873 
   12874     @Override
   12875     public LevelStepTracker getDailyDischargeLevelStepTracker() {
   12876         return mDailyDischargeStepTracker;
   12877     }
   12878 
   12879     @Override
   12880     public long computeChargeTimeRemaining(long curTime) {
   12881         if (mOnBattery) {
   12882             // Not yet working.
   12883             return -1;
   12884         }
   12885         /* Broken
   12886         int curLevel = mCurrentBatteryLevel;
   12887         int plugLevel = mDischargePlugLevel;
   12888         if (plugLevel < 0 || curLevel < (plugLevel+1)) {
   12889             return -1;
   12890         }
   12891         long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
   12892         if (duration < 1000*1000) {
   12893             return -1;
   12894         }
   12895         long usPerLevel = duration/(curLevel-plugLevel);
   12896         return usPerLevel * (100-curLevel);
   12897         */
   12898         if (mChargeStepTracker.mNumStepDurations < 1) {
   12899             return -1;
   12900         }
   12901         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
   12902         if (msPerLevel <= 0) {
   12903             return -1;
   12904         }
   12905         return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
   12906     }
   12907 
   12908     /*@hide */
   12909     public CellularBatteryStats getCellularBatteryStats() {
   12910         CellularBatteryStats s = new CellularBatteryStats();
   12911         final int which = STATS_SINCE_CHARGED;
   12912         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
   12913         final ControllerActivityCounter counter = getModemControllerActivity();
   12914         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
   12915         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
   12916         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
   12917         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
   12918         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
   12919         for (int i = 0; i < timeInRatMs.length; i++) {
   12920            timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
   12921         }
   12922         long[] timeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
   12923         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
   12924            timeInRxSignalStrengthLevelMs[i]
   12925                = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
   12926         }
   12927         long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
   12928             counter.getTxTimeCounters().length)];
   12929         long totalTxTimeMs = 0;
   12930         for (int i = 0; i < txTimeMs.length; i++) {
   12931             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
   12932             totalTxTimeMs += txTimeMs[i];
   12933         }
   12934         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
   12935         s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
   12936         s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
   12937         s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
   12938         s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
   12939         s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
   12940         s.setSleepTimeMs(sleepTimeMs);
   12941         s.setIdleTimeMs(idleTimeMs);
   12942         s.setRxTimeMs(rxTimeMs);
   12943         s.setEnergyConsumedMaMs(energyConsumedMaMs);
   12944         s.setTimeInRatMs(timeInRatMs);
   12945         s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
   12946         s.setTxTimeMs(txTimeMs);
   12947         return s;
   12948     }
   12949 
   12950      /*@hide */
   12951      public WifiBatteryStats getWifiBatteryStats() {
   12952          WifiBatteryStats s = new WifiBatteryStats();
   12953          final int which = STATS_SINCE_CHARGED;
   12954          final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
   12955          final ControllerActivityCounter counter = getWifiControllerActivity();
   12956          final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
   12957          final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
   12958          final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
   12959          final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
   12960          final long totalControllerActivityTimeMs
   12961              = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
   12962          final long sleepTimeMs
   12963              = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
   12964          final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
   12965          long numAppScanRequest = 0;
   12966          for (int i = 0; i < mUidStats.size(); i++) {
   12967              numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
   12968          }
   12969          long[] timeInStateMs = new long[NUM_WIFI_STATES];
   12970          for (int i=0; i<NUM_WIFI_STATES; i++) {
   12971             timeInStateMs[i] = getWifiStateTime(i, rawRealTime, which) / 1000;
   12972          }
   12973          long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
   12974          for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   12975              timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000;
   12976          }
   12977          long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
   12978          for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   12979              timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000;
   12980          }
   12981          s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
   12982          s.setKernelActiveTimeMs(getWifiActiveTime(rawRealTime, which) / 1000);
   12983          s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
   12984          s.setNumBytesTx(getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
   12985          s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
   12986          s.setNumBytesRx(getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
   12987          s.setSleepTimeMs(sleepTimeMs);
   12988          s.setIdleTimeMs(idleTimeMs);
   12989          s.setRxTimeMs(rxTimeMs);
   12990          s.setTxTimeMs(txTimeMs);
   12991          s.setScanTimeMs(scanTimeMs);
   12992          s.setEnergyConsumedMaMs(energyConsumedMaMs);
   12993          s.setNumAppScanRequest(numAppScanRequest);
   12994          s.setTimeInStateMs(timeInStateMs);
   12995          s.setTimeInSupplicantStateMs(timeInSupplStateMs);
   12996          s.setTimeInRxSignalStrengthLevelMs(timeSignalStrengthTimeMs);
   12997          return s;
   12998      }
   12999 
   13000     /*@hide */
   13001     public GpsBatteryStats getGpsBatteryStats() {
   13002         GpsBatteryStats s = new GpsBatteryStats();
   13003         final int which = STATS_SINCE_CHARGED;
   13004         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
   13005         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
   13006         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
   13007         long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
   13008         for (int i=0; i<time.length; i++) {
   13009             time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
   13010         }
   13011         s.setTimeInGpsSignalQualityLevel(time);
   13012         return s;
   13013     }
   13014 
   13015     @Override
   13016     public LevelStepTracker getChargeLevelStepTracker() {
   13017         return mChargeStepTracker;
   13018     }
   13019 
   13020     @Override
   13021     public LevelStepTracker getDailyChargeLevelStepTracker() {
   13022         return mDailyChargeStepTracker;
   13023     }
   13024 
   13025     @Override
   13026     public ArrayList<PackageChange> getDailyPackageChanges() {
   13027         return mDailyPackageChanges;
   13028     }
   13029 
   13030     protected long getBatteryUptimeLocked() {
   13031         return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
   13032     }
   13033 
   13034     @Override
   13035     public long getBatteryUptime(long curTime) {
   13036         return mOnBatteryTimeBase.getUptime(curTime);
   13037     }
   13038 
   13039     @Override
   13040     public long getBatteryRealtime(long curTime) {
   13041         return mOnBatteryTimeBase.getRealtime(curTime);
   13042     }
   13043 
   13044     @Override
   13045     public int getDischargeStartLevel() {
   13046         synchronized(this) {
   13047             return getDischargeStartLevelLocked();
   13048         }
   13049     }
   13050 
   13051     public int getDischargeStartLevelLocked() {
   13052             return mDischargeUnplugLevel;
   13053     }
   13054 
   13055     @Override
   13056     public int getDischargeCurrentLevel() {
   13057         synchronized(this) {
   13058             return getDischargeCurrentLevelLocked();
   13059         }
   13060     }
   13061 
   13062     public int getDischargeCurrentLevelLocked() {
   13063         return mDischargeCurrentLevel;
   13064     }
   13065 
   13066     @Override
   13067     public int getLowDischargeAmountSinceCharge() {
   13068         synchronized(this) {
   13069             int val = mLowDischargeAmountSinceCharge;
   13070             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
   13071                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
   13072             }
   13073             return val;
   13074         }
   13075     }
   13076 
   13077     @Override
   13078     public int getHighDischargeAmountSinceCharge() {
   13079         synchronized(this) {
   13080             int val = mHighDischargeAmountSinceCharge;
   13081             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
   13082                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
   13083             }
   13084             return val;
   13085         }
   13086     }
   13087 
   13088     @Override
   13089     public int getDischargeAmount(int which) {
   13090         int dischargeAmount = which == STATS_SINCE_CHARGED
   13091                 ? getHighDischargeAmountSinceCharge()
   13092                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
   13093         if (dischargeAmount < 0) {
   13094             dischargeAmount = 0;
   13095         }
   13096         return dischargeAmount;
   13097     }
   13098 
   13099     @Override
   13100     public int getDischargeAmountScreenOn() {
   13101         synchronized(this) {
   13102             int val = mDischargeAmountScreenOn;
   13103             if (mOnBattery && isScreenOn(mScreenState)
   13104                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
   13105                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
   13106             }
   13107             return val;
   13108         }
   13109     }
   13110 
   13111     @Override
   13112     public int getDischargeAmountScreenOnSinceCharge() {
   13113         synchronized(this) {
   13114             int val = mDischargeAmountScreenOnSinceCharge;
   13115             if (mOnBattery && isScreenOn(mScreenState)
   13116                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
   13117                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
   13118             }
   13119             return val;
   13120         }
   13121     }
   13122 
   13123     @Override
   13124     public int getDischargeAmountScreenOff() {
   13125         synchronized(this) {
   13126             int val = mDischargeAmountScreenOff;
   13127             if (mOnBattery && isScreenOff(mScreenState)
   13128                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
   13129                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
   13130             }
   13131             // For backward compatibility, doze discharge is counted into screen off.
   13132             return val + getDischargeAmountScreenDoze();
   13133         }
   13134     }
   13135 
   13136     @Override
   13137     public int getDischargeAmountScreenOffSinceCharge() {
   13138         synchronized(this) {
   13139             int val = mDischargeAmountScreenOffSinceCharge;
   13140             if (mOnBattery && isScreenOff(mScreenState)
   13141                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
   13142                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
   13143             }
   13144             // For backward compatibility, doze discharge is counted into screen off.
   13145             return val + getDischargeAmountScreenDozeSinceCharge();
   13146         }
   13147     }
   13148 
   13149     @Override
   13150     public int getDischargeAmountScreenDoze() {
   13151         synchronized(this) {
   13152             int val = mDischargeAmountScreenDoze;
   13153             if (mOnBattery && isScreenDoze(mScreenState)
   13154                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
   13155                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
   13156             }
   13157             return val;
   13158         }
   13159     }
   13160 
   13161     @Override
   13162     public int getDischargeAmountScreenDozeSinceCharge() {
   13163         synchronized(this) {
   13164             int val = mDischargeAmountScreenDozeSinceCharge;
   13165             if (mOnBattery && isScreenDoze(mScreenState)
   13166                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
   13167                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
   13168             }
   13169             return val;
   13170         }
   13171     }
   13172 
   13173     /**
   13174      * Retrieve the statistics object for a particular uid, creating if needed.
   13175      */
   13176     public Uid getUidStatsLocked(int uid) {
   13177         Uid u = mUidStats.get(uid);
   13178         if (u == null) {
   13179             u = new Uid(this, uid);
   13180             mUidStats.put(uid, u);
   13181         }
   13182         return u;
   13183     }
   13184 
   13185     /**
   13186      * Retrieve the statistics object for a particular uid. Returns null if the object is not
   13187      * available.
   13188      */
   13189     public Uid getAvailableUidStatsLocked(int uid) {
   13190         Uid u = mUidStats.get(uid);
   13191         return u;
   13192     }
   13193 
   13194     public void onCleanupUserLocked(int userId) {
   13195         final int firstUidForUser = UserHandle.getUid(userId, 0);
   13196         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
   13197         mPendingRemovedUids.add(
   13198                 new UidToRemove(firstUidForUser, lastUidForUser, mClocks.elapsedRealtime()));
   13199     }
   13200 
   13201     public void onUserRemovedLocked(int userId) {
   13202         final int firstUidForUser = UserHandle.getUid(userId, 0);
   13203         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
   13204         mUidStats.put(firstUidForUser, null);
   13205         mUidStats.put(lastUidForUser, null);
   13206         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
   13207         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
   13208         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
   13209     }
   13210 
   13211     /**
   13212      * Remove the statistics object for a particular uid.
   13213      */
   13214     public void removeUidStatsLocked(int uid) {
   13215         mUidStats.remove(uid);
   13216         mPendingRemovedUids.add(new UidToRemove(uid, mClocks.elapsedRealtime()));
   13217     }
   13218 
   13219     /**
   13220      * Retrieve the statistics object for a particular process, creating
   13221      * if needed.
   13222      */
   13223     public Uid.Proc getProcessStatsLocked(int uid, String name) {
   13224         uid = mapUid(uid);
   13225         Uid u = getUidStatsLocked(uid);
   13226         return u.getProcessStatsLocked(name);
   13227     }
   13228 
   13229     /**
   13230      * Retrieve the statistics object for a particular process, creating
   13231      * if needed.
   13232      */
   13233     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
   13234         uid = mapUid(uid);
   13235         Uid u = getUidStatsLocked(uid);
   13236         return u.getPackageStatsLocked(pkg);
   13237     }
   13238 
   13239     /**
   13240      * Retrieve the statistics object for a particular service, creating
   13241      * if needed.
   13242      */
   13243     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
   13244         uid = mapUid(uid);
   13245         Uid u = getUidStatsLocked(uid);
   13246         return u.getServiceStatsLocked(pkg, name);
   13247     }
   13248 
   13249     public void shutdownLocked() {
   13250         recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
   13251         writeSyncLocked();
   13252         mShuttingDown = true;
   13253     }
   13254 
   13255     public boolean trackPerProcStateCpuTimes() {
   13256         return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
   13257     }
   13258 
   13259     public void systemServicesReady(Context context) {
   13260         mConstants.startObserving(context.getContentResolver());
   13261         registerUsbStateReceiver(context);
   13262     }
   13263 
   13264     @VisibleForTesting
   13265     public final class Constants extends ContentObserver {
   13266         public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE
   13267                 = "track_cpu_times_by_proc_state";
   13268         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
   13269                 = "track_cpu_active_cluster_time";
   13270         public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
   13271                 = "proc_state_cpu_times_read_delay_ms";
   13272         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
   13273                 = "kernel_uid_readers_throttle_time";
   13274         public static final String KEY_UID_REMOVE_DELAY_MS
   13275                 = "uid_remove_delay_ms";
   13276         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
   13277                 = "external_stats_collection_rate_limit_ms";
   13278         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
   13279                 = "battery_level_collection_delay_ms";
   13280 
   13281         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = true;
   13282         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
   13283         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
   13284         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 10_000;
   13285         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
   13286         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
   13287         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
   13288 
   13289         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
   13290         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
   13291         public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
   13292         public long KERNEL_UID_READERS_THROTTLE_TIME = DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME;
   13293         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
   13294         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
   13295                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
   13296         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
   13297                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
   13298 
   13299         private ContentResolver mResolver;
   13300         private final KeyValueListParser mParser = new KeyValueListParser(',');
   13301 
   13302         public Constants(Handler handler) {
   13303             super(handler);
   13304         }
   13305 
   13306         public void startObserving(ContentResolver resolver) {
   13307             mResolver = resolver;
   13308             mResolver.registerContentObserver(
   13309                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
   13310                     false /* notifyForDescendants */, this);
   13311             updateConstants();
   13312         }
   13313 
   13314         @Override
   13315         public void onChange(boolean selfChange, Uri uri) {
   13316             updateConstants();
   13317         }
   13318 
   13319         private void updateConstants() {
   13320             synchronized (BatteryStatsImpl.this) {
   13321                 try {
   13322                     mParser.setString(Settings.Global.getString(mResolver,
   13323                             Settings.Global.BATTERY_STATS_CONSTANTS));
   13324                 } catch (IllegalArgumentException e) {
   13325                     // Failed to parse the settings string, log this and move on
   13326                     // with defaults.
   13327                     Slog.e(TAG, "Bad batterystats settings", e);
   13328                 }
   13329 
   13330                 updateTrackCpuTimesByProcStateLocked(TRACK_CPU_TIMES_BY_PROC_STATE,
   13331                         mParser.getBoolean(KEY_TRACK_CPU_TIMES_BY_PROC_STATE,
   13332                                 DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE));
   13333                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
   13334                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
   13335                 updateProcStateCpuTimesReadDelayMs(PROC_STATE_CPU_TIMES_READ_DELAY_MS,
   13336                         mParser.getLong(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS,
   13337                                 DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS));
   13338                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
   13339                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
   13340                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
   13341                 updateUidRemoveDelay(
   13342                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
   13343                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
   13344                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
   13345                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
   13346                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
   13347                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
   13348                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
   13349             }
   13350         }
   13351 
   13352         private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
   13353             TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
   13354             if (isEnabled && !wasEnabled) {
   13355                 mKernelSingleUidTimeReader.markDataAsStale(true);
   13356                 mExternalSync.scheduleCpuSyncDueToSettingChange();
   13357 
   13358                 mNumSingleUidCpuTimeReads = 0;
   13359                 mNumBatchedSingleUidCpuTimeReads = 0;
   13360                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
   13361             }
   13362         }
   13363 
   13364         private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
   13365             PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
   13366             if (oldDelayMillis != newDelayMillis) {
   13367                 mNumSingleUidCpuTimeReads = 0;
   13368                 mNumBatchedSingleUidCpuTimeReads = 0;
   13369                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
   13370             }
   13371         }
   13372 
   13373         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
   13374             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
   13375             if (oldTimeMs != newTimeMs) {
   13376                 mKernelUidCpuTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
   13377                 mKernelUidCpuFreqTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
   13378                 mKernelUidCpuActiveTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
   13379                 mKernelUidCpuClusterTimeReader
   13380                         .setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
   13381             }
   13382         }
   13383 
   13384         private void updateUidRemoveDelay(long newTimeMs) {
   13385             UID_REMOVE_DELAY_MS = newTimeMs;
   13386             clearPendingRemovedUids();
   13387         }
   13388 
   13389         public void dumpLocked(PrintWriter pw) {
   13390             pw.print(KEY_TRACK_CPU_TIMES_BY_PROC_STATE); pw.print("=");
   13391             pw.println(TRACK_CPU_TIMES_BY_PROC_STATE);
   13392             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
   13393             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
   13394             pw.print(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS); pw.print("=");
   13395             pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
   13396             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
   13397             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
   13398             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
   13399             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
   13400             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
   13401             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
   13402         }
   13403     }
   13404 
   13405     public long getExternalStatsCollectionRateLimitMs() {
   13406         synchronized (this) {
   13407             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
   13408         }
   13409     }
   13410 
   13411     @GuardedBy("this")
   13412     public void dumpConstantsLocked(PrintWriter pw) {
   13413         mConstants.dumpLocked(pw);
   13414     }
   13415 
   13416     @GuardedBy("this")
   13417     public void dumpCpuStatsLocked(PrintWriter pw) {
   13418         int size = mUidStats.size();
   13419         pw.println("Per UID CPU user & system time in ms:");
   13420         for (int i = 0; i < size; i++) {
   13421             int u = mUidStats.keyAt(i);
   13422             Uid uid = mUidStats.get(u);
   13423             pw.print("  "); pw.print(u); pw.print(": ");
   13424             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
   13425             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
   13426         }
   13427         pw.println("Per UID CPU active time in ms:");
   13428         for (int i = 0; i < size; i++) {
   13429             int u = mUidStats.keyAt(i);
   13430             Uid uid = mUidStats.get(u);
   13431             if (uid.getCpuActiveTime() > 0) {
   13432                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
   13433             }
   13434         }
   13435         pw.println("Per UID CPU cluster time in ms:");
   13436         for (int i = 0; i < size; i++) {
   13437             int u = mUidStats.keyAt(i);
   13438             long[] times = mUidStats.get(u).getCpuClusterTimes();
   13439             if (times != null) {
   13440                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
   13441             }
   13442         }
   13443         pw.println("Per UID CPU frequency time in ms:");
   13444         for (int i = 0; i < size; i++) {
   13445             int u = mUidStats.keyAt(i);
   13446             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
   13447             if (times != null) {
   13448                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
   13449             }
   13450         }
   13451     }
   13452 
   13453     Parcel mPendingWrite = null;
   13454     final ReentrantLock mWriteLock = new ReentrantLock();
   13455 
   13456     public void writeAsyncLocked() {
   13457         writeLocked(false);
   13458     }
   13459 
   13460     public void writeSyncLocked() {
   13461         writeLocked(true);
   13462     }
   13463 
   13464     void writeLocked(boolean sync) {
   13465         if (mFile == null) {
   13466             Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
   13467             return;
   13468         }
   13469 
   13470         if (mShuttingDown) {
   13471             return;
   13472         }
   13473 
   13474         Parcel out = Parcel.obtain();
   13475         writeSummaryToParcel(out, true);
   13476         mLastWriteTime = mClocks.elapsedRealtime();
   13477 
   13478         if (mPendingWrite != null) {
   13479             mPendingWrite.recycle();
   13480         }
   13481         mPendingWrite = out;
   13482 
   13483         if (sync) {
   13484             commitPendingDataToDisk();
   13485         } else {
   13486             BackgroundThread.getHandler().post(new Runnable() {
   13487                 @Override public void run() {
   13488                     commitPendingDataToDisk();
   13489                 }
   13490             });
   13491         }
   13492     }
   13493 
   13494     public void commitPendingDataToDisk() {
   13495         final Parcel next;
   13496         synchronized (this) {
   13497             next = mPendingWrite;
   13498             mPendingWrite = null;
   13499             if (next == null) {
   13500                 return;
   13501             }
   13502         }
   13503 
   13504         mWriteLock.lock();
   13505         try {
   13506             final long startTime = SystemClock.uptimeMillis();
   13507             FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
   13508             stream.write(next.marshall());
   13509             stream.flush();
   13510             FileUtils.sync(stream);
   13511             stream.close();
   13512             mFile.commit();
   13513             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
   13514                     "batterystats", SystemClock.uptimeMillis() - startTime);
   13515         } catch (IOException e) {
   13516             Slog.w("BatteryStats", "Error writing battery statistics", e);
   13517             mFile.rollback();
   13518         } finally {
   13519             next.recycle();
   13520             mWriteLock.unlock();
   13521         }
   13522     }
   13523 
   13524     public void readLocked() {
   13525         if (mDailyFile != null) {
   13526             readDailyStatsLocked();
   13527         }
   13528 
   13529         if (mFile == null) {
   13530             Slog.w("BatteryStats", "readLocked: no file associated with this instance");
   13531             return;
   13532         }
   13533 
   13534         mUidStats.clear();
   13535 
   13536         try {
   13537             File file = mFile.chooseForRead();
   13538             if (!file.exists()) {
   13539                 return;
   13540             }
   13541             FileInputStream stream = new FileInputStream(file);
   13542 
   13543             byte[] raw = BatteryStatsHelper.readFully(stream);
   13544             Parcel in = Parcel.obtain();
   13545             in.unmarshall(raw, 0, raw.length);
   13546             in.setDataPosition(0);
   13547             stream.close();
   13548 
   13549             readSummaryFromParcel(in);
   13550         } catch(Exception e) {
   13551             Slog.e("BatteryStats", "Error reading battery statistics", e);
   13552             resetAllStatsLocked();
   13553         }
   13554 
   13555         mEndPlatformVersion = Build.ID;
   13556 
   13557         if (mHistoryBuffer.dataPosition() > 0) {
   13558             mRecordingHistory = true;
   13559             final long elapsedRealtime = mClocks.elapsedRealtime();
   13560             final long uptime = mClocks.uptimeMillis();
   13561             if (USE_OLD_HISTORY) {
   13562                 addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
   13563             }
   13564             addHistoryBufferLocked(elapsedRealtime, HistoryItem.CMD_START, mHistoryCur);
   13565             startRecordingHistory(elapsedRealtime, uptime, false);
   13566         }
   13567 
   13568         recordDailyStatsIfNeededLocked(false);
   13569     }
   13570 
   13571     public int describeContents() {
   13572         return 0;
   13573     }
   13574 
   13575     void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
   13576         final long historyBaseTime = in.readLong();
   13577 
   13578         mHistoryBuffer.setDataSize(0);
   13579         mHistoryBuffer.setDataPosition(0);
   13580         mHistoryTagPool.clear();
   13581         mNextHistoryTagIdx = 0;
   13582         mNumHistoryTagChars = 0;
   13583 
   13584         int numTags = in.readInt();
   13585         for (int i=0; i<numTags; i++) {
   13586             int idx = in.readInt();
   13587             String str = in.readString();
   13588             if (str == null) {
   13589                 throw new ParcelFormatException("null history tag string");
   13590             }
   13591             int uid = in.readInt();
   13592             HistoryTag tag = new HistoryTag();
   13593             tag.string = str;
   13594             tag.uid = uid;
   13595             tag.poolIdx = idx;
   13596             mHistoryTagPool.put(tag, idx);
   13597             if (idx >= mNextHistoryTagIdx) {
   13598                 mNextHistoryTagIdx = idx+1;
   13599             }
   13600             mNumHistoryTagChars += tag.string.length() + 1;
   13601         }
   13602 
   13603         int bufSize = in.readInt();
   13604         int curPos = in.dataPosition();
   13605         if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
   13606             throw new ParcelFormatException("File corrupt: history data buffer too large " +
   13607                     bufSize);
   13608         } else if ((bufSize&~3) != bufSize) {
   13609             throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
   13610                     bufSize);
   13611         } else {
   13612             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
   13613                     + " bytes at " + curPos);
   13614             mHistoryBuffer.appendFrom(in, curPos, bufSize);
   13615             in.setDataPosition(curPos + bufSize);
   13616         }
   13617 
   13618         if (andOldHistory) {
   13619             readOldHistory(in);
   13620         }
   13621 
   13622         if (DEBUG_HISTORY) {
   13623             StringBuilder sb = new StringBuilder(128);
   13624             sb.append("****************** OLD mHistoryBaseTime: ");
   13625             TimeUtils.formatDuration(mHistoryBaseTime, sb);
   13626             Slog.i(TAG, sb.toString());
   13627         }
   13628         mHistoryBaseTime = historyBaseTime;
   13629         if (DEBUG_HISTORY) {
   13630             StringBuilder sb = new StringBuilder(128);
   13631             sb.append("****************** NEW mHistoryBaseTime: ");
   13632             TimeUtils.formatDuration(mHistoryBaseTime, sb);
   13633             Slog.i(TAG, sb.toString());
   13634         }
   13635 
   13636         // We are just arbitrarily going to insert 1 minute from the sample of
   13637         // the last run until samples in this run.
   13638         if (mHistoryBaseTime > 0) {
   13639             long oldnow = mClocks.elapsedRealtime();
   13640             mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
   13641             if (DEBUG_HISTORY) {
   13642                 StringBuilder sb = new StringBuilder(128);
   13643                 sb.append("****************** ADJUSTED mHistoryBaseTime: ");
   13644                 TimeUtils.formatDuration(mHistoryBaseTime, sb);
   13645                 Slog.i(TAG, sb.toString());
   13646             }
   13647         }
   13648     }
   13649 
   13650     void readOldHistory(Parcel in) {
   13651         if (!USE_OLD_HISTORY) {
   13652             return;
   13653         }
   13654         mHistory = mHistoryEnd = mHistoryCache = null;
   13655         long time;
   13656         while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
   13657             HistoryItem rec = new HistoryItem(time, in);
   13658             addHistoryRecordLocked(rec);
   13659         }
   13660     }
   13661 
   13662     void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
   13663         if (DEBUG_HISTORY) {
   13664             StringBuilder sb = new StringBuilder(128);
   13665             sb.append("****************** WRITING mHistoryBaseTime: ");
   13666             TimeUtils.formatDuration(mHistoryBaseTime, sb);
   13667             sb.append(" mLastHistoryElapsedRealtime: ");
   13668             TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
   13669             Slog.i(TAG, sb.toString());
   13670         }
   13671         out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
   13672         if (!inclData) {
   13673             out.writeInt(0);
   13674             out.writeInt(0);
   13675             return;
   13676         }
   13677         out.writeInt(mHistoryTagPool.size());
   13678         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
   13679             HistoryTag tag = ent.getKey();
   13680             out.writeInt(ent.getValue());
   13681             out.writeString(tag.string);
   13682             out.writeInt(tag.uid);
   13683         }
   13684         out.writeInt(mHistoryBuffer.dataSize());
   13685         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
   13686                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
   13687         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
   13688 
   13689         if (andOldHistory) {
   13690             writeOldHistory(out);
   13691         }
   13692     }
   13693 
   13694     void writeOldHistory(Parcel out) {
   13695         if (!USE_OLD_HISTORY) {
   13696             return;
   13697         }
   13698         HistoryItem rec = mHistory;
   13699         while (rec != null) {
   13700             if (rec.time >= 0) rec.writeToParcel(out, 0);
   13701             rec = rec.next;
   13702         }
   13703         out.writeLong(-1);
   13704     }
   13705 
   13706     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
   13707         final int version = in.readInt();
   13708         if (version != VERSION) {
   13709             Slog.w("BatteryStats", "readFromParcel: version got " + version
   13710                 + ", expected " + VERSION + "; erasing old stats");
   13711             return;
   13712         }
   13713 
   13714         readHistory(in, true);
   13715 
   13716         mStartCount = in.readInt();
   13717         mUptime = in.readLong();
   13718         mRealtime = in.readLong();
   13719         mStartClockTime = in.readLong();
   13720         mStartPlatformVersion = in.readString();
   13721         mEndPlatformVersion = in.readString();
   13722         mOnBatteryTimeBase.readSummaryFromParcel(in);
   13723         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
   13724         mDischargeUnplugLevel = in.readInt();
   13725         mDischargePlugLevel = in.readInt();
   13726         mDischargeCurrentLevel = in.readInt();
   13727         mCurrentBatteryLevel = in.readInt();
   13728         mEstimatedBatteryCapacity = in.readInt();
   13729         mMinLearnedBatteryCapacity = in.readInt();
   13730         mMaxLearnedBatteryCapacity = in.readInt();
   13731         mLowDischargeAmountSinceCharge = in.readInt();
   13732         mHighDischargeAmountSinceCharge = in.readInt();
   13733         mDischargeAmountScreenOnSinceCharge = in.readInt();
   13734         mDischargeAmountScreenOffSinceCharge = in.readInt();
   13735         mDischargeAmountScreenDozeSinceCharge = in.readInt();
   13736         mDischargeStepTracker.readFromParcel(in);
   13737         mChargeStepTracker.readFromParcel(in);
   13738         mDailyDischargeStepTracker.readFromParcel(in);
   13739         mDailyChargeStepTracker.readFromParcel(in);
   13740         mDischargeCounter.readSummaryFromParcelLocked(in);
   13741         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
   13742         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
   13743         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
   13744         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
   13745         int NPKG = in.readInt();
   13746         if (NPKG > 0) {
   13747             mDailyPackageChanges = new ArrayList<>(NPKG);
   13748             while (NPKG > 0) {
   13749                 NPKG--;
   13750                 PackageChange pc = new PackageChange();
   13751                 pc.mPackageName = in.readString();
   13752                 pc.mUpdate = in.readInt() != 0;
   13753                 pc.mVersionCode = in.readLong();
   13754                 mDailyPackageChanges.add(pc);
   13755             }
   13756         } else {
   13757             mDailyPackageChanges = null;
   13758         }
   13759         mDailyStartTime = in.readLong();
   13760         mNextMinDailyDeadline = in.readLong();
   13761         mNextMaxDailyDeadline = in.readLong();
   13762 
   13763         mStartCount++;
   13764 
   13765         mScreenState = Display.STATE_UNKNOWN;
   13766         mScreenOnTimer.readSummaryFromParcelLocked(in);
   13767         mScreenDozeTimer.readSummaryFromParcelLocked(in);
   13768         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   13769             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
   13770         }
   13771         mInteractive = false;
   13772         mInteractiveTimer.readSummaryFromParcelLocked(in);
   13773         mPhoneOn = false;
   13774         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
   13775         mLongestLightIdleTime = in.readLong();
   13776         mLongestFullIdleTime = in.readLong();
   13777         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
   13778         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
   13779         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
   13780         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
   13781         mPhoneOnTimer.readSummaryFromParcelLocked(in);
   13782         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   13783             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
   13784         }
   13785         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
   13786         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   13787             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
   13788         }
   13789         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   13790             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
   13791             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
   13792         }
   13793         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
   13794         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
   13795         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
   13796         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
   13797         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
   13798         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
   13799         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
   13800         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
   13801         mWifiOn = false;
   13802         mWifiOnTimer.readSummaryFromParcelLocked(in);
   13803         mGlobalWifiRunning = false;
   13804         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
   13805         for (int i=0; i<NUM_WIFI_STATES; i++) {
   13806             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
   13807         }
   13808         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   13809             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
   13810         }
   13811         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   13812             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
   13813         }
   13814         mWifiActiveTimer.readSummaryFromParcelLocked(in);
   13815         mWifiActivity.readSummaryFromParcel(in);
   13816         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
   13817             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
   13818         }
   13819         mBluetoothActivity.readSummaryFromParcel(in);
   13820         mModemActivity.readSummaryFromParcel(in);
   13821         mHasWifiReporting = in.readInt() != 0;
   13822         mHasBluetoothReporting = in.readInt() != 0;
   13823         mHasModemReporting = in.readInt() != 0;
   13824 
   13825         mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
   13826         mFlashlightOnNesting = 0;
   13827         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
   13828         mCameraOnNesting = 0;
   13829         mCameraOnTimer.readSummaryFromParcelLocked(in);
   13830         mBluetoothScanNesting = 0;
   13831         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
   13832         mIsCellularTxPowerHigh = false;
   13833 
   13834         int NRPMS = in.readInt();
   13835         if (NRPMS > 10000) {
   13836             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
   13837         }
   13838         for (int irpm = 0; irpm < NRPMS; irpm++) {
   13839             if (in.readInt() != 0) {
   13840                 String rpmName = in.readString();
   13841                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
   13842             }
   13843         }
   13844         int NSORPMS = in.readInt();
   13845         if (NSORPMS > 10000) {
   13846             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
   13847         }
   13848         for (int irpm = 0; irpm < NSORPMS; irpm++) {
   13849             if (in.readInt() != 0) {
   13850                 String rpmName = in.readString();
   13851                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
   13852             }
   13853         }
   13854 
   13855         int NKW = in.readInt();
   13856         if (NKW > 10000) {
   13857             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
   13858         }
   13859         for (int ikw = 0; ikw < NKW; ikw++) {
   13860             if (in.readInt() != 0) {
   13861                 String kwltName = in.readString();
   13862                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
   13863             }
   13864         }
   13865 
   13866         int NWR = in.readInt();
   13867         if (NWR > 10000) {
   13868             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
   13869         }
   13870         for (int iwr = 0; iwr < NWR; iwr++) {
   13871             if (in.readInt() != 0) {
   13872                 String reasonName = in.readString();
   13873                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
   13874             }
   13875         }
   13876 
   13877         int NMS = in.readInt();
   13878         for (int ims = 0; ims < NMS; ims++) {
   13879             if (in.readInt() != 0) {
   13880                 long kmstName = in.readLong();
   13881                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
   13882             }
   13883         }
   13884 
   13885         final int NU = in.readInt();
   13886         if (NU > 10000) {
   13887             throw new ParcelFormatException("File corrupt: too many uids " + NU);
   13888         }
   13889         for (int iu = 0; iu < NU; iu++) {
   13890             int uid = in.readInt();
   13891             Uid u = new Uid(this, uid);
   13892             mUidStats.put(uid, u);
   13893 
   13894             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
   13895             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
   13896 
   13897             u.mWifiRunning = false;
   13898             if (in.readInt() != 0) {
   13899                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
   13900             }
   13901             u.mFullWifiLockOut = false;
   13902             if (in.readInt() != 0) {
   13903                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
   13904             }
   13905             u.mWifiScanStarted = false;
   13906             if (in.readInt() != 0) {
   13907                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
   13908             }
   13909             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
   13910             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   13911                 if (in.readInt() != 0) {
   13912                     u.makeWifiBatchedScanBin(i, null);
   13913                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
   13914                 }
   13915             }
   13916             u.mWifiMulticastEnabled = false;
   13917             if (in.readInt() != 0) {
   13918                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
   13919             }
   13920             if (in.readInt() != 0) {
   13921                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
   13922             }
   13923             if (in.readInt() != 0) {
   13924                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
   13925             }
   13926             if (in.readInt() != 0) {
   13927                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
   13928             }
   13929             if (in.readInt() != 0) {
   13930                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
   13931             }
   13932             if (in.readInt() != 0) {
   13933                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
   13934             }
   13935             if (in.readInt() != 0) {
   13936                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
   13937             }
   13938             if (in.readInt() != 0) {
   13939                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
   13940             }
   13941             if (in.readInt() != 0) {
   13942                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
   13943             }
   13944             if (in.readInt() != 0) {
   13945                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
   13946             }
   13947             if (in.readInt() != 0) {
   13948                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
   13949             }
   13950             if (in.readInt() != 0) {
   13951                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
   13952             }
   13953             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
   13954             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
   13955                 if (in.readInt() != 0) {
   13956                     u.makeProcessState(i, null);
   13957                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
   13958                 }
   13959             }
   13960             if (in.readInt() != 0) {
   13961                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
   13962             }
   13963 
   13964             if (in.readInt() != 0) {
   13965                 if (u.mUserActivityCounters == null) {
   13966                     u.initUserActivityLocked();
   13967                 }
   13968                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
   13969                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
   13970                 }
   13971             }
   13972 
   13973             if (in.readInt() != 0) {
   13974                 if (u.mNetworkByteActivityCounters == null) {
   13975                     u.initNetworkActivityLocked();
   13976                 }
   13977                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   13978                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
   13979                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
   13980                 }
   13981                 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
   13982                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
   13983             }
   13984 
   13985             u.mUserCpuTime.readSummaryFromParcelLocked(in);
   13986             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
   13987 
   13988             if (in.readInt() != 0) {
   13989                 final int numClusters = in.readInt();
   13990                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
   13991                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
   13992                 }
   13993 
   13994                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
   13995                 for (int cluster = 0; cluster < numClusters; cluster++) {
   13996                     if (in.readInt() != 0) {
   13997                         final int NSB = in.readInt();
   13998                         if (mPowerProfile != null &&
   13999                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
   14000                             throw new ParcelFormatException("File corrupt: too many speed bins " +
   14001                                     NSB);
   14002                         }
   14003 
   14004                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
   14005                         for (int speed = 0; speed < NSB; speed++) {
   14006                             if (in.readInt() != 0) {
   14007                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
   14008                                         mOnBatteryTimeBase);
   14009                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
   14010                             }
   14011                         }
   14012                     } else {
   14013                         u.mCpuClusterSpeedTimesUs[cluster] = null;
   14014                     }
   14015                 }
   14016             } else {
   14017                 u.mCpuClusterSpeedTimesUs = null;
   14018             }
   14019 
   14020             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
   14021                     in, mOnBatteryTimeBase);
   14022             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
   14023                     in, mOnBatteryScreenOffTimeBase);
   14024 
   14025             u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
   14026             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
   14027 
   14028             int length = in.readInt();
   14029             if (length == Uid.NUM_PROCESS_STATE) {
   14030                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
   14031                 for (int procState = 0; procState < length; ++procState) {
   14032                     u.mProcStateTimeMs[procState]
   14033                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
   14034                                     in, mOnBatteryTimeBase);
   14035                 }
   14036             } else {
   14037                 u.mProcStateTimeMs = null;
   14038             }
   14039             length = in.readInt();
   14040             if (length == Uid.NUM_PROCESS_STATE) {
   14041                 u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
   14042                 for (int procState = 0; procState < length; ++procState) {
   14043                     u.mProcStateScreenOffTimeMs[procState]
   14044                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
   14045                                     in, mOnBatteryScreenOffTimeBase);
   14046                 }
   14047             } else {
   14048                 u.mProcStateScreenOffTimeMs = null;
   14049             }
   14050 
   14051             if (in.readInt() != 0) {
   14052                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
   14053                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
   14054             } else {
   14055                 u.mMobileRadioApWakeupCount = null;
   14056             }
   14057 
   14058             if (in.readInt() != 0) {
   14059                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
   14060                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
   14061             } else {
   14062                 u.mWifiRadioApWakeupCount = null;
   14063             }
   14064 
   14065             int NW = in.readInt();
   14066             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
   14067                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
   14068             }
   14069             for (int iw = 0; iw < NW; iw++) {
   14070                 String wlName = in.readString();
   14071                 u.readWakeSummaryFromParcelLocked(wlName, in);
   14072             }
   14073 
   14074             int NS = in.readInt();
   14075             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
   14076                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
   14077             }
   14078             for (int is = 0; is < NS; is++) {
   14079                 String name = in.readString();
   14080                 u.readSyncSummaryFromParcelLocked(name, in);
   14081             }
   14082 
   14083             int NJ = in.readInt();
   14084             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
   14085                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
   14086             }
   14087             for (int ij = 0; ij < NJ; ij++) {
   14088                 String name = in.readString();
   14089                 u.readJobSummaryFromParcelLocked(name, in);
   14090             }
   14091 
   14092             u.readJobCompletionsFromParcelLocked(in);
   14093 
   14094             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
   14095             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
   14096             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
   14097             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
   14098                 if (in.readInt() != 0) {
   14099                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
   14100                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
   14101                 }
   14102             }
   14103 
   14104             int NP = in.readInt();
   14105             if (NP > 1000) {
   14106                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
   14107             }
   14108             for (int is = 0; is < NP; is++) {
   14109                 int seNumber = in.readInt();
   14110                 if (in.readInt() != 0) {
   14111                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
   14112                 }
   14113             }
   14114 
   14115             NP = in.readInt();
   14116             if (NP > 1000) {
   14117                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
   14118             }
   14119             for (int ip = 0; ip < NP; ip++) {
   14120                 String procName = in.readString();
   14121                 Uid.Proc p = u.getProcessStatsLocked(procName);
   14122                 p.mUserTime = p.mLoadedUserTime = in.readLong();
   14123                 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
   14124                 p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
   14125                 p.mStarts = p.mLoadedStarts = in.readInt();
   14126                 p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
   14127                 p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
   14128                 p.readExcessivePowerFromParcelLocked(in);
   14129             }
   14130 
   14131             NP = in.readInt();
   14132             if (NP > 10000) {
   14133                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
   14134             }
   14135             for (int ip = 0; ip < NP; ip++) {
   14136                 String pkgName = in.readString();
   14137                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
   14138                 final int NWA = in.readInt();
   14139                 if (NWA > 1000) {
   14140                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
   14141                 }
   14142                 p.mWakeupAlarms.clear();
   14143                 for (int iwa=0; iwa<NWA; iwa++) {
   14144                     String tag = in.readString();
   14145                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
   14146                     c.readSummaryFromParcelLocked(in);
   14147                     p.mWakeupAlarms.put(tag, c);
   14148                 }
   14149                 NS = in.readInt();
   14150                 if (NS > 1000) {
   14151                     throw new ParcelFormatException("File corrupt: too many services " + NS);
   14152                 }
   14153                 for (int is = 0; is < NS; is++) {
   14154                     String servName = in.readString();
   14155                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
   14156                     s.mStartTime = s.mLoadedStartTime = in.readLong();
   14157                     s.mStarts = s.mLoadedStarts = in.readInt();
   14158                     s.mLaunches = s.mLoadedLaunches = in.readInt();
   14159                 }
   14160             }
   14161         }
   14162     }
   14163 
   14164     /**
   14165      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
   14166      * disk.  This format does not allow a lossless round-trip.
   14167      *
   14168      * @param out the Parcel to be written to.
   14169      */
   14170     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
   14171         pullPendingStateUpdatesLocked();
   14172 
   14173         // Pull the clock time.  This may update the time and make a new history entry
   14174         // if we had originally pulled a time before the RTC was set.
   14175         long startClockTime = getStartClockTime();
   14176 
   14177         final long NOW_SYS = mClocks.uptimeMillis() * 1000;
   14178         final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
   14179 
   14180         out.writeInt(VERSION);
   14181 
   14182         writeHistory(out, inclHistory, true);
   14183 
   14184         out.writeInt(mStartCount);
   14185         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
   14186         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
   14187         out.writeLong(startClockTime);
   14188         out.writeString(mStartPlatformVersion);
   14189         out.writeString(mEndPlatformVersion);
   14190         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
   14191         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
   14192         out.writeInt(mDischargeUnplugLevel);
   14193         out.writeInt(mDischargePlugLevel);
   14194         out.writeInt(mDischargeCurrentLevel);
   14195         out.writeInt(mCurrentBatteryLevel);
   14196         out.writeInt(mEstimatedBatteryCapacity);
   14197         out.writeInt(mMinLearnedBatteryCapacity);
   14198         out.writeInt(mMaxLearnedBatteryCapacity);
   14199         out.writeInt(getLowDischargeAmountSinceCharge());
   14200         out.writeInt(getHighDischargeAmountSinceCharge());
   14201         out.writeInt(getDischargeAmountScreenOnSinceCharge());
   14202         out.writeInt(getDischargeAmountScreenOffSinceCharge());
   14203         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
   14204         mDischargeStepTracker.writeToParcel(out);
   14205         mChargeStepTracker.writeToParcel(out);
   14206         mDailyDischargeStepTracker.writeToParcel(out);
   14207         mDailyChargeStepTracker.writeToParcel(out);
   14208         mDischargeCounter.writeSummaryFromParcelLocked(out);
   14209         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
   14210         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
   14211         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
   14212         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
   14213         if (mDailyPackageChanges != null) {
   14214             final int NPKG = mDailyPackageChanges.size();
   14215             out.writeInt(NPKG);
   14216             for (int i=0; i<NPKG; i++) {
   14217                 PackageChange pc = mDailyPackageChanges.get(i);
   14218                 out.writeString(pc.mPackageName);
   14219                 out.writeInt(pc.mUpdate ? 1 : 0);
   14220                 out.writeLong(pc.mVersionCode);
   14221             }
   14222         } else {
   14223             out.writeInt(0);
   14224         }
   14225         out.writeLong(mDailyStartTime);
   14226         out.writeLong(mNextMinDailyDeadline);
   14227         out.writeLong(mNextMaxDailyDeadline);
   14228 
   14229         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14230         mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14231         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   14232             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14233         }
   14234         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14235         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14236         out.writeLong(mLongestLightIdleTime);
   14237         out.writeLong(mLongestFullIdleTime);
   14238         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14239         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14240         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14241         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14242         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14243         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   14244             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14245         }
   14246         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14247         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   14248             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14249         }
   14250         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   14251             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
   14252             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
   14253         }
   14254         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14255         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14256         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
   14257         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
   14258         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
   14259         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14260         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14261         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14262         for (int i=0; i<NUM_WIFI_STATES; i++) {
   14263             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14264         }
   14265         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   14266             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14267         }
   14268         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   14269             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14270         }
   14271         mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14272         mWifiActivity.writeSummaryToParcel(out);
   14273         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
   14274             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14275         }
   14276         mBluetoothActivity.writeSummaryToParcel(out);
   14277         mModemActivity.writeSummaryToParcel(out);
   14278         out.writeInt(mHasWifiReporting ? 1 : 0);
   14279         out.writeInt(mHasBluetoothReporting ? 1 : 0);
   14280         out.writeInt(mHasModemReporting ? 1 : 0);
   14281 
   14282         out.writeInt(mNumConnectivityChange);
   14283         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14284         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14285         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14286 
   14287         out.writeInt(mRpmStats.size());
   14288         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
   14289             Timer rpmt = ent.getValue();
   14290             if (rpmt != null) {
   14291                 out.writeInt(1);
   14292                 out.writeString(ent.getKey());
   14293                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14294             } else {
   14295                 out.writeInt(0);
   14296             }
   14297         }
   14298         out.writeInt(mScreenOffRpmStats.size());
   14299         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
   14300             Timer rpmt = ent.getValue();
   14301             if (rpmt != null) {
   14302                 out.writeInt(1);
   14303                 out.writeString(ent.getKey());
   14304                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14305             } else {
   14306                 out.writeInt(0);
   14307             }
   14308         }
   14309 
   14310         out.writeInt(mKernelWakelockStats.size());
   14311         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
   14312             Timer kwlt = ent.getValue();
   14313             if (kwlt != null) {
   14314                 out.writeInt(1);
   14315                 out.writeString(ent.getKey());
   14316                 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14317             } else {
   14318                 out.writeInt(0);
   14319             }
   14320         }
   14321 
   14322         out.writeInt(mWakeupReasonStats.size());
   14323         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
   14324             SamplingTimer timer = ent.getValue();
   14325             if (timer != null) {
   14326                 out.writeInt(1);
   14327                 out.writeString(ent.getKey());
   14328                 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14329             } else {
   14330                 out.writeInt(0);
   14331             }
   14332         }
   14333 
   14334         out.writeInt(mKernelMemoryStats.size());
   14335         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
   14336             Timer kmt = mKernelMemoryStats.valueAt(i);
   14337             if (kmt != null) {
   14338                 out.writeInt(1);
   14339                 out.writeLong(mKernelMemoryStats.keyAt(i));
   14340                 kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14341             } else {
   14342                 out.writeInt(0);
   14343             }
   14344         }
   14345 
   14346         final int NU = mUidStats.size();
   14347         out.writeInt(NU);
   14348         for (int iu = 0; iu < NU; iu++) {
   14349             out.writeInt(mUidStats.keyAt(iu));
   14350             Uid u = mUidStats.valueAt(iu);
   14351 
   14352             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
   14353             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
   14354 
   14355             if (u.mWifiRunningTimer != null) {
   14356                 out.writeInt(1);
   14357                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14358             } else {
   14359                 out.writeInt(0);
   14360             }
   14361             if (u.mFullWifiLockTimer != null) {
   14362                 out.writeInt(1);
   14363                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14364             } else {
   14365                 out.writeInt(0);
   14366             }
   14367             if (u.mWifiScanTimer != null) {
   14368                 out.writeInt(1);
   14369                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14370             } else {
   14371                 out.writeInt(0);
   14372             }
   14373             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
   14374                 if (u.mWifiBatchedScanTimer[i] != null) {
   14375                     out.writeInt(1);
   14376                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14377                 } else {
   14378                     out.writeInt(0);
   14379                 }
   14380             }
   14381             if (u.mWifiMulticastTimer != null) {
   14382                 out.writeInt(1);
   14383                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14384             } else {
   14385                 out.writeInt(0);
   14386             }
   14387             if (u.mAudioTurnedOnTimer != null) {
   14388                 out.writeInt(1);
   14389                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14390             } else {
   14391                 out.writeInt(0);
   14392             }
   14393             if (u.mVideoTurnedOnTimer != null) {
   14394                 out.writeInt(1);
   14395                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14396             } else {
   14397                 out.writeInt(0);
   14398             }
   14399             if (u.mFlashlightTurnedOnTimer != null) {
   14400                 out.writeInt(1);
   14401                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14402             } else {
   14403                 out.writeInt(0);
   14404             }
   14405             if (u.mCameraTurnedOnTimer != null) {
   14406                 out.writeInt(1);
   14407                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14408             } else {
   14409                 out.writeInt(0);
   14410             }
   14411             if (u.mForegroundActivityTimer != null) {
   14412                 out.writeInt(1);
   14413                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14414             } else {
   14415                 out.writeInt(0);
   14416             }
   14417             if (u.mForegroundServiceTimer != null) {
   14418                 out.writeInt(1);
   14419                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14420             } else {
   14421                 out.writeInt(0);
   14422             }
   14423             if (u.mAggregatedPartialWakelockTimer != null) {
   14424                 out.writeInt(1);
   14425                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14426             } else {
   14427                 out.writeInt(0);
   14428             }
   14429             if (u.mBluetoothScanTimer != null) {
   14430                 out.writeInt(1);
   14431                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14432             } else {
   14433                 out.writeInt(0);
   14434             }
   14435             if (u.mBluetoothUnoptimizedScanTimer != null) {
   14436                 out.writeInt(1);
   14437                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14438             } else {
   14439                 out.writeInt(0);
   14440             }
   14441             if (u.mBluetoothScanResultCounter != null) {
   14442                 out.writeInt(1);
   14443                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
   14444             } else {
   14445                 out.writeInt(0);
   14446             }
   14447             if (u.mBluetoothScanResultBgCounter != null) {
   14448                 out.writeInt(1);
   14449                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
   14450             } else {
   14451                 out.writeInt(0);
   14452             }
   14453             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
   14454                 if (u.mProcessStateTimer[i] != null) {
   14455                     out.writeInt(1);
   14456                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14457                 } else {
   14458                     out.writeInt(0);
   14459                 }
   14460             }
   14461             if (u.mVibratorOnTimer != null) {
   14462                 out.writeInt(1);
   14463                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14464             } else {
   14465                 out.writeInt(0);
   14466             }
   14467 
   14468             if (u.mUserActivityCounters == null) {
   14469                 out.writeInt(0);
   14470             } else {
   14471                 out.writeInt(1);
   14472                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
   14473                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
   14474                 }
   14475             }
   14476 
   14477             if (u.mNetworkByteActivityCounters == null) {
   14478                 out.writeInt(0);
   14479             } else {
   14480                 out.writeInt(1);
   14481                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   14482                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
   14483                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
   14484                 }
   14485                 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
   14486                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
   14487             }
   14488 
   14489             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
   14490             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
   14491 
   14492             if (u.mCpuClusterSpeedTimesUs != null) {
   14493                 out.writeInt(1);
   14494                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
   14495                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
   14496                     if (cpuSpeeds != null) {
   14497                         out.writeInt(1);
   14498                         out.writeInt(cpuSpeeds.length);
   14499                         for (LongSamplingCounter c : cpuSpeeds) {
   14500                             if (c != null) {
   14501                                 out.writeInt(1);
   14502                                 c.writeSummaryFromParcelLocked(out);
   14503                             } else {
   14504                                 out.writeInt(0);
   14505                             }
   14506                         }
   14507                     } else {
   14508                         out.writeInt(0);
   14509                     }
   14510                 }
   14511             } else {
   14512                 out.writeInt(0);
   14513             }
   14514 
   14515             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
   14516             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
   14517 
   14518             u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
   14519             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
   14520 
   14521             if (u.mProcStateTimeMs != null) {
   14522                 out.writeInt(u.mProcStateTimeMs.length);
   14523                 for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
   14524                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
   14525                 }
   14526             } else {
   14527                 out.writeInt(0);
   14528             }
   14529             if (u.mProcStateScreenOffTimeMs != null) {
   14530                 out.writeInt(u.mProcStateScreenOffTimeMs.length);
   14531                 for (LongSamplingCounterArray counters : u.mProcStateScreenOffTimeMs) {
   14532                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
   14533                 }
   14534             } else {
   14535                 out.writeInt(0);
   14536             }
   14537 
   14538             if (u.mMobileRadioApWakeupCount != null) {
   14539                 out.writeInt(1);
   14540                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
   14541             } else {
   14542                 out.writeInt(0);
   14543             }
   14544 
   14545             if (u.mWifiRadioApWakeupCount != null) {
   14546                 out.writeInt(1);
   14547                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
   14548             } else {
   14549                 out.writeInt(0);
   14550             }
   14551 
   14552             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
   14553             int NW = wakeStats.size();
   14554             out.writeInt(NW);
   14555             for (int iw=0; iw<NW; iw++) {
   14556                 out.writeString(wakeStats.keyAt(iw));
   14557                 Uid.Wakelock wl = wakeStats.valueAt(iw);
   14558                 if (wl.mTimerFull != null) {
   14559                     out.writeInt(1);
   14560                     wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14561                 } else {
   14562                     out.writeInt(0);
   14563                 }
   14564                 if (wl.mTimerPartial != null) {
   14565                     out.writeInt(1);
   14566                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14567                 } else {
   14568                     out.writeInt(0);
   14569                 }
   14570                 if (wl.mTimerWindow != null) {
   14571                     out.writeInt(1);
   14572                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14573                 } else {
   14574                     out.writeInt(0);
   14575                 }
   14576                 if (wl.mTimerDraw != null) {
   14577                     out.writeInt(1);
   14578                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14579                 } else {
   14580                     out.writeInt(0);
   14581                 }
   14582             }
   14583 
   14584             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
   14585             int NS = syncStats.size();
   14586             out.writeInt(NS);
   14587             for (int is=0; is<NS; is++) {
   14588                 out.writeString(syncStats.keyAt(is));
   14589                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14590             }
   14591 
   14592             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
   14593             int NJ = jobStats.size();
   14594             out.writeInt(NJ);
   14595             for (int ij=0; ij<NJ; ij++) {
   14596                 out.writeString(jobStats.keyAt(ij));
   14597                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14598             }
   14599 
   14600             u.writeJobCompletionsToParcelLocked(out);
   14601 
   14602             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
   14603             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
   14604             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
   14605             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
   14606                 if (u.mJobsFreshnessBuckets[i] != null) {
   14607                     out.writeInt(1);
   14608                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
   14609                 } else {
   14610                     out.writeInt(0);
   14611                 }
   14612             }
   14613 
   14614             int NSE = u.mSensorStats.size();
   14615             out.writeInt(NSE);
   14616             for (int ise=0; ise<NSE; ise++) {
   14617                 out.writeInt(u.mSensorStats.keyAt(ise));
   14618                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
   14619                 if (se.mTimer != null) {
   14620                     out.writeInt(1);
   14621                     se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
   14622                 } else {
   14623                     out.writeInt(0);
   14624                 }
   14625             }
   14626 
   14627             int NP = u.mProcessStats.size();
   14628             out.writeInt(NP);
   14629             for (int ip=0; ip<NP; ip++) {
   14630                 out.writeString(u.mProcessStats.keyAt(ip));
   14631                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
   14632                 out.writeLong(ps.mUserTime);
   14633                 out.writeLong(ps.mSystemTime);
   14634                 out.writeLong(ps.mForegroundTime);
   14635                 out.writeInt(ps.mStarts);
   14636                 out.writeInt(ps.mNumCrashes);
   14637                 out.writeInt(ps.mNumAnrs);
   14638                 ps.writeExcessivePowerToParcelLocked(out);
   14639             }
   14640 
   14641             NP = u.mPackageStats.size();
   14642             out.writeInt(NP);
   14643             if (NP > 0) {
   14644                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
   14645                     : u.mPackageStats.entrySet()) {
   14646                     out.writeString(ent.getKey());
   14647                     Uid.Pkg ps = ent.getValue();
   14648                     final int NWA = ps.mWakeupAlarms.size();
   14649                     out.writeInt(NWA);
   14650                     for (int iwa=0; iwa<NWA; iwa++) {
   14651                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
   14652                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
   14653                     }
   14654                     NS = ps.mServiceStats.size();
   14655                     out.writeInt(NS);
   14656                     for (int is=0; is<NS; is++) {
   14657                         out.writeString(ps.mServiceStats.keyAt(is));
   14658                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
   14659                         long time = ss.getStartTimeToNowLocked(
   14660                                 mOnBatteryTimeBase.getUptime(NOW_SYS));
   14661                         out.writeLong(time);
   14662                         out.writeInt(ss.mStarts);
   14663                         out.writeInt(ss.mLaunches);
   14664                     }
   14665                 }
   14666             }
   14667         }
   14668     }
   14669 
   14670     public void readFromParcel(Parcel in) {
   14671         readFromParcelLocked(in);
   14672     }
   14673 
   14674     void readFromParcelLocked(Parcel in) {
   14675         int magic = in.readInt();
   14676         if (magic != MAGIC) {
   14677             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
   14678         }
   14679 
   14680         readHistory(in, false);
   14681 
   14682         mStartCount = in.readInt();
   14683         mStartClockTime = in.readLong();
   14684         mStartPlatformVersion = in.readString();
   14685         mEndPlatformVersion = in.readString();
   14686         mUptime = in.readLong();
   14687         mUptimeStart = in.readLong();
   14688         mRealtime = in.readLong();
   14689         mRealtimeStart = in.readLong();
   14690         mOnBattery = in.readInt() != 0;
   14691         mEstimatedBatteryCapacity = in.readInt();
   14692         mMinLearnedBatteryCapacity = in.readInt();
   14693         mMaxLearnedBatteryCapacity = in.readInt();
   14694         mOnBatteryInternal = false; // we are no longer really running.
   14695         mOnBatteryTimeBase.readFromParcel(in);
   14696         mOnBatteryScreenOffTimeBase.readFromParcel(in);
   14697 
   14698         mScreenState = Display.STATE_UNKNOWN;
   14699         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
   14700         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
   14701         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   14702             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
   14703                     mOnBatteryTimeBase, in);
   14704         }
   14705         mInteractive = false;
   14706         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
   14707         mPhoneOn = false;
   14708         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
   14709                 mOnBatteryTimeBase, in);
   14710         mLongestLightIdleTime = in.readLong();
   14711         mLongestFullIdleTime = in.readLong();
   14712         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
   14713                 mOnBatteryTimeBase, in);
   14714         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
   14715                 mOnBatteryTimeBase, in);
   14716         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
   14717                 mOnBatteryTimeBase, in);
   14718         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
   14719         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
   14720         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   14721             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
   14722                     null, mOnBatteryTimeBase, in);
   14723         }
   14724         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
   14725                 mOnBatteryTimeBase, in);
   14726         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   14727             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
   14728                     null, mOnBatteryTimeBase, in);
   14729         }
   14730         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   14731             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
   14732             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
   14733         }
   14734         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
   14735         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
   14736                 mOnBatteryTimeBase, in);
   14737         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
   14738                 mOnBatteryTimeBase, in);
   14739         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
   14740         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
   14741         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
   14742         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null, -4, null,
   14743                 mOnBatteryTimeBase, in);
   14744         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
   14745         mWifiOn = false;
   14746         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
   14747         mGlobalWifiRunning = false;
   14748         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
   14749                 mOnBatteryTimeBase, in);
   14750         for (int i=0; i<NUM_WIFI_STATES; i++) {
   14751             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
   14752                     null, mOnBatteryTimeBase, in);
   14753         }
   14754         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   14755             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
   14756                     null, mOnBatteryTimeBase, in);
   14757         }
   14758         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   14759             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
   14760                     null, mOnBatteryTimeBase, in);
   14761         }
   14762         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null,
   14763             mOnBatteryTimeBase, in);
   14764         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
   14765                 NUM_WIFI_TX_LEVELS, in);
   14766         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
   14767             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
   14768                 null, mOnBatteryTimeBase, in);
   14769         }
   14770         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
   14771                 NUM_BT_TX_LEVELS, in);
   14772         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
   14773                 ModemActivityInfo.TX_POWER_LEVELS, in);
   14774         mHasWifiReporting = in.readInt() != 0;
   14775         mHasBluetoothReporting = in.readInt() != 0;
   14776         mHasModemReporting = in.readInt() != 0;
   14777 
   14778         mNumConnectivityChange = in.readInt();
   14779         mLoadedNumConnectivityChange = in.readInt();
   14780         mUnpluggedNumConnectivityChange = in.readInt();
   14781         mAudioOnNesting = 0;
   14782         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
   14783         mVideoOnNesting = 0;
   14784         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
   14785         mFlashlightOnNesting = 0;
   14786         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
   14787         mCameraOnNesting = 0;
   14788         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
   14789         mBluetoothScanNesting = 0;
   14790         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
   14791         mIsCellularTxPowerHigh = false;
   14792         mDischargeUnplugLevel = in.readInt();
   14793         mDischargePlugLevel = in.readInt();
   14794         mDischargeCurrentLevel = in.readInt();
   14795         mCurrentBatteryLevel = in.readInt();
   14796         mLowDischargeAmountSinceCharge = in.readInt();
   14797         mHighDischargeAmountSinceCharge = in.readInt();
   14798         mDischargeAmountScreenOn = in.readInt();
   14799         mDischargeAmountScreenOnSinceCharge = in.readInt();
   14800         mDischargeAmountScreenOff = in.readInt();
   14801         mDischargeAmountScreenOffSinceCharge = in.readInt();
   14802         mDischargeAmountScreenDoze = in.readInt();
   14803         mDischargeAmountScreenDozeSinceCharge = in.readInt();
   14804         mDischargeStepTracker.readFromParcel(in);
   14805         mChargeStepTracker.readFromParcel(in);
   14806         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
   14807         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
   14808         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
   14809         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
   14810         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
   14811         mLastWriteTime = in.readLong();
   14812 
   14813         mRpmStats.clear();
   14814         int NRPMS = in.readInt();
   14815         for (int irpm = 0; irpm < NRPMS; irpm++) {
   14816             if (in.readInt() != 0) {
   14817                 String rpmName = in.readString();
   14818                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
   14819                 mRpmStats.put(rpmName, rpmt);
   14820             }
   14821         }
   14822         mScreenOffRpmStats.clear();
   14823         int NSORPMS = in.readInt();
   14824         for (int irpm = 0; irpm < NSORPMS; irpm++) {
   14825             if (in.readInt() != 0) {
   14826                 String rpmName = in.readString();
   14827                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
   14828                 mScreenOffRpmStats.put(rpmName, rpmt);
   14829             }
   14830         }
   14831 
   14832         mKernelWakelockStats.clear();
   14833         int NKW = in.readInt();
   14834         for (int ikw = 0; ikw < NKW; ikw++) {
   14835             if (in.readInt() != 0) {
   14836                 String wakelockName = in.readString();
   14837                 SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
   14838                 mKernelWakelockStats.put(wakelockName, kwlt);
   14839             }
   14840         }
   14841 
   14842         mWakeupReasonStats.clear();
   14843         int NWR = in.readInt();
   14844         for (int iwr = 0; iwr < NWR; iwr++) {
   14845             if (in.readInt() != 0) {
   14846                 String reasonName = in.readString();
   14847                 SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
   14848                 mWakeupReasonStats.put(reasonName, timer);
   14849             }
   14850         }
   14851 
   14852         mKernelMemoryStats.clear();
   14853         int nmt = in.readInt();
   14854         for (int imt = 0; imt < nmt; imt++) {
   14855             if (in.readInt() != 0) {
   14856                 Long bucket = in.readLong();
   14857                 SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
   14858                 mKernelMemoryStats.put(bucket, kmt);
   14859             }
   14860         }
   14861 
   14862         mPartialTimers.clear();
   14863         mFullTimers.clear();
   14864         mWindowTimers.clear();
   14865         mWifiRunningTimers.clear();
   14866         mFullWifiLockTimers.clear();
   14867         mWifiScanTimers.clear();
   14868         mWifiBatchedScanTimers.clear();
   14869         mWifiMulticastTimers.clear();
   14870         mAudioTurnedOnTimers.clear();
   14871         mVideoTurnedOnTimers.clear();
   14872         mFlashlightTurnedOnTimers.clear();
   14873         mCameraTurnedOnTimers.clear();
   14874 
   14875         int numUids = in.readInt();
   14876         mUidStats.clear();
   14877         for (int i = 0; i < numUids; i++) {
   14878             int uid = in.readInt();
   14879             Uid u = new Uid(this, uid);
   14880             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
   14881             mUidStats.append(uid, u);
   14882         }
   14883     }
   14884 
   14885     public void writeToParcel(Parcel out, int flags) {
   14886         writeToParcelLocked(out, true, flags);
   14887     }
   14888 
   14889     public void writeToParcelWithoutUids(Parcel out, int flags) {
   14890         writeToParcelLocked(out, false, flags);
   14891     }
   14892 
   14893     @SuppressWarnings("unused")
   14894     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
   14895         // Need to update with current kernel wake lock counts.
   14896         pullPendingStateUpdatesLocked();
   14897 
   14898         // Pull the clock time.  This may update the time and make a new history entry
   14899         // if we had originally pulled a time before the RTC was set.
   14900         long startClockTime = getStartClockTime();
   14901 
   14902         final long uSecUptime = mClocks.uptimeMillis() * 1000;
   14903         final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
   14904         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
   14905         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
   14906 
   14907         out.writeInt(MAGIC);
   14908 
   14909         writeHistory(out, true, false);
   14910 
   14911         out.writeInt(mStartCount);
   14912         out.writeLong(startClockTime);
   14913         out.writeString(mStartPlatformVersion);
   14914         out.writeString(mEndPlatformVersion);
   14915         out.writeLong(mUptime);
   14916         out.writeLong(mUptimeStart);
   14917         out.writeLong(mRealtime);
   14918         out.writeLong(mRealtimeStart);
   14919         out.writeInt(mOnBattery ? 1 : 0);
   14920         out.writeInt(mEstimatedBatteryCapacity);
   14921         out.writeInt(mMinLearnedBatteryCapacity);
   14922         out.writeInt(mMaxLearnedBatteryCapacity);
   14923         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
   14924         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
   14925 
   14926         mScreenOnTimer.writeToParcel(out, uSecRealtime);
   14927         mScreenDozeTimer.writeToParcel(out, uSecRealtime);
   14928         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   14929             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
   14930         }
   14931         mInteractiveTimer.writeToParcel(out, uSecRealtime);
   14932         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
   14933         out.writeLong(mLongestLightIdleTime);
   14934         out.writeLong(mLongestFullIdleTime);
   14935         mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
   14936         mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
   14937         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
   14938         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
   14939         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
   14940         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   14941             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
   14942         }
   14943         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
   14944         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   14945             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
   14946         }
   14947         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
   14948             mNetworkByteActivityCounters[i].writeToParcel(out);
   14949             mNetworkPacketActivityCounters[i].writeToParcel(out);
   14950         }
   14951         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
   14952         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
   14953         mMobileRadioActiveAdjustedTime.writeToParcel(out);
   14954         mMobileRadioActiveUnknownTime.writeToParcel(out);
   14955         mMobileRadioActiveUnknownCount.writeToParcel(out);
   14956         mWifiMulticastWakelockTimer.writeToParcel(out, uSecRealtime);
   14957         mWifiOnTimer.writeToParcel(out, uSecRealtime);
   14958         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
   14959         for (int i=0; i<NUM_WIFI_STATES; i++) {
   14960             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
   14961         }
   14962         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   14963             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
   14964         }
   14965         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   14966             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
   14967         }
   14968         mWifiActiveTimer.writeToParcel(out, uSecRealtime);
   14969         mWifiActivity.writeToParcel(out, 0);
   14970         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
   14971             mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
   14972         }
   14973         mBluetoothActivity.writeToParcel(out, 0);
   14974         mModemActivity.writeToParcel(out, 0);
   14975         out.writeInt(mHasWifiReporting ? 1 : 0);
   14976         out.writeInt(mHasBluetoothReporting ? 1 : 0);
   14977         out.writeInt(mHasModemReporting ? 1 : 0);
   14978 
   14979         out.writeInt(mNumConnectivityChange);
   14980         out.writeInt(mLoadedNumConnectivityChange);
   14981         out.writeInt(mUnpluggedNumConnectivityChange);
   14982         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
   14983         mCameraOnTimer.writeToParcel(out, uSecRealtime);
   14984         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
   14985         out.writeInt(mDischargeUnplugLevel);
   14986         out.writeInt(mDischargePlugLevel);
   14987         out.writeInt(mDischargeCurrentLevel);
   14988         out.writeInt(mCurrentBatteryLevel);
   14989         out.writeInt(mLowDischargeAmountSinceCharge);
   14990         out.writeInt(mHighDischargeAmountSinceCharge);
   14991         out.writeInt(mDischargeAmountScreenOn);
   14992         out.writeInt(mDischargeAmountScreenOnSinceCharge);
   14993         out.writeInt(mDischargeAmountScreenOff);
   14994         out.writeInt(mDischargeAmountScreenOffSinceCharge);
   14995         out.writeInt(mDischargeAmountScreenDoze);
   14996         out.writeInt(mDischargeAmountScreenDozeSinceCharge);
   14997         mDischargeStepTracker.writeToParcel(out);
   14998         mChargeStepTracker.writeToParcel(out);
   14999         mDischargeCounter.writeToParcel(out);
   15000         mDischargeScreenOffCounter.writeToParcel(out);
   15001         mDischargeScreenDozeCounter.writeToParcel(out);
   15002         mDischargeLightDozeCounter.writeToParcel(out);
   15003         mDischargeDeepDozeCounter.writeToParcel(out);
   15004         out.writeLong(mLastWriteTime);
   15005 
   15006         out.writeInt(mRpmStats.size());
   15007         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
   15008             SamplingTimer rpmt = ent.getValue();
   15009             if (rpmt != null) {
   15010                 out.writeInt(1);
   15011                 out.writeString(ent.getKey());
   15012                 rpmt.writeToParcel(out, uSecRealtime);
   15013             } else {
   15014                 out.writeInt(0);
   15015             }
   15016         }
   15017         out.writeInt(mScreenOffRpmStats.size());
   15018         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
   15019             SamplingTimer rpmt = ent.getValue();
   15020             if (rpmt != null) {
   15021                 out.writeInt(1);
   15022                 out.writeString(ent.getKey());
   15023                 rpmt.writeToParcel(out, uSecRealtime);
   15024             } else {
   15025                 out.writeInt(0);
   15026             }
   15027         }
   15028 
   15029         if (inclUids) {
   15030             out.writeInt(mKernelWakelockStats.size());
   15031             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
   15032                 SamplingTimer kwlt = ent.getValue();
   15033                 if (kwlt != null) {
   15034                     out.writeInt(1);
   15035                     out.writeString(ent.getKey());
   15036                     kwlt.writeToParcel(out, uSecRealtime);
   15037                 } else {
   15038                     out.writeInt(0);
   15039                 }
   15040             }
   15041             out.writeInt(mWakeupReasonStats.size());
   15042             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
   15043                 SamplingTimer timer = ent.getValue();
   15044                 if (timer != null) {
   15045                     out.writeInt(1);
   15046                     out.writeString(ent.getKey());
   15047                     timer.writeToParcel(out, uSecRealtime);
   15048                 } else {
   15049                     out.writeInt(0);
   15050                 }
   15051             }
   15052         } else {
   15053             out.writeInt(0);
   15054             out.writeInt(0);
   15055         }
   15056 
   15057         out.writeInt(mKernelMemoryStats.size());
   15058         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
   15059             SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
   15060             if (kmt != null) {
   15061                 out.writeInt(1);
   15062                 out.writeLong(mKernelMemoryStats.keyAt(i));
   15063                 kmt.writeToParcel(out, uSecRealtime);
   15064             } else {
   15065                 out.writeInt(0);
   15066             }
   15067         }
   15068 
   15069         if (inclUids) {
   15070             int size = mUidStats.size();
   15071             out.writeInt(size);
   15072             for (int i = 0; i < size; i++) {
   15073                 out.writeInt(mUidStats.keyAt(i));
   15074                 Uid uid = mUidStats.valueAt(i);
   15075 
   15076                 uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
   15077             }
   15078         } else {
   15079             out.writeInt(0);
   15080         }
   15081     }
   15082 
   15083     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
   15084         new Parcelable.Creator<BatteryStatsImpl>() {
   15085         public BatteryStatsImpl createFromParcel(Parcel in) {
   15086             return new BatteryStatsImpl(in);
   15087         }
   15088 
   15089         public BatteryStatsImpl[] newArray(int size) {
   15090             return new BatteryStatsImpl[size];
   15091         }
   15092     };
   15093 
   15094     public void prepareForDumpLocked() {
   15095         // Need to retrieve current kernel wake lock stats before printing.
   15096         pullPendingStateUpdatesLocked();
   15097 
   15098         // Pull the clock time.  This may update the time and make a new history entry
   15099         // if we had originally pulled a time before the RTC was set.
   15100         getStartClockTime();
   15101     }
   15102 
   15103     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
   15104         if (DEBUG) {
   15105             pw.println("mOnBatteryTimeBase:");
   15106             mOnBatteryTimeBase.dump(pw, "  ");
   15107             pw.println("mOnBatteryScreenOffTimeBase:");
   15108             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
   15109             Printer pr = new PrintWriterPrinter(pw);
   15110             pr.println("*** Screen on timer:");
   15111             mScreenOnTimer.logState(pr, "  ");
   15112             pr.println("*** Screen doze timer:");
   15113             mScreenDozeTimer.logState(pr, "  ");
   15114             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
   15115                 pr.println("*** Screen brightness #" + i + ":");
   15116                 mScreenBrightnessTimer[i].logState(pr, "  ");
   15117             }
   15118             pr.println("*** Interactive timer:");
   15119             mInteractiveTimer.logState(pr, "  ");
   15120             pr.println("*** Power save mode timer:");
   15121             mPowerSaveModeEnabledTimer.logState(pr, "  ");
   15122             pr.println("*** Device idle mode light timer:");
   15123             mDeviceIdleModeLightTimer.logState(pr, "  ");
   15124             pr.println("*** Device idle mode full timer:");
   15125             mDeviceIdleModeFullTimer.logState(pr, "  ");
   15126             pr.println("*** Device light idling timer:");
   15127             mDeviceLightIdlingTimer.logState(pr, "  ");
   15128             pr.println("*** Device idling timer:");
   15129             mDeviceIdlingTimer.logState(pr, "  ");
   15130             pr.println("*** Phone timer:");
   15131             mPhoneOnTimer.logState(pr, "  ");
   15132             for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
   15133                 pr.println("*** Phone signal strength #" + i + ":");
   15134                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
   15135             }
   15136             pr.println("*** Signal scanning :");
   15137             mPhoneSignalScanningTimer.logState(pr, "  ");
   15138             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
   15139                 pr.println("*** Data connection type #" + i + ":");
   15140                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
   15141             }
   15142             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
   15143             pr.println("*** Mobile network active timer:");
   15144             mMobileRadioActiveTimer.logState(pr, "  ");
   15145             pr.println("*** Mobile network active adjusted timer:");
   15146             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
   15147             pr.println("*** Wifi Multicast WakeLock Timer:");
   15148             mWifiMulticastWakelockTimer.logState(pr, "  ");
   15149             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
   15150             pr.println("*** Wifi timer:");
   15151             mWifiOnTimer.logState(pr, "  ");
   15152             pr.println("*** WifiRunning timer:");
   15153             mGlobalWifiRunningTimer.logState(pr, "  ");
   15154             for (int i=0; i<NUM_WIFI_STATES; i++) {
   15155                 pr.println("*** Wifi state #" + i + ":");
   15156                 mWifiStateTimer[i].logState(pr, "  ");
   15157             }
   15158             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
   15159                 pr.println("*** Wifi suppl state #" + i + ":");
   15160                 mWifiSupplStateTimer[i].logState(pr, "  ");
   15161             }
   15162             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
   15163                 pr.println("*** Wifi signal strength #" + i + ":");
   15164                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
   15165             }
   15166             for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
   15167                 pr.println("*** GPS signal quality #" + i + ":");
   15168                 mGpsSignalQualityTimer[i].logState(pr, "  ");
   15169             }
   15170             pr.println("*** Flashlight timer:");
   15171             mFlashlightOnTimer.logState(pr, "  ");
   15172             pr.println("*** Camera timer:");
   15173             mCameraOnTimer.logState(pr, "  ");
   15174         }
   15175         super.dumpLocked(context, pw, flags, reqUid, histStart);
   15176         pw.print("Total cpu time reads: ");
   15177         pw.println(mNumSingleUidCpuTimeReads);
   15178         pw.print("Batched cpu time reads: ");
   15179         pw.println(mNumBatchedSingleUidCpuTimeReads);
   15180         pw.print("Batching Duration (min): ");
   15181         pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTime) / (60 * 1000));
   15182         pw.print("All UID cpu time reads since the later of device start or stats reset: ");
   15183         pw.println(mNumAllUidCpuTimeReads);
   15184         pw.print("UIDs removed since the later of device start or stats reset: ");
   15185         pw.println(mNumUidsRemoved);
   15186     }
   15187 }
   15188