OSDN Git Service

Log deferred jobs metrics to batterystats
[android-x86/frameworks-base.git] / core / java / com / android / internal / os / BatteryStatsImpl.java
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.ContentResolver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.database.ContentObserver;
28 import android.net.ConnectivityManager;
29 import android.net.NetworkStats;
30 import android.net.Uri;
31 import android.net.wifi.WifiActivityEnergyInfo;
32 import android.net.wifi.WifiManager;
33 import android.os.BatteryManager;
34 import android.os.BatteryStats;
35 import android.os.Build;
36 import android.os.connectivity.CellularBatteryStats;
37 import android.os.connectivity.WifiBatteryStats;
38 import android.os.connectivity.GpsBatteryStats;
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.provider.Settings;
57 import android.telephony.DataConnectionRealTimeInfo;
58 import android.telephony.ModemActivityInfo;
59 import android.telephony.ServiceState;
60 import android.telephony.SignalStrength;
61 import android.telephony.TelephonyManager;
62 import android.text.TextUtils;
63 import android.util.ArrayMap;
64 import android.util.IntArray;
65 import android.util.KeyValueListParser;
66 import android.util.Log;
67 import android.util.LogWriter;
68 import android.util.LongSparseArray;
69 import android.util.LongSparseLongArray;
70 import android.util.MutableInt;
71 import android.util.Pools;
72 import android.util.PrintWriterPrinter;
73 import android.util.Printer;
74 import android.util.Slog;
75 import android.util.SparseArray;
76 import android.util.SparseIntArray;
77 import android.util.SparseLongArray;
78 import android.util.StatsLog;
79 import android.util.TimeUtils;
80 import android.util.Xml;
81 import android.view.Display;
82
83 import com.android.internal.annotations.GuardedBy;
84 import com.android.internal.annotations.VisibleForTesting;
85 import com.android.internal.location.gnssmetrics.GnssMetrics;
86 import com.android.internal.net.NetworkStatsFactory;
87 import com.android.internal.util.ArrayUtils;
88 import com.android.internal.util.FastPrintWriter;
89 import com.android.internal.util.FastXmlSerializer;
90 import com.android.internal.util.JournaledFile;
91 import com.android.internal.util.XmlUtils;
92
93 import java.util.List;
94 import libcore.util.EmptyArray;
95 import org.xmlpull.v1.XmlPullParser;
96 import org.xmlpull.v1.XmlPullParserException;
97 import org.xmlpull.v1.XmlSerializer;
98
99 import java.io.ByteArrayOutputStream;
100 import java.io.File;
101 import java.io.FileInputStream;
102 import java.io.FileNotFoundException;
103 import java.io.FileOutputStream;
104 import java.io.IOException;
105 import java.io.PrintWriter;
106 import java.nio.charset.StandardCharsets;
107 import java.util.ArrayList;
108 import java.util.Arrays;
109 import java.util.Calendar;
110 import java.util.HashMap;
111 import java.util.Iterator;
112 import java.util.Map;
113 import java.util.concurrent.Future;
114 import java.util.concurrent.atomic.AtomicInteger;
115 import java.util.concurrent.locks.ReentrantLock;
116
117 /**
118  * All information we are collecting about things that can happen that impact
119  * battery life.  All times are represented in microseconds except where indicated
120  * otherwise.
121  */
122 public class BatteryStatsImpl extends BatteryStats {
123     private static final String TAG = "BatteryStatsImpl";
124     private static final boolean DEBUG = false;
125     public static final boolean DEBUG_ENERGY = false;
126     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
127     private static final boolean DEBUG_MEMORY = false;
128     private static final boolean DEBUG_HISTORY = false;
129     private static final boolean USE_OLD_HISTORY = false;   // for debugging.
130
131     // TODO: remove "tcp" from network methods, since we measure total stats.
132
133     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
134     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
135
136     // Current on-disk Parcel version
137     private static final int VERSION = 175 + (USE_OLD_HISTORY ? 1000 : 0);
138
139     // Maximum number of items we will record in the history.
140     private static final int MAX_HISTORY_ITEMS;
141
142     // No, really, THIS is the maximum number of items we will record in the history.
143     private static final int MAX_MAX_HISTORY_ITEMS;
144
145     // The maximum number of names wakelocks we will keep track of
146     // per uid; once the limit is reached, we batch the remaining wakelocks
147     // in to one common name.
148     private static final int MAX_WAKELOCKS_PER_UID;
149
150     static final int MAX_HISTORY_BUFFER; // 256KB
151     static final int MAX_MAX_HISTORY_BUFFER; // 320KB
152
153     static {
154         if (ActivityManager.isLowRamDeviceStatic()) {
155             MAX_HISTORY_ITEMS = 800;
156             MAX_MAX_HISTORY_ITEMS = 1200;
157             MAX_WAKELOCKS_PER_UID = 40;
158             MAX_HISTORY_BUFFER = 96*1024;  // 96KB
159             MAX_MAX_HISTORY_BUFFER = 128*1024; // 128KB
160         } else {
161             MAX_HISTORY_ITEMS = 4000;
162             MAX_MAX_HISTORY_ITEMS = 6000;
163             MAX_WAKELOCKS_PER_UID = 200;
164             MAX_HISTORY_BUFFER = 512*1024;  // 512KB
165             MAX_MAX_HISTORY_BUFFER = 640*1024;  // 640KB
166         }
167     }
168
169     // Number of transmit power states the Wifi controller can be in.
170     private static final int NUM_WIFI_TX_LEVELS = 1;
171
172     // Number of transmit power states the Bluetooth controller can be in.
173     private static final int NUM_BT_TX_LEVELS = 1;
174
175     /**
176      * Holding a wakelock costs more than just using the cpu.
177      * Currently, we assign only half the cpu time to an app that is running but
178      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
179      * If no app is holding a wakelock, then the distribution is normal.
180      */
181     @VisibleForTesting
182     public static final int WAKE_LOCK_WEIGHT = 50;
183
184     protected Clocks mClocks;
185
186     private final JournaledFile mFile;
187     public final AtomicFile mCheckinFile;
188     public final AtomicFile mDailyFile;
189
190     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
191     static final int MSG_REPORT_POWER_CHANGE = 2;
192     static final int MSG_REPORT_CHARGING = 3;
193     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
194
195     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
196     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
197
198     @VisibleForTesting
199     protected KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
200     @VisibleForTesting
201     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
202     @VisibleForTesting
203     protected KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
204             new KernelUidCpuFreqTimeReader();
205     @VisibleForTesting
206     protected KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader =
207             new KernelUidCpuActiveTimeReader();
208     @VisibleForTesting
209     protected KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
210             new KernelUidCpuClusterTimeReader();
211     @VisibleForTesting
212     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
213
214     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
215             = new KernelMemoryBandwidthStats();
216     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
217     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
218         return mKernelMemoryStats;
219     }
220
221     @GuardedBy("this")
222     public boolean mPerProcStateCpuTimesAvailable = true;
223
224     /**
225      * Uids for which per-procstate cpu times need to be updated.
226      *
227      * Contains uid -> procState mappings.
228      */
229     @GuardedBy("this")
230     @VisibleForTesting
231     protected final SparseIntArray mPendingUids = new SparseIntArray();
232
233     @GuardedBy("this")
234     private long mNumCpuTimeReads;
235     @GuardedBy("this")
236     private long mNumBatchedCpuTimeReads;
237     @GuardedBy("this")
238     private long mCpuTimeReadsTrackingStartTime = SystemClock.uptimeMillis();
239
240     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
241     private final RpmStats mTmpRpmStats = new RpmStats();
242     /** The soonest the RPM stats can be updated after it was last updated. */
243     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
244     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
245     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
246
247     public interface BatteryCallback {
248         public void batteryNeedsCpuUpdate();
249         public void batteryPowerChanged(boolean onBattery);
250         public void batterySendBroadcast(Intent intent);
251     }
252
253     public interface PlatformIdleStateCallback {
254         public void fillLowPowerStats(RpmStats rpmStats);
255         public String getPlatformLowPowerStats();
256         public String getSubsystemLowPowerStats();
257     }
258
259     public static abstract class UserInfoProvider {
260         private int[] userIds;
261         protected abstract @Nullable int[] getUserIds();
262         @VisibleForTesting
263         public final void refreshUserIds() {
264             userIds = getUserIds();
265         }
266         @VisibleForTesting
267         public boolean exists(int userId) {
268             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
269         }
270     }
271
272     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
273
274     final class MyHandler extends Handler {
275         public MyHandler(Looper looper) {
276             super(looper, null, true);
277         }
278
279         @Override
280         public void handleMessage(Message msg) {
281             BatteryCallback cb = mCallback;
282             switch (msg.what) {
283                 case MSG_REPORT_CPU_UPDATE_NEEDED:
284                     if (cb != null) {
285                         cb.batteryNeedsCpuUpdate();
286                     }
287                     break;
288                 case MSG_REPORT_POWER_CHANGE:
289                     if (cb != null) {
290                         cb.batteryPowerChanged(msg.arg1 != 0);
291                     }
292                     break;
293                 case MSG_REPORT_CHARGING:
294                     if (cb != null) {
295                         final String action;
296                         synchronized (BatteryStatsImpl.this) {
297                             action = mCharging ? BatteryManager.ACTION_CHARGING
298                                     : BatteryManager.ACTION_DISCHARGING;
299                         }
300                         Intent intent = new Intent(action);
301                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
302                         cb.batterySendBroadcast(intent);
303                     }
304                     break;
305             }
306         }
307     }
308
309     public void postBatteryNeedsCpuUpdateMsg() {
310         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
311     }
312
313     /**
314      * Update per-freq cpu times for all the uids in {@link #mPendingUids}.
315      */
316     public void updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
317         final SparseIntArray uidStates;
318         synchronized (BatteryStatsImpl.this) {
319             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
320                 return;
321             }
322             if(!initKernelSingleUidTimeReaderLocked()) {
323                 return;
324             }
325             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
326             // compute deltas since it might result in mis-attributing cpu times to wrong states.
327             if (mKernelSingleUidTimeReader.hasStaleData()) {
328                 mPendingUids.clear();
329                 return;
330             }
331
332             if (mPendingUids.size() == 0) {
333                 return;
334             }
335             uidStates = mPendingUids.clone();
336             mPendingUids.clear();
337         }
338         for (int i = uidStates.size() - 1; i >= 0; --i) {
339             final int uid = uidStates.keyAt(i);
340             final int procState = uidStates.valueAt(i);
341             final int[] isolatedUids;
342             final Uid u;
343             synchronized (BatteryStatsImpl.this) {
344                 // It's possible that uid no longer exists and any internal references have
345                 // already been deleted, so using {@link #getAvailableUidStatsLocked} to avoid
346                 // creating an UidStats object if it doesn't already exist.
347                 u = getAvailableUidStatsLocked(uid);
348                 if (u == null) {
349                     continue;
350                 }
351                 if (u.mChildUids == null) {
352                     isolatedUids = null;
353                 } else {
354                     isolatedUids = u.mChildUids.toArray();
355                     for (int j = isolatedUids.length - 1; j >= 0; --j) {
356                         isolatedUids[j] = u.mChildUids.get(j);
357                     }
358                 }
359             }
360             long[] cpuTimesMs = mKernelSingleUidTimeReader.readDeltaMs(uid);
361             if (isolatedUids != null) {
362                 for (int j = isolatedUids.length - 1; j >= 0; --j) {
363                     cpuTimesMs = addCpuTimes(cpuTimesMs,
364                             mKernelSingleUidTimeReader.readDeltaMs(isolatedUids[j]));
365                 }
366             }
367             if (onBattery && cpuTimesMs != null) {
368                 synchronized (BatteryStatsImpl.this) {
369                     u.addProcStateTimesMs(procState, cpuTimesMs, onBattery);
370                     u.addProcStateScreenOffTimesMs(procState, cpuTimesMs, onBatteryScreenOff);
371                 }
372             }
373         }
374     }
375
376     public void copyFromAllUidsCpuTimes() {
377         synchronized (BatteryStatsImpl.this) {
378             copyFromAllUidsCpuTimes(
379                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
380         }
381     }
382
383     /**
384      * When the battery/screen state changes, we don't attribute the cpu times to any process
385      * but we still need to snapshots of all uids to get correct deltas later on. Since we
386      * already read this data for updating per-freq cpu times, we can use the same data for
387      * per-procstate cpu times.
388      */
389     public void copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
390         synchronized (BatteryStatsImpl.this) {
391             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
392                 return;
393             }
394             if(!initKernelSingleUidTimeReaderLocked()) {
395                 return;
396             }
397
398             final SparseArray<long[]> allUidCpuFreqTimesMs =
399                     mKernelUidCpuFreqTimeReader.getAllUidCpuFreqTimeMs();
400             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
401             // compute deltas since it might result in mis-attributing cpu times to wrong states.
402             if (mKernelSingleUidTimeReader.hasStaleData()) {
403                 mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
404                 mKernelSingleUidTimeReader.markDataAsStale(false);
405                 mPendingUids.clear();
406                 return;
407             }
408             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
409                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
410                 final Uid u = getAvailableUidStatsLocked(mapUid(uid));
411                 if (u == null) {
412                     continue;
413                 }
414                 final long[] cpuTimesMs = allUidCpuFreqTimesMs.valueAt(i);
415                 if (cpuTimesMs == null) {
416                     continue;
417                 }
418                 final long[] deltaTimesMs = mKernelSingleUidTimeReader.computeDelta(
419                         uid, cpuTimesMs.clone());
420                 if (onBattery && deltaTimesMs != null) {
421                     final int procState;
422                     final int idx = mPendingUids.indexOfKey(uid);
423                     if (idx >= 0) {
424                         procState = mPendingUids.valueAt(idx);
425                         mPendingUids.removeAt(idx);
426                     } else {
427                         procState = u.mProcessState;
428                     }
429                     if (procState >= 0 && procState < Uid.NUM_PROCESS_STATE) {
430                         u.addProcStateTimesMs(procState, deltaTimesMs, onBattery);
431                         u.addProcStateScreenOffTimesMs(procState, deltaTimesMs, onBatteryScreenOff);
432                     }
433                 }
434             }
435         }
436     }
437
438     @VisibleForTesting
439     public long[] addCpuTimes(long[] timesA, long[] timesB) {
440         if (timesA != null && timesB != null) {
441             for (int i = timesA.length - 1; i >= 0; --i) {
442                 timesA[i] += timesB[i];
443             }
444             return timesA;
445         }
446         return timesA == null ? (timesB == null ? null : timesB) : timesA;
447     }
448
449     @GuardedBy("this")
450     private boolean initKernelSingleUidTimeReaderLocked() {
451         if (mKernelSingleUidTimeReader == null) {
452             if (mPowerProfile == null) {
453                 return false;
454             }
455             if (mCpuFreqs == null) {
456                 mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
457             }
458             if (mCpuFreqs != null) {
459                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
460             } else {
461                 mPerProcStateCpuTimesAvailable = mKernelUidCpuFreqTimeReader.allUidTimesAvailable();
462                 return false;
463             }
464         }
465         mPerProcStateCpuTimesAvailable = mKernelUidCpuFreqTimeReader.allUidTimesAvailable()
466                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
467         return true;
468     }
469
470     public interface Clocks {
471         public long elapsedRealtime();
472         public long uptimeMillis();
473     }
474
475     public static class SystemClocks implements Clocks {
476         public long elapsedRealtime() {
477             return SystemClock.elapsedRealtime();
478         }
479
480         public long uptimeMillis() {
481             return SystemClock.uptimeMillis();
482         }
483     }
484
485     public interface ExternalStatsSync {
486         int UPDATE_CPU = 0x01;
487         int UPDATE_WIFI = 0x02;
488         int UPDATE_RADIO = 0x04;
489         int UPDATE_BT = 0x08;
490         int UPDATE_RPM = 0x10; // 16
491         int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM;
492
493         Future<?> scheduleSync(String reason, int flags);
494         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
495         Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff,
496                 long delayMillis);
497         Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
498         Future<?> scheduleCpuSyncDueToSettingChange();
499         Future<?> scheduleCpuSyncDueToScreenStateChange(boolean onBattery,
500                 boolean onBatteryScreenOff);
501         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
502         void cancelCpuSyncDueToWakelockChange();
503     }
504
505     public Handler mHandler;
506     private ExternalStatsSync mExternalSync = null;
507     @VisibleForTesting
508     protected UserInfoProvider mUserInfoProvider = null;
509
510     private BatteryCallback mCallback;
511
512     /**
513      * Mapping isolated uids to the actual owning app uid.
514      */
515     final SparseIntArray mIsolatedUids = new SparseIntArray();
516
517     /**
518      * The statistics we have collected organized by uids.
519      */
520     final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
521
522     // A set of pools of currently active timers.  When a timer is queried, we will divide the
523     // elapsed time by the number of active timers to arrive at that timer's share of the time.
524     // In order to do this, we must refresh each timer whenever the number of active timers
525     // changes.
526     @VisibleForTesting
527     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
528     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
529     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
530     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
531     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
532     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
533     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
534     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
535     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
536     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
537     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
538     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
539     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
540     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
541     final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
542
543     // Last partial timers we use for distributing CPU usage.
544     @VisibleForTesting
545     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
546
547     // These are the objects that will want to do something when the device
548     // is unplugged from power.
549     protected final TimeBase mOnBatteryTimeBase = new TimeBase();
550
551     // These are the objects that will want to do something when the device
552     // is unplugged from power *and* the screen is off or doze.
553     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase();
554
555     // Set to true when we want to distribute CPU across wakelocks for the next
556     // CPU update, even if we aren't currently running wake locks.
557     boolean mDistributeWakelockCpu;
558
559     boolean mShuttingDown;
560
561     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
562
563     long mHistoryBaseTime;
564     protected boolean mHaveBatteryLevel = false;
565     protected boolean mRecordingHistory = false;
566     int mNumHistoryItems;
567
568     final Parcel mHistoryBuffer = Parcel.obtain();
569     final HistoryItem mHistoryLastWritten = new HistoryItem();
570     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
571     final HistoryItem mHistoryReadTmp = new HistoryItem();
572     final HistoryItem mHistoryAddTmp = new HistoryItem();
573     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
574     String[] mReadHistoryStrings;
575     int[] mReadHistoryUids;
576     int mReadHistoryChars;
577     int mNextHistoryTagIdx = 0;
578     int mNumHistoryTagChars = 0;
579     int mHistoryBufferLastPos = -1;
580     boolean mHistoryOverflow = false;
581     int mActiveHistoryStates = 0xffffffff;
582     int mActiveHistoryStates2 = 0xffffffff;
583     long mLastHistoryElapsedRealtime = 0;
584     long mTrackRunningHistoryElapsedRealtime = 0;
585     long mTrackRunningHistoryUptime = 0;
586
587     final HistoryItem mHistoryCur = new HistoryItem();
588
589     HistoryItem mHistory;
590     HistoryItem mHistoryEnd;
591     HistoryItem mHistoryLastEnd;
592     HistoryItem mHistoryCache;
593
594     // Used by computeHistoryStepDetails
595     HistoryStepDetails mLastHistoryStepDetails = null;
596     byte mLastHistoryStepLevel = 0;
597     final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
598     final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
599     final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
600
601     /**
602      * Total time (in milliseconds) spent executing in user code.
603      */
604     long mLastStepCpuUserTime;
605     long mCurStepCpuUserTime;
606     /**
607      * Total time (in milliseconds) spent executing in kernel code.
608      */
609     long mLastStepCpuSystemTime;
610     long mCurStepCpuSystemTime;
611     /**
612      * Times from /proc/stat (but measured in milliseconds).
613      */
614     long mLastStepStatUserTime;
615     long mLastStepStatSystemTime;
616     long mLastStepStatIOWaitTime;
617     long mLastStepStatIrqTime;
618     long mLastStepStatSoftIrqTime;
619     long mLastStepStatIdleTime;
620     long mCurStepStatUserTime;
621     long mCurStepStatSystemTime;
622     long mCurStepStatIOWaitTime;
623     long mCurStepStatIrqTime;
624     long mCurStepStatSoftIrqTime;
625     long mCurStepStatIdleTime;
626
627     private HistoryItem mHistoryIterator;
628     private boolean mReadOverflow;
629     private boolean mIteratingHistory;
630
631     int mStartCount;
632
633     long mStartClockTime;
634     String mStartPlatformVersion;
635     String mEndPlatformVersion;
636
637     long mUptime;
638     long mUptimeStart;
639     long mRealtime;
640     long mRealtimeStart;
641
642     int mWakeLockNesting;
643     boolean mWakeLockImportant;
644     public boolean mRecordAllHistory;
645     boolean mNoAutoReset;
646
647     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
648     protected int mScreenState = Display.STATE_UNKNOWN;
649     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
650     protected StopwatchTimer mScreenOnTimer;
651     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
652     protected StopwatchTimer mScreenDozeTimer;
653
654     int mScreenBrightnessBin = -1;
655     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
656
657     boolean mPretendScreenOff;
658
659     boolean mInteractive;
660     StopwatchTimer mInteractiveTimer;
661
662     boolean mPowerSaveModeEnabled;
663     StopwatchTimer mPowerSaveModeEnabledTimer;
664
665     boolean mDeviceIdling;
666     StopwatchTimer mDeviceIdlingTimer;
667
668     boolean mDeviceLightIdling;
669     StopwatchTimer mDeviceLightIdlingTimer;
670
671     int mDeviceIdleMode;
672     long mLastIdleTimeStart;
673     long mLongestLightIdleTime;
674     long mLongestFullIdleTime;
675     StopwatchTimer mDeviceIdleModeLightTimer;
676     StopwatchTimer mDeviceIdleModeFullTimer;
677
678     boolean mPhoneOn;
679     StopwatchTimer mPhoneOnTimer;
680
681     int mAudioOnNesting;
682     StopwatchTimer mAudioOnTimer;
683
684     int mVideoOnNesting;
685     StopwatchTimer mVideoOnTimer;
686
687     int mFlashlightOnNesting;
688     StopwatchTimer mFlashlightOnTimer;
689
690     int mCameraOnNesting;
691     StopwatchTimer mCameraOnTimer;
692
693     int mGpsSignalQualityBin = -1;
694     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
695     protected final StopwatchTimer[] mGpsSignalQualityTimer =
696         new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
697
698     int mPhoneSignalStrengthBin = -1;
699     int mPhoneSignalStrengthBinRaw = -1;
700     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
701             new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
702
703     StopwatchTimer mPhoneSignalScanningTimer;
704
705     int mPhoneDataConnectionType = -1;
706     final StopwatchTimer[] mPhoneDataConnectionsTimer =
707             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
708
709     final LongSamplingCounter[] mNetworkByteActivityCounters =
710             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
711     final LongSamplingCounter[] mNetworkPacketActivityCounters =
712             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
713
714     /**
715      * The WiFi Overall wakelock timer
716      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
717      * since addition of per UID timers would not result in an accurate value due to overlapp of
718      * per uid wakelock timers
719      */
720     StopwatchTimer mWifiMulticastWakelockTimer;
721
722     /**
723      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
724      */
725     ControllerActivityCounterImpl mWifiActivity;
726
727     /**
728      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
729      */
730     ControllerActivityCounterImpl mBluetoothActivity;
731
732     /**
733      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
734      */
735     ControllerActivityCounterImpl mModemActivity;
736
737     /**
738      * Whether the device supports WiFi controller energy reporting. This is set to true on
739      * the first WiFi energy report. See {@link #mWifiActivity}.
740      */
741     boolean mHasWifiReporting = false;
742
743     /**
744      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
745      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
746      */
747     boolean mHasBluetoothReporting = false;
748
749     /**
750      * Whether the device supports Modem controller energy reporting. This is set to true on
751      * the first Modem energy report. See {@link #mModemActivity}.
752      */
753     boolean mHasModemReporting = false;
754
755     boolean mWifiOn;
756     StopwatchTimer mWifiOnTimer;
757
758     boolean mGlobalWifiRunning;
759     StopwatchTimer mGlobalWifiRunningTimer;
760
761     int mWifiState = -1;
762     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
763
764     int mWifiSupplState = -1;
765     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
766
767     int mWifiSignalStrengthBin = -1;
768     final StopwatchTimer[] mWifiSignalStrengthsTimer =
769             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
770
771     StopwatchTimer mWifiActiveTimer;
772
773     int mBluetoothScanNesting;
774     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
775     protected StopwatchTimer mBluetoothScanTimer;
776
777     boolean mIsCellularTxPowerHigh = false;
778
779     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
780     long mMobileRadioActiveStartTime;
781     StopwatchTimer mMobileRadioActiveTimer;
782     StopwatchTimer mMobileRadioActivePerAppTimer;
783     LongSamplingCounter mMobileRadioActiveAdjustedTime;
784     LongSamplingCounter mMobileRadioActiveUnknownTime;
785     LongSamplingCounter mMobileRadioActiveUnknownCount;
786
787     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
788
789     /**
790      * These provide time bases that discount the time the device is plugged
791      * in to power.
792      */
793     boolean mOnBattery;
794     @VisibleForTesting
795     protected boolean mOnBatteryInternal;
796
797     /**
798      * External reporting of whether the device is actually charging.
799      */
800     boolean mCharging = true;
801     int mLastChargingStateLevel;
802
803     /*
804      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
805      */
806     int mDischargeStartLevel;
807     int mDischargeUnplugLevel;
808     int mDischargePlugLevel;
809     int mDischargeCurrentLevel;
810     int mCurrentBatteryLevel;
811     int mLowDischargeAmountSinceCharge;
812     int mHighDischargeAmountSinceCharge;
813     int mDischargeScreenOnUnplugLevel;
814     int mDischargeScreenOffUnplugLevel;
815     int mDischargeScreenDozeUnplugLevel;
816     int mDischargeAmountScreenOn;
817     int mDischargeAmountScreenOnSinceCharge;
818     int mDischargeAmountScreenOff;
819     int mDischargeAmountScreenOffSinceCharge;
820     int mDischargeAmountScreenDoze;
821     int mDischargeAmountScreenDozeSinceCharge;
822
823     private LongSamplingCounter mDischargeScreenOffCounter;
824     private LongSamplingCounter mDischargeScreenDozeCounter;
825     private LongSamplingCounter mDischargeCounter;
826     private LongSamplingCounter mDischargeLightDozeCounter;
827     private LongSamplingCounter mDischargeDeepDozeCounter;
828
829     static final int MAX_LEVEL_STEPS = 200;
830
831     int mInitStepMode = 0;
832     int mCurStepMode = 0;
833     int mModStepMode = 0;
834
835     int mLastDischargeStepLevel;
836     int mMinDischargeStepLevel;
837     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
838     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
839     ArrayList<PackageChange> mDailyPackageChanges;
840
841     int mLastChargeStepLevel;
842     int mMaxChargeStepLevel;
843     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
844     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
845
846     static final int MAX_DAILY_ITEMS = 10;
847
848     long mDailyStartTime = 0;
849     long mNextMinDailyDeadline = 0;
850     long mNextMaxDailyDeadline = 0;
851
852     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
853
854     long mLastWriteTime = 0; // Milliseconds
855
856     private int mPhoneServiceState = -1;
857     private int mPhoneServiceStateRaw = -1;
858     private int mPhoneSimStateRaw = -1;
859
860     private int mNumConnectivityChange;
861     private int mLoadedNumConnectivityChange;
862     private int mUnpluggedNumConnectivityChange;
863
864     private int mEstimatedBatteryCapacity = -1;
865
866     private int mMinLearnedBatteryCapacity = -1;
867     private int mMaxLearnedBatteryCapacity = -1;
868
869     private long[] mCpuFreqs;
870
871     @VisibleForTesting
872     protected PowerProfile mPowerProfile;
873
874     @GuardedBy("this")
875     private final Constants mConstants;
876
877     /*
878      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
879      * recording their times when on-battery (regardless of screen state).
880      */
881     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
882     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
883     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
884
885     @Override
886     public Map<String, ? extends Timer> getRpmStats() {
887         return mRpmStats;
888     }
889
890     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
891     @Override
892     public Map<String, ? extends Timer> getScreenOffRpmStats() {
893         return mScreenOffRpmStats;
894     }
895
896     /*
897      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
898      */
899     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
900
901     public Map<String, ? extends Timer> getKernelWakelockStats() {
902         return mKernelWakelockStats;
903     }
904
905     String mLastWakeupReason = null;
906     long mLastWakeupUptimeMs = 0;
907     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
908
909     public Map<String, ? extends Timer> getWakeupReasonStats() {
910         return mWakeupReasonStats;
911     }
912
913     @Override
914     public long getUahDischarge(int which) {
915         return mDischargeCounter.getCountLocked(which);
916     }
917
918     @Override
919     public long getUahDischargeScreenOff(int which) {
920         return mDischargeScreenOffCounter.getCountLocked(which);
921     }
922
923     @Override
924     public long getUahDischargeScreenDoze(int which) {
925         return mDischargeScreenDozeCounter.getCountLocked(which);
926     }
927
928     @Override
929     public long getUahDischargeLightDoze(int which) {
930         return mDischargeLightDozeCounter.getCountLocked(which);
931     }
932
933     @Override
934     public long getUahDischargeDeepDoze(int which) {
935         return mDischargeDeepDozeCounter.getCountLocked(which);
936     }
937
938     @Override
939     public int getEstimatedBatteryCapacity() {
940         return mEstimatedBatteryCapacity;
941     }
942
943     @Override
944     public int getMinLearnedBatteryCapacity() {
945         return mMinLearnedBatteryCapacity;
946     }
947
948     @Override
949     public int getMaxLearnedBatteryCapacity() {
950         return mMaxLearnedBatteryCapacity;
951     }
952
953     public BatteryStatsImpl() {
954         this(new SystemClocks());
955     }
956
957     public BatteryStatsImpl(Clocks clocks) {
958         init(clocks);
959         mFile = null;
960         mCheckinFile = null;
961         mDailyFile = null;
962         mHandler = null;
963         mPlatformIdleStateCallback = null;
964         mUserInfoProvider = null;
965         mConstants = new Constants(mHandler);
966         clearHistoryLocked();
967     }
968
969     private void init(Clocks clocks) {
970         mClocks = clocks;
971     }
972
973     public interface TimeBaseObs {
974         void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
975         void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
976     }
977
978     // methods are protected not private to be VisibleForTesting
979     public static class TimeBase {
980         protected final ArrayList<TimeBaseObs> mObservers = new ArrayList<>();
981
982         protected long mUptime;
983         protected long mRealtime;
984
985         protected boolean mRunning;
986
987         protected long mPastUptime;
988         protected long mUptimeStart;
989         protected long mPastRealtime;
990         protected long mRealtimeStart;
991         protected long mUnpluggedUptime;
992         protected long mUnpluggedRealtime;
993
994         public void dump(PrintWriter pw, String prefix) {
995             StringBuilder sb = new StringBuilder(128);
996             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
997             sb.setLength(0);
998             sb.append(prefix);
999                     sb.append("mUptime=");
1000                     formatTimeMs(sb, mUptime / 1000);
1001             pw.println(sb.toString());
1002             sb.setLength(0);
1003             sb.append(prefix);
1004                     sb.append("mRealtime=");
1005                     formatTimeMs(sb, mRealtime / 1000);
1006             pw.println(sb.toString());
1007             sb.setLength(0);
1008             sb.append(prefix);
1009                     sb.append("mPastUptime=");
1010                     formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
1011                     formatTimeMs(sb, mUptimeStart / 1000);
1012                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
1013             pw.println(sb.toString());
1014             sb.setLength(0);
1015             sb.append(prefix);
1016                     sb.append("mPastRealtime=");
1017                     formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
1018                     formatTimeMs(sb, mRealtimeStart / 1000);
1019                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
1020             pw.println(sb.toString());
1021         }
1022
1023         public void add(TimeBaseObs observer) {
1024             mObservers.add(observer);
1025         }
1026
1027         public void remove(TimeBaseObs observer) {
1028             if (!mObservers.remove(observer)) {
1029                 Slog.wtf(TAG, "Removed unknown observer: " + observer);
1030             }
1031         }
1032
1033         public boolean hasObserver(TimeBaseObs observer) {
1034             return mObservers.contains(observer);
1035         }
1036
1037         public void init(long uptime, long realtime) {
1038             mRealtime = 0;
1039             mUptime = 0;
1040             mPastUptime = 0;
1041             mPastRealtime = 0;
1042             mUptimeStart = uptime;
1043             mRealtimeStart = realtime;
1044             mUnpluggedUptime = getUptime(mUptimeStart);
1045             mUnpluggedRealtime = getRealtime(mRealtimeStart);
1046         }
1047
1048         public void reset(long uptime, long realtime) {
1049             if (!mRunning) {
1050                 mPastUptime = 0;
1051                 mPastRealtime = 0;
1052             } else {
1053                 mUptimeStart = uptime;
1054                 mRealtimeStart = realtime;
1055                 // TODO: Since mUptimeStart was just reset and we are running, getUptime will
1056                 // just return mPastUptime. Also, are we sure we don't want to reset that?
1057                 mUnpluggedUptime = getUptime(uptime);
1058                 // TODO: likewise.
1059                 mUnpluggedRealtime = getRealtime(realtime);
1060             }
1061         }
1062
1063         public long computeUptime(long curTime, int which) {
1064             switch (which) {
1065                 case STATS_SINCE_CHARGED:
1066                     return mUptime + getUptime(curTime);
1067                 case STATS_CURRENT:
1068                     return getUptime(curTime);
1069                 case STATS_SINCE_UNPLUGGED:
1070                     return getUptime(curTime) - mUnpluggedUptime;
1071             }
1072             return 0;
1073         }
1074
1075         public long computeRealtime(long curTime, int which) {
1076             switch (which) {
1077                 case STATS_SINCE_CHARGED:
1078                     return mRealtime + getRealtime(curTime);
1079                 case STATS_CURRENT:
1080                     return getRealtime(curTime);
1081                 case STATS_SINCE_UNPLUGGED:
1082                     return getRealtime(curTime) - mUnpluggedRealtime;
1083             }
1084             return 0;
1085         }
1086
1087         public long getUptime(long curTime) {
1088             long time = mPastUptime;
1089             if (mRunning) {
1090                 time += curTime - mUptimeStart;
1091             }
1092             return time;
1093         }
1094
1095         public long getRealtime(long curTime) {
1096             long time = mPastRealtime;
1097             if (mRunning) {
1098                 time += curTime - mRealtimeStart;
1099             }
1100             return time;
1101         }
1102
1103         public long getUptimeStart() {
1104             return mUptimeStart;
1105         }
1106
1107         public long getRealtimeStart() {
1108             return mRealtimeStart;
1109         }
1110
1111         public boolean isRunning() {
1112             return mRunning;
1113         }
1114
1115         public boolean setRunning(boolean running, long uptime, long realtime) {
1116             if (mRunning != running) {
1117                 mRunning = running;
1118                 if (running) {
1119                     mUptimeStart = uptime;
1120                     mRealtimeStart = realtime;
1121                     long batteryUptime = mUnpluggedUptime = getUptime(uptime);
1122                     long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
1123
1124                     for (int i = mObservers.size() - 1; i >= 0; i--) {
1125                         mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime);
1126                     }
1127                 } else {
1128                     mPastUptime += uptime - mUptimeStart;
1129                     mPastRealtime += realtime - mRealtimeStart;
1130
1131                     long batteryUptime = getUptime(uptime);
1132                     long batteryRealtime = getRealtime(realtime);
1133
1134                     for (int i = mObservers.size() - 1; i >= 0; i--) {
1135                         mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime);
1136                     }
1137                 }
1138                 return true;
1139             }
1140             return false;
1141         }
1142
1143         public void readSummaryFromParcel(Parcel in) {
1144             mUptime = in.readLong();
1145             mRealtime = in.readLong();
1146         }
1147
1148         public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
1149             out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
1150             out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
1151         }
1152
1153         public void readFromParcel(Parcel in) {
1154             mRunning = false;
1155             mUptime = in.readLong();
1156             mPastUptime = in.readLong();
1157             mUptimeStart = in.readLong();
1158             mRealtime = in.readLong();
1159             mPastRealtime = in.readLong();
1160             mRealtimeStart = in.readLong();
1161             mUnpluggedUptime = in.readLong();
1162             mUnpluggedRealtime = in.readLong();
1163         }
1164
1165         public void writeToParcel(Parcel out, long uptime, long realtime) {
1166             final long runningUptime = getUptime(uptime);
1167             final long runningRealtime = getRealtime(realtime);
1168             out.writeLong(mUptime);
1169             out.writeLong(runningUptime);
1170             out.writeLong(mUptimeStart);
1171             out.writeLong(mRealtime);
1172             out.writeLong(runningRealtime);
1173             out.writeLong(mRealtimeStart);
1174             out.writeLong(mUnpluggedUptime);
1175             out.writeLong(mUnpluggedRealtime);
1176         }
1177     }
1178
1179     /**
1180      * State for keeping track of counting information.
1181      */
1182     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
1183         final AtomicInteger mCount = new AtomicInteger();
1184         final TimeBase mTimeBase;
1185         int mLoadedCount;
1186         int mUnpluggedCount;
1187         int mPluggedCount;
1188
1189         public Counter(TimeBase timeBase, Parcel in) {
1190             mTimeBase = timeBase;
1191             mPluggedCount = in.readInt();
1192             mCount.set(mPluggedCount);
1193             mLoadedCount = in.readInt();
1194             mUnpluggedCount = in.readInt();
1195             timeBase.add(this);
1196         }
1197
1198         public Counter(TimeBase timeBase) {
1199             mTimeBase = timeBase;
1200             timeBase.add(this);
1201         }
1202
1203         public void writeToParcel(Parcel out) {
1204             out.writeInt(mCount.get());
1205             out.writeInt(mLoadedCount);
1206             out.writeInt(mUnpluggedCount);
1207         }
1208
1209         @Override
1210         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1211             mUnpluggedCount = mPluggedCount;
1212         }
1213
1214         @Override
1215         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1216             mPluggedCount = mCount.get();
1217         }
1218
1219         /**
1220          * Writes a possibly null Counter to a Parcel.
1221          *
1222          * @param out the Parcel to be written to.
1223          * @param counter a Counter, or null.
1224          */
1225         public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
1226             if (counter == null) {
1227                 out.writeInt(0); // indicates null
1228                 return;
1229             }
1230             out.writeInt(1); // indicates non-null
1231
1232             counter.writeToParcel(out);
1233         }
1234
1235         /**
1236          * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
1237          * @param timeBase the timebase to assign to the Counter
1238          * @param in the parcel to read from
1239          * @return the Counter or null.
1240          */
1241         public static @Nullable Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
1242             if (in.readInt() == 0) {
1243                 return null;
1244             }
1245             return new Counter(timeBase, in);
1246         }
1247
1248         @Override
1249         public int getCountLocked(int which) {
1250             int val = mCount.get();
1251             if (which == STATS_SINCE_UNPLUGGED) {
1252                 val -= mUnpluggedCount;
1253             } else if (which != STATS_SINCE_CHARGED) {
1254                 val -= mLoadedCount;
1255             }
1256
1257             return val;
1258         }
1259
1260         public void logState(Printer pw, String prefix) {
1261             pw.println(prefix + "mCount=" + mCount.get()
1262                     + " mLoadedCount=" + mLoadedCount
1263                     + " mUnpluggedCount=" + mUnpluggedCount
1264                     + " mPluggedCount=" + mPluggedCount);
1265         }
1266
1267         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
1268         public void stepAtomic() {
1269             if (mTimeBase.isRunning()) {
1270                 mCount.incrementAndGet();
1271             }
1272         }
1273
1274         void addAtomic(int delta) {
1275             if (mTimeBase.isRunning()) {
1276                 mCount.addAndGet(delta);
1277             }
1278         }
1279
1280         /**
1281          * Clear state of this counter.
1282          */
1283         void reset(boolean detachIfReset) {
1284             mCount.set(0);
1285             mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
1286             if (detachIfReset) {
1287                 detach();
1288             }
1289         }
1290
1291         void detach() {
1292             mTimeBase.remove(this);
1293         }
1294
1295         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
1296         public void writeSummaryFromParcelLocked(Parcel out) {
1297             int count = mCount.get();
1298             out.writeInt(count);
1299         }
1300
1301         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
1302         public void readSummaryFromParcelLocked(Parcel in) {
1303             mLoadedCount = in.readInt();
1304             mCount.set(mLoadedCount);
1305             mUnpluggedCount = mPluggedCount = mLoadedCount;
1306         }
1307     }
1308
1309     @VisibleForTesting
1310     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
1311         final TimeBase mTimeBase;
1312         public long[] mCounts;
1313         public long[] mLoadedCounts;
1314         public long[] mUnpluggedCounts;
1315
1316         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
1317             mTimeBase = timeBase;
1318             mCounts = in.createLongArray();
1319             mLoadedCounts = in.createLongArray();
1320             mUnpluggedCounts = in.createLongArray();
1321             timeBase.add(this);
1322         }
1323
1324         public LongSamplingCounterArray(TimeBase timeBase) {
1325             mTimeBase = timeBase;
1326             timeBase.add(this);
1327         }
1328
1329         private void writeToParcel(Parcel out) {
1330             out.writeLongArray(mCounts);
1331             out.writeLongArray(mLoadedCounts);
1332             out.writeLongArray(mUnpluggedCounts);
1333         }
1334
1335         @Override
1336         public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
1337             mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
1338         }
1339
1340         @Override
1341         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1342         }
1343
1344         @Override
1345         public long[] getCountsLocked(int which) {
1346             long[] val = copyArray(mCounts, null);
1347             if (which == STATS_SINCE_UNPLUGGED) {
1348                 subtract(val, mUnpluggedCounts);
1349             } else if (which != STATS_SINCE_CHARGED) {
1350                 subtract(val, mLoadedCounts);
1351             }
1352             return val;
1353         }
1354
1355         @Override
1356         public void logState(Printer pw, String prefix) {
1357             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts)
1358                     + " mLoadedCounts=" + Arrays.toString(mLoadedCounts)
1359                     + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts));
1360         }
1361
1362         public void addCountLocked(long[] counts) {
1363             addCountLocked(counts, mTimeBase.isRunning());
1364         }
1365
1366         public void addCountLocked(long[] counts, boolean isRunning) {
1367             if (counts == null) {
1368                 return;
1369             }
1370             if (isRunning) {
1371                 if (mCounts == null) {
1372                     mCounts = new long[counts.length];
1373                 }
1374                 for (int i = 0; i < counts.length; ++i) {
1375                     mCounts[i] += counts[i];
1376                 }
1377             }
1378         }
1379
1380         public int getSize() {
1381             return mCounts == null ? 0 : mCounts.length;
1382         }
1383
1384         /**
1385          * Clear state of this counter.
1386          */
1387         public void reset(boolean detachIfReset) {
1388             fillArray(mCounts, 0);
1389             fillArray(mLoadedCounts, 0);
1390             fillArray(mUnpluggedCounts, 0);
1391             if (detachIfReset) {
1392                 detach();
1393             }
1394         }
1395
1396         public void detach() {
1397             mTimeBase.remove(this);
1398         }
1399
1400         private void writeSummaryToParcelLocked(Parcel out) {
1401             out.writeLongArray(mCounts);
1402         }
1403
1404         private void readSummaryFromParcelLocked(Parcel in) {
1405             mCounts = in.createLongArray();
1406             mLoadedCounts = copyArray(mCounts, mLoadedCounts);
1407             mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
1408         }
1409
1410         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
1411             if (counterArray != null) {
1412                 out.writeInt(1);
1413                 counterArray.writeToParcel(out);
1414             } else {
1415                 out.writeInt(0);
1416             }
1417         }
1418
1419         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
1420             if (in.readInt() != 0) {
1421                 return new LongSamplingCounterArray(timeBase, in);
1422             } else {
1423                 return null;
1424             }
1425         }
1426
1427         public static void writeSummaryToParcelLocked(Parcel out,
1428                 LongSamplingCounterArray counterArray) {
1429             if (counterArray != null) {
1430                 out.writeInt(1);
1431                 counterArray.writeSummaryToParcelLocked(out);
1432             } else {
1433                 out.writeInt(0);
1434             }
1435         }
1436
1437         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
1438                 TimeBase timeBase) {
1439             if (in.readInt() != 0) {
1440                 final LongSamplingCounterArray counterArray
1441                         = new LongSamplingCounterArray(timeBase);
1442                 counterArray.readSummaryFromParcelLocked(in);
1443                 return counterArray;
1444             } else {
1445                 return null;
1446             }
1447         }
1448
1449         private static void fillArray(long[] a, long val) {
1450             if (a != null) {
1451                 Arrays.fill(a, val);
1452             }
1453         }
1454
1455         private static void subtract(@NonNull long[] val, long[] toSubtract) {
1456             if (toSubtract == null) {
1457                 return;
1458             }
1459             for (int i = 0; i < val.length; i++) {
1460                 val[i] -= toSubtract[i];
1461             }
1462         }
1463
1464         private static long[] copyArray(long[] src, long[] dest) {
1465             if (src == null) {
1466                 return null;
1467             } else {
1468                 if (dest == null) {
1469                     dest = new long[src.length];
1470                 }
1471                 System.arraycopy(src, 0, dest, 0, src.length);
1472                 return dest;
1473             }
1474         }
1475     }
1476
1477     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
1478         final TimeBase mTimeBase;
1479         long mCount;
1480         long mLoadedCount;
1481         long mUnpluggedCount;
1482
1483         LongSamplingCounter(TimeBase timeBase, Parcel in) {
1484             mTimeBase = timeBase;
1485             mCount = in.readLong();
1486             mLoadedCount = in.readLong();
1487             mUnpluggedCount = in.readLong();
1488             timeBase.add(this);
1489         }
1490
1491         LongSamplingCounter(TimeBase timeBase) {
1492             mTimeBase = timeBase;
1493             timeBase.add(this);
1494         }
1495
1496         public void writeToParcel(Parcel out) {
1497             out.writeLong(mCount);
1498             out.writeLong(mLoadedCount);
1499             out.writeLong(mUnpluggedCount);
1500         }
1501
1502         @Override
1503         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1504             mUnpluggedCount = mCount;
1505         }
1506
1507         @Override
1508         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1509         }
1510
1511         public long getCountLocked(int which) {
1512             long val = mCount;
1513             if (which == STATS_SINCE_UNPLUGGED) {
1514                 val -= mUnpluggedCount;
1515             } else if (which != STATS_SINCE_CHARGED) {
1516                 val -= mLoadedCount;
1517             }
1518             return val;
1519         }
1520
1521         @Override
1522         public void logState(Printer pw, String prefix) {
1523             pw.println(prefix + "mCount=" + mCount
1524                     + " mLoadedCount=" + mLoadedCount
1525                     + " mUnpluggedCount=" + mUnpluggedCount);
1526         }
1527
1528         void addCountLocked(long count) {
1529             addCountLocked(count, mTimeBase.isRunning());
1530         }
1531
1532         void addCountLocked(long count, boolean isRunning) {
1533             if (isRunning) {
1534                 mCount += count;
1535             }
1536         }
1537
1538         /**
1539          * Clear state of this counter.
1540          */
1541         void reset(boolean detachIfReset) {
1542             mCount = 0;
1543             mLoadedCount = mUnpluggedCount = 0;
1544             if (detachIfReset) {
1545                 detach();
1546             }
1547         }
1548
1549         void detach() {
1550             mTimeBase.remove(this);
1551         }
1552
1553         void writeSummaryFromParcelLocked(Parcel out) {
1554             out.writeLong(mCount);
1555         }
1556
1557         void readSummaryFromParcelLocked(Parcel in) {
1558             mLoadedCount = in.readLong();
1559             mCount = mLoadedCount;
1560             mUnpluggedCount = mLoadedCount;
1561         }
1562     }
1563
1564     /**
1565      * State for keeping track of timing information.
1566      */
1567     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
1568         protected final Clocks mClocks;
1569         protected final int mType;
1570         protected final TimeBase mTimeBase;
1571
1572         protected int mCount;
1573         protected int mLoadedCount;
1574         protected int mLastCount;
1575         protected int mUnpluggedCount;
1576
1577         // Times are in microseconds for better accuracy when dividing by the
1578         // lock count, and are in "battery realtime" units.
1579
1580         /**
1581          * The total time we have accumulated since the start of the original
1582          * boot, to the last time something interesting happened in the
1583          * current run.
1584          */
1585         protected long mTotalTime;
1586
1587         /**
1588          * The total time we loaded for the previous runs.  Subtract this from
1589          * mTotalTime to find the time for the current run of the system.
1590          */
1591         protected long mLoadedTime;
1592
1593         /**
1594          * The run time of the last run of the system, as loaded from the
1595          * saved data.
1596          */
1597         protected long mLastTime;
1598
1599         /**
1600          * The value of mTotalTime when unplug() was last called.  Subtract
1601          * this from mTotalTime to find the time since the last unplug from
1602          * power.
1603          */
1604         protected long mUnpluggedTime;
1605
1606         /**
1607          * The total time this timer has been running until the latest mark has been set.
1608          * Subtract this from mTotalTime to get the time spent running since the mark was set.
1609          */
1610         protected long mTimeBeforeMark;
1611
1612         /**
1613          * Constructs from a parcel.
1614          * @param type
1615          * @param timeBase
1616          * @param in
1617          */
1618         public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
1619             mClocks = clocks;
1620             mType = type;
1621             mTimeBase = timeBase;
1622
1623             mCount = in.readInt();
1624             mLoadedCount = in.readInt();
1625             mLastCount = 0;
1626             mUnpluggedCount = in.readInt();
1627             mTotalTime = in.readLong();
1628             mLoadedTime = in.readLong();
1629             mLastTime = 0;
1630             mUnpluggedTime = in.readLong();
1631             mTimeBeforeMark = in.readLong();
1632             timeBase.add(this);
1633             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
1634         }
1635
1636         public Timer(Clocks clocks, int type, TimeBase timeBase) {
1637             mClocks = clocks;
1638             mType = type;
1639             mTimeBase = timeBase;
1640             timeBase.add(this);
1641         }
1642
1643         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
1644
1645         protected abstract int computeCurrentCountLocked();
1646
1647         /**
1648          * Clear state of this timer.  Returns true if the timer is inactive
1649          * so can be completely dropped.
1650          */
1651         public boolean reset(boolean detachIfReset) {
1652             mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0;
1653             mCount = mLoadedCount = mLastCount = 0;
1654             if (detachIfReset) {
1655                 detach();
1656             }
1657             return true;
1658         }
1659
1660         public void detach() {
1661             mTimeBase.remove(this);
1662         }
1663
1664         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1665             if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
1666                     + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1667             out.writeInt(computeCurrentCountLocked());
1668             out.writeInt(mLoadedCount);
1669             out.writeInt(mUnpluggedCount);
1670             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1671             out.writeLong(mLoadedTime);
1672             out.writeLong(mUnpluggedTime);
1673             out.writeLong(mTimeBeforeMark);
1674         }
1675
1676         @Override
1677         public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
1678             if (DEBUG && mType < 0) {
1679                 Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime
1680                         + " old mUnpluggedTime=" + mUnpluggedTime
1681                         + " old mUnpluggedCount=" + mUnpluggedCount);
1682             }
1683             mUnpluggedTime = computeRunTimeLocked(baseRealtime);
1684             mUnpluggedCount = computeCurrentCountLocked();
1685             if (DEBUG && mType < 0) {
1686                 Log.v(TAG, "unplug #" + mType
1687                         + ": new mUnpluggedTime=" + mUnpluggedTime
1688                         + " new mUnpluggedCount=" + mUnpluggedCount);
1689             }
1690         }
1691
1692         @Override
1693         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1694             if (DEBUG && mType < 0) {
1695                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
1696                         + " old mTotalTime=" + mTotalTime);
1697             }
1698             mTotalTime = computeRunTimeLocked(baseRealtime);
1699             mCount = computeCurrentCountLocked();
1700             if (DEBUG && mType < 0) {
1701                 Log.v(TAG, "plug #" + mType
1702                         + ": new mTotalTime=" + mTotalTime);
1703             }
1704         }
1705
1706         /**
1707          * Writes a possibly null Timer to a Parcel.
1708          *
1709          * @param out the Parcel to be written to.
1710          * @param timer a Timer, or null.
1711          */
1712         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
1713             if (timer == null) {
1714                 out.writeInt(0); // indicates null
1715                 return;
1716             }
1717             out.writeInt(1); // indicates non-null
1718
1719             timer.writeToParcel(out, elapsedRealtimeUs);
1720         }
1721
1722         @Override
1723         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
1724             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1725             if (which == STATS_SINCE_UNPLUGGED) {
1726                 val -= mUnpluggedTime;
1727             } else if (which != STATS_SINCE_CHARGED) {
1728                 val -= mLoadedTime;
1729             }
1730
1731             return val;
1732         }
1733
1734         @Override
1735         public int getCountLocked(int which) {
1736             int val = computeCurrentCountLocked();
1737             if (which == STATS_SINCE_UNPLUGGED) {
1738                 val -= mUnpluggedCount;
1739             } else if (which != STATS_SINCE_CHARGED) {
1740                 val -= mLoadedCount;
1741             }
1742
1743             return val;
1744         }
1745
1746         @Override
1747         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
1748             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1749             return val - mTimeBeforeMark;
1750         }
1751
1752         @Override
1753         public void logState(Printer pw, String prefix) {
1754             pw.println(prefix + "mCount=" + mCount
1755                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
1756                     + " mUnpluggedCount=" + mUnpluggedCount);
1757             pw.println(prefix + "mTotalTime=" + mTotalTime
1758                     + " mLoadedTime=" + mLoadedTime);
1759             pw.println(prefix + "mLastTime=" + mLastTime
1760                     + " mUnpluggedTime=" + mUnpluggedTime);
1761         }
1762
1763
1764         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1765             long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1766             out.writeLong(runTime);
1767             out.writeInt(computeCurrentCountLocked());
1768         }
1769
1770         public void readSummaryFromParcelLocked(Parcel in) {
1771             // Multiply by 1000 for backwards compatibility
1772             mTotalTime = mLoadedTime = in.readLong();
1773             mLastTime = 0;
1774             mUnpluggedTime = mTotalTime;
1775             mCount = mLoadedCount = in.readInt();
1776             mLastCount = 0;
1777             mUnpluggedCount = mCount;
1778
1779             // When reading the summary, we set the mark to be the latest information.
1780             mTimeBeforeMark = mTotalTime;
1781         }
1782     }
1783
1784     /**
1785      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
1786      * method. The state of the timer according to its {@link TimeBase} will determine how much
1787      * of the value is recorded.
1788      *
1789      * If the value being recorded resets, {@link #endSample()} can be called in order to
1790      * account for the change. If the value passed in to {@link #update(long, int)} decreased
1791      * between calls, the {@link #endSample()} is automatically called and the new value is
1792      * expected to increase monotonically from that point on.
1793      */
1794     public static class SamplingTimer extends Timer {
1795
1796         /**
1797          * The most recent reported count from /proc/wakelocks.
1798          */
1799         int mCurrentReportedCount;
1800
1801         /**
1802          * The reported count from /proc/wakelocks when unplug() was last
1803          * called.
1804          */
1805         int mUnpluggedReportedCount;
1806
1807         /**
1808          * The most recent reported total_time from /proc/wakelocks.
1809          */
1810         long mCurrentReportedTotalTime;
1811
1812
1813         /**
1814          * The reported total_time from /proc/wakelocks when unplug() was last
1815          * called.
1816          */
1817         long mUnpluggedReportedTotalTime;
1818
1819         /**
1820          * Whether we are currently in a discharge cycle.
1821          */
1822         boolean mTimeBaseRunning;
1823
1824         /**
1825          * Whether we are currently recording reported values.
1826          */
1827         boolean mTrackingReportedValues;
1828
1829         /*
1830          * A sequence counter, incremented once for each update of the stats.
1831          */
1832         int mUpdateVersion;
1833
1834         @VisibleForTesting
1835         public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
1836             super(clocks, 0, timeBase, in);
1837             mCurrentReportedCount = in.readInt();
1838             mUnpluggedReportedCount = in.readInt();
1839             mCurrentReportedTotalTime = in.readLong();
1840             mUnpluggedReportedTotalTime = in.readLong();
1841             mTrackingReportedValues = in.readInt() == 1;
1842             mTimeBaseRunning = timeBase.isRunning();
1843         }
1844
1845         @VisibleForTesting
1846         public SamplingTimer(Clocks clocks, TimeBase timeBase) {
1847             super(clocks, 0, timeBase);
1848             mTrackingReportedValues = false;
1849             mTimeBaseRunning = timeBase.isRunning();
1850         }
1851
1852         /**
1853          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
1854          * be less than the values used for a previous invocation.
1855          */
1856         public void endSample() {
1857             mTotalTime = computeRunTimeLocked(0 /* unused by us */);
1858             mCount = computeCurrentCountLocked();
1859             mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
1860             mUnpluggedReportedCount = mCurrentReportedCount = 0;
1861         }
1862
1863         public void setUpdateVersion(int version) {
1864             mUpdateVersion = version;
1865         }
1866
1867         public int getUpdateVersion() {
1868             return mUpdateVersion;
1869         }
1870
1871         /**
1872          * Updates the current recorded values. These are meant to be monotonically increasing
1873          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
1874          *
1875          * If the values being recorded have been reset, the monotonically increasing requirement
1876          * will be broken. In this case, {@link #endSample()} is automatically called and
1877          * the total value of totalTime and count are recorded, starting a new monotonically
1878          * increasing sample.
1879          *
1880          * @param totalTime total time of sample in microseconds.
1881          * @param count total number of times the event being sampled occurred.
1882          */
1883         public void update(long totalTime, int count) {
1884             if (mTimeBaseRunning && !mTrackingReportedValues) {
1885                 // Updating the reported value for the first time.
1886                 mUnpluggedReportedTotalTime = totalTime;
1887                 mUnpluggedReportedCount = count;
1888             }
1889
1890             mTrackingReportedValues = true;
1891
1892             if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) {
1893                 endSample();
1894             }
1895
1896             mCurrentReportedTotalTime = totalTime;
1897             mCurrentReportedCount = count;
1898         }
1899
1900         /**
1901          * Adds deltaTime and deltaCount to the current sample.
1902          *
1903          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
1904          * @param deltaCount additional number of times the event being sampled occurred.
1905          */
1906         public void add(long deltaTime, int deltaCount) {
1907             update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount);
1908         }
1909
1910         @Override
1911         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1912             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
1913             if (mTrackingReportedValues) {
1914                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
1915                 mUnpluggedReportedCount = mCurrentReportedCount;
1916             }
1917             mTimeBaseRunning = true;
1918         }
1919
1920         @Override
1921         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1922             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
1923             mTimeBaseRunning = false;
1924         }
1925
1926         @Override
1927         public void logState(Printer pw, String prefix) {
1928             super.logState(pw, prefix);
1929             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
1930                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
1931                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
1932                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
1933         }
1934
1935         @Override
1936         protected long computeRunTimeLocked(long curBatteryRealtime) {
1937             return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
1938                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
1939         }
1940
1941         @Override
1942         protected int computeCurrentCountLocked() {
1943             return mCount + (mTimeBaseRunning && mTrackingReportedValues
1944                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
1945         }
1946
1947         @Override
1948         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1949             super.writeToParcel(out, elapsedRealtimeUs);
1950             out.writeInt(mCurrentReportedCount);
1951             out.writeInt(mUnpluggedReportedCount);
1952             out.writeLong(mCurrentReportedTotalTime);
1953             out.writeLong(mUnpluggedReportedTotalTime);
1954             out.writeInt(mTrackingReportedValues ? 1 : 0);
1955         }
1956
1957         @Override
1958         public boolean reset(boolean detachIfReset) {
1959             super.reset(detachIfReset);
1960             mTrackingReportedValues = false;
1961             mUnpluggedReportedTotalTime = 0;
1962             mUnpluggedReportedCount = 0;
1963             return true;
1964         }
1965     }
1966
1967     /**
1968      * A timer that increments in batches.  It does not run for durations, but just jumps
1969      * for a pre-determined amount.
1970      */
1971     public static class BatchTimer extends Timer {
1972         final Uid mUid;
1973
1974         /**
1975          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
1976          */
1977         long mLastAddedTime;
1978
1979         /**
1980          * The last duration that we added to the timer.  This is in microseconds.
1981          */
1982         long mLastAddedDuration;
1983
1984         /**
1985          * Whether we are currently in a discharge cycle.
1986          */
1987         boolean mInDischarge;
1988
1989         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
1990             super(clocks, type, timeBase, in);
1991             mUid = uid;
1992             mLastAddedTime = in.readLong();
1993             mLastAddedDuration = in.readLong();
1994             mInDischarge = timeBase.isRunning();
1995         }
1996
1997         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
1998             super(clocks, type, timeBase);
1999             mUid = uid;
2000             mInDischarge = timeBase.isRunning();
2001         }
2002
2003         @Override
2004         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2005             super.writeToParcel(out, elapsedRealtimeUs);
2006             out.writeLong(mLastAddedTime);
2007             out.writeLong(mLastAddedDuration);
2008         }
2009
2010         @Override
2011         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2012             recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
2013             mInDischarge = false;
2014             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2015         }
2016
2017         @Override
2018         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
2019             recomputeLastDuration(elapsedRealtime, false);
2020             mInDischarge = true;
2021             // If we are still within the last added duration, then re-added whatever remains.
2022             if (mLastAddedTime == elapsedRealtime) {
2023                 mTotalTime += mLastAddedDuration;
2024             }
2025             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
2026         }
2027
2028         @Override
2029         public void logState(Printer pw, String prefix) {
2030             super.logState(pw, prefix);
2031             pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
2032                     + " mLastAddedDuration=" + mLastAddedDuration);
2033         }
2034
2035         private long computeOverage(long curTime) {
2036             if (mLastAddedTime > 0) {
2037                 return mLastTime + mLastAddedDuration - curTime;
2038             }
2039             return 0;
2040         }
2041
2042         private void recomputeLastDuration(long curTime, boolean abort) {
2043             final long overage = computeOverage(curTime);
2044             if (overage > 0) {
2045                 // Aborting before the duration ran out -- roll back the remaining
2046                 // duration.  Only do this if currently discharging; otherwise we didn't
2047                 // actually add the time.
2048                 if (mInDischarge) {
2049                     mTotalTime -= overage;
2050                 }
2051                 if (abort) {
2052                     mLastAddedTime = 0;
2053                 } else {
2054                     mLastAddedTime = curTime;
2055                     mLastAddedDuration -= overage;
2056                 }
2057             }
2058         }
2059
2060         public void addDuration(BatteryStatsImpl stats, long durationMillis) {
2061             final long now = mClocks.elapsedRealtime() * 1000;
2062             recomputeLastDuration(now, true);
2063             mLastAddedTime = now;
2064             mLastAddedDuration = durationMillis * 1000;
2065             if (mInDischarge) {
2066                 mTotalTime += mLastAddedDuration;
2067                 mCount++;
2068             }
2069         }
2070
2071         public void abortLastDuration(BatteryStatsImpl stats) {
2072             final long now = mClocks.elapsedRealtime() * 1000;
2073             recomputeLastDuration(now, true);
2074         }
2075
2076         @Override
2077         protected int computeCurrentCountLocked() {
2078             return mCount;
2079         }
2080
2081         @Override
2082         protected long computeRunTimeLocked(long curBatteryRealtime) {
2083             final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
2084             if (overage > 0) {
2085                 return mTotalTime = overage;
2086             }
2087             return mTotalTime;
2088         }
2089
2090         @Override
2091         public boolean reset(boolean detachIfReset) {
2092             final long now = mClocks.elapsedRealtime() * 1000;
2093             recomputeLastDuration(now, true);
2094             boolean stillActive = mLastAddedTime == now;
2095             super.reset(!stillActive && detachIfReset);
2096             return !stillActive;
2097         }
2098     }
2099
2100
2101     /**
2102      * A StopwatchTimer that also tracks the total and max individual
2103      * time spent active according to the given timebase.  Whereas
2104      * StopwatchTimer apportions the time amongst all in the pool,
2105      * the total and max durations are not apportioned.
2106      */
2107     public static class DurationTimer extends StopwatchTimer {
2108         /**
2109          * The time (in ms) that the timer was last acquired or the time base
2110          * last (re-)started. Increasing the nesting depth does not reset this time.
2111          *
2112          * -1 if the timer is currently not running or the time base is not running.
2113          *
2114          * If written to a parcel, the start time is reset, as is mNesting in the base class
2115          * StopwatchTimer.
2116          */
2117         long mStartTimeMs = -1;
2118
2119         /**
2120          * The longest time period (in ms) that the timer has been active. Not pooled.
2121          */
2122         long mMaxDurationMs;
2123
2124         /**
2125          * The time (in ms) that that the timer has been active since most recent
2126          * stopRunningLocked() or reset(). Not pooled.
2127          */
2128         long mCurrentDurationMs;
2129
2130         /**
2131          * The total time (in ms) that that the timer has been active since most recent reset()
2132          * prior to the current startRunningLocked. This is the sum of all past currentDurations
2133          * (but not including the present currentDuration) since reset. Not pooled.
2134          */
2135         long mTotalDurationMs;
2136
2137         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2138                 TimeBase timeBase, Parcel in) {
2139             super(clocks, uid, type, timerPool, timeBase, in);
2140             mMaxDurationMs = in.readLong();
2141             mTotalDurationMs = in.readLong();
2142             mCurrentDurationMs = in.readLong();
2143         }
2144
2145         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2146                 TimeBase timeBase) {
2147             super(clocks, uid, type, timerPool, timeBase);
2148         }
2149
2150         @Override
2151         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2152             super.writeToParcel(out, elapsedRealtimeUs);
2153             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2154             out.writeLong(mTotalDurationMs);
2155             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
2156         }
2157
2158         /**
2159          * Write the summary to the parcel.
2160          *
2161          * Since the time base is probably meaningless after we come back, reading
2162          * from this will have the effect of stopping the timer. So here all we write
2163          * is the max and total durations.
2164          */
2165         @Override
2166         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2167             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2168             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2169             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
2170         }
2171
2172         /**
2173          * Read the summary parcel.
2174          *
2175          * Has the side effect of stopping the timer.
2176          */
2177         @Override
2178         public void readSummaryFromParcelLocked(Parcel in) {
2179             super.readSummaryFromParcelLocked(in);
2180             mMaxDurationMs = in.readLong();
2181             mTotalDurationMs = in.readLong();
2182             mStartTimeMs = -1;
2183             mCurrentDurationMs = 0;
2184         }
2185
2186         /**
2187          * The TimeBase time started (again).
2188          *
2189          * If the timer is also running, store the start time.
2190          */
2191         public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
2192             super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
2193             if (mNesting > 0) {
2194                 mStartTimeMs = baseRealtime / 1000;
2195             }
2196         }
2197
2198         /**
2199          * The TimeBase stopped running.
2200          *
2201          * If the timer is running, add the duration into mCurrentDurationMs.
2202          */
2203         @Override
2204         public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) {
2205             super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs);
2206             if (mNesting > 0) {
2207                 // baseRealtimeUs has already been converted to the timebase's realtime.
2208                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
2209             }
2210             mStartTimeMs = -1;
2211         }
2212
2213         @Override
2214         public void logState(Printer pw, String prefix) {
2215             super.logState(pw, prefix);
2216         }
2217
2218         @Override
2219         public void startRunningLocked(long elapsedRealtimeMs) {
2220             super.startRunningLocked(elapsedRealtimeMs);
2221             if (mNesting == 1 && mTimeBase.isRunning()) {
2222                 // Just started
2223                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
2224             }
2225         }
2226
2227         /**
2228          * Decrements the mNesting ref-count on this timer.
2229          *
2230          * If it actually stopped (mNesting went to 0), then possibly update
2231          * mMaxDuration if the current duration was the longest ever.
2232          */
2233         @Override
2234         public void stopRunningLocked(long elapsedRealtimeMs) {
2235             if (mNesting == 1) {
2236                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2237                 mTotalDurationMs += durationMs;
2238                 if (durationMs > mMaxDurationMs) {
2239                     mMaxDurationMs = durationMs;
2240                 }
2241                 mStartTimeMs = -1;
2242                 mCurrentDurationMs = 0;
2243             }
2244             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
2245             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
2246             super.stopRunningLocked(elapsedRealtimeMs);
2247         }
2248
2249         @Override
2250         public boolean reset(boolean detachIfReset) {
2251             boolean result = super.reset(detachIfReset);
2252             mMaxDurationMs = 0;
2253             mTotalDurationMs = 0;
2254             mCurrentDurationMs = 0;
2255             if (mNesting > 0) {
2256                 mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
2257             } else {
2258                 mStartTimeMs = -1;
2259             }
2260             return result;
2261         }
2262
2263         /**
2264          * Returns the max duration that this timer has ever seen.
2265          *
2266          * Note that this time is NOT split between the timers in the timer group that
2267          * this timer is attached to.  It is the TOTAL time.
2268          */
2269         @Override
2270         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
2271             if (mNesting > 0) {
2272                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2273                 if (durationMs > mMaxDurationMs) {
2274                     return durationMs;
2275                 }
2276             }
2277             return mMaxDurationMs;
2278         }
2279
2280         /**
2281          * Returns the time since the timer was started.
2282          * Returns 0 if the timer is not currently running.
2283          *
2284          * Note that this time is NOT split between the timers in the timer group that
2285          * this timer is attached to.  It is the TOTAL time.
2286          *
2287          * Note that if running timer is parceled and unparceled, this method will return
2288          * current duration value at the time of parceling even though timer may not be
2289          * currently running.
2290          */
2291         @Override
2292         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
2293             long durationMs = mCurrentDurationMs;
2294             if (mNesting > 0 && mTimeBase.isRunning()) {
2295                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000)
2296                         - mStartTimeMs;
2297             }
2298             return durationMs;
2299         }
2300
2301         /**
2302          * Returns the total cumulative duration that this timer has been on since reset().
2303          * If mTimerPool == null, this should be the same
2304          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
2305          *
2306          * Note that this time is NOT split between the timers in the timer group that
2307          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
2308          * the result will not be equivalent to getTotalTimeLocked.
2309          */
2310         @Override
2311         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
2312             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
2313         }
2314     }
2315
2316     /**
2317      * State for keeping track of timing information.
2318      */
2319     public static class StopwatchTimer extends Timer {
2320         final Uid mUid;
2321         final ArrayList<StopwatchTimer> mTimerPool;
2322
2323         int mNesting;
2324
2325         /**
2326          * The last time at which we updated the timer.  If mNesting is > 0,
2327          * subtract this from the current battery time to find the amount of
2328          * time we have been running since we last computed an update.
2329          */
2330         long mUpdateTime;
2331
2332         /**
2333          * The total time at which the timer was acquired, to determine if it
2334          * was actually held for an interesting duration. If time base was not running when timer
2335          * was acquired, will be -1.
2336          */
2337         long mAcquireTime = -1;
2338
2339         long mTimeout;
2340
2341         /**
2342          * For partial wake locks, keep track of whether we are in the list
2343          * to consume CPU cycles.
2344          */
2345         @VisibleForTesting
2346         public boolean mInList;
2347
2348         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2349                 TimeBase timeBase, Parcel in) {
2350             super(clocks, type, timeBase, in);
2351             mUid = uid;
2352             mTimerPool = timerPool;
2353             mUpdateTime = in.readLong();
2354         }
2355
2356         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2357                 TimeBase timeBase) {
2358             super(clocks, type, timeBase);
2359             mUid = uid;
2360             mTimerPool = timerPool;
2361         }
2362
2363         public void setTimeout(long timeout) {
2364             mTimeout = timeout;
2365         }
2366
2367         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2368             super.writeToParcel(out, elapsedRealtimeUs);
2369             out.writeLong(mUpdateTime);
2370         }
2371
2372         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2373             if (mNesting > 0) {
2374                 if (DEBUG && mType < 0) {
2375                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
2376                 }
2377                 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2378                 mUpdateTime = baseRealtime;
2379                 if (DEBUG && mType < 0) {
2380                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
2381                 }
2382             }
2383         }
2384
2385         public void logState(Printer pw, String prefix) {
2386             super.logState(pw, prefix);
2387             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
2388                     + " mAcquireTime=" + mAcquireTime);
2389         }
2390
2391         public void startRunningLocked(long elapsedRealtimeMs) {
2392             if (mNesting++ == 0) {
2393                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2394                 mUpdateTime = batteryRealtime;
2395                 if (mTimerPool != null) {
2396                     // Accumulate time to all currently active timers before adding
2397                     // this new one to the pool.
2398                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
2399                     // Add this timer to the active pool
2400                     mTimerPool.add(this);
2401                 }
2402                 if (mTimeBase.isRunning()) {
2403                     // Increment the count
2404                     mCount++;
2405                     mAcquireTime = mTotalTime;
2406                 } else {
2407                     mAcquireTime = -1;
2408                 }
2409                 if (DEBUG && mType < 0) {
2410                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
2411                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2412                             + " mAcquireTime=" + mAcquireTime);
2413                 }
2414             }
2415         }
2416
2417         public boolean isRunningLocked() {
2418             return mNesting > 0;
2419         }
2420
2421         public void stopRunningLocked(long elapsedRealtimeMs) {
2422             // Ignore attempt to stop a timer that isn't running
2423             if (mNesting == 0) {
2424                 return;
2425             }
2426             if (--mNesting == 0) {
2427                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2428                 if (mTimerPool != null) {
2429                     // Accumulate time to all active counters, scaled by the total
2430                     // active in the pool, before taking this one out of the pool.
2431                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
2432                     // Remove this timer from the active pool
2433                     mTimerPool.remove(this);
2434                 } else {
2435                     mNesting = 1;
2436                     mTotalTime = computeRunTimeLocked(batteryRealtime);
2437                     mNesting = 0;
2438                 }
2439
2440                 if (DEBUG && mType < 0) {
2441                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
2442                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2443                             + " mAcquireTime=" + mAcquireTime);
2444                 }
2445
2446                 if (mAcquireTime >= 0 && mTotalTime == mAcquireTime) {
2447                     // If there was no change in the time, then discard this
2448                     // count.  A somewhat cheezy strategy, but hey.
2449                     mCount--;
2450                 }
2451             }
2452         }
2453
2454         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2455             if (mNesting > 0) {
2456                 mNesting = 1;
2457                 stopRunningLocked(elapsedRealtimeMs);
2458             }
2459         }
2460
2461         // Update the total time for all other running Timers with the same type as this Timer
2462         // due to a change in timer count
2463         private static long refreshTimersLocked(long batteryRealtime,
2464                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
2465             long selfTime = 0;
2466             final int N = pool.size();
2467             for (int i=N-1; i>= 0; i--) {
2468                 final StopwatchTimer t = pool.get(i);
2469                 long heldTime = batteryRealtime - t.mUpdateTime;
2470                 if (heldTime > 0) {
2471                     final long myTime = heldTime / N;
2472                     if (t == self) {
2473                         selfTime = myTime;
2474                     }
2475                     t.mTotalTime += myTime;
2476                 }
2477                 t.mUpdateTime = batteryRealtime;
2478             }
2479             return selfTime;
2480         }
2481
2482         @Override
2483         protected long computeRunTimeLocked(long curBatteryRealtime) {
2484             if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
2485                 curBatteryRealtime = mUpdateTime + mTimeout;
2486             }
2487             return mTotalTime + (mNesting > 0
2488                     ? (curBatteryRealtime - mUpdateTime)
2489                             / (mTimerPool != null ? mTimerPool.size() : 1)
2490                     : 0);
2491         }
2492
2493         @Override
2494         protected int computeCurrentCountLocked() {
2495             return mCount;
2496         }
2497
2498         @Override
2499         public boolean reset(boolean detachIfReset) {
2500             boolean canDetach = mNesting <= 0;
2501             super.reset(canDetach && detachIfReset);
2502             if (mNesting > 0) {
2503                 mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
2504             }
2505             mAcquireTime = -1; // to ensure mCount isn't decreased to -1 if timer is stopped later.
2506             return canDetach;
2507         }
2508
2509         @Override
2510         public void detach() {
2511             super.detach();
2512             if (mTimerPool != null) {
2513                 mTimerPool.remove(this);
2514             }
2515         }
2516
2517         @Override
2518         public void readSummaryFromParcelLocked(Parcel in) {
2519             super.readSummaryFromParcelLocked(in);
2520             mNesting = 0;
2521         }
2522
2523         /**
2524          * Set the mark so that we can query later for the total time the timer has
2525          * accumulated since this point. The timer can be running or not.
2526          *
2527          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
2528          */
2529         public void setMark(long elapsedRealtimeMs) {
2530             final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2531             if (mNesting > 0) {
2532                 // We are running.
2533                 if (mTimerPool != null) {
2534                     refreshTimersLocked(batteryRealtime, mTimerPool, this);
2535                 } else {
2536                     mTotalTime += batteryRealtime - mUpdateTime;
2537                     mUpdateTime = batteryRealtime;
2538                 }
2539             }
2540             mTimeBeforeMark = mTotalTime;
2541         }
2542     }
2543
2544     /**
2545      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
2546      * TimeBase is effectively a subset of the other.
2547      */
2548     public static class DualTimer extends DurationTimer {
2549         // This class both is a DurationTimer and also holds a second DurationTimer.
2550         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
2551         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
2552         // STATS_SINCE_CHARGED).
2553         // mSubTimer typically tracks only part of the total time, such as background time, as
2554         // determined by a subTimeBase. It is NOT pooled.
2555         private final DurationTimer mSubTimer;
2556
2557         /**
2558          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2559          * The main timer (this) is based on the given timeBase and timerPool.
2560          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2561          * the main timer is.
2562          */
2563         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2564                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
2565             super(clocks, uid, type, timerPool, timeBase, in);
2566             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase, in);
2567         }
2568
2569         /**
2570          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2571          * The main timer (this) is based on the given timeBase and timerPool.
2572          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2573          * the main timer is.
2574          */
2575         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2576                 TimeBase timeBase, TimeBase subTimeBase) {
2577             super(clocks, uid, type, timerPool, timeBase);
2578             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase);
2579         }
2580
2581         /** Get the secondary timer. */
2582         @Override
2583         public DurationTimer getSubTimer() {
2584             return mSubTimer;
2585         }
2586
2587         @Override
2588         public void startRunningLocked(long elapsedRealtimeMs) {
2589             super.startRunningLocked(elapsedRealtimeMs);
2590             mSubTimer.startRunningLocked(elapsedRealtimeMs);
2591         }
2592
2593         @Override
2594         public void stopRunningLocked(long elapsedRealtimeMs) {
2595             super.stopRunningLocked(elapsedRealtimeMs);
2596             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
2597         }
2598
2599         @Override
2600         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2601             super.stopAllRunningLocked(elapsedRealtimeMs);
2602             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
2603         }
2604
2605         @Override
2606         public boolean reset(boolean detachIfReset) {
2607             boolean active = false;
2608             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
2609             active |= !mSubTimer.reset(false);
2610             active |= !super.reset(detachIfReset);
2611             return !active;
2612         }
2613
2614         @Override
2615         public void detach() {
2616             mSubTimer.detach();
2617             super.detach();
2618         }
2619
2620         @Override
2621         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2622             super.writeToParcel(out, elapsedRealtimeUs);
2623             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
2624         }
2625
2626         @Override
2627         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2628             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2629             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2630         }
2631
2632         @Override
2633         public void readSummaryFromParcelLocked(Parcel in) {
2634             super.readSummaryFromParcelLocked(in);
2635             mSubTimer.readSummaryFromParcelLocked(in);
2636         }
2637     }
2638
2639
2640     public abstract class OverflowArrayMap<T> {
2641         private static final String OVERFLOW_NAME = "*overflow*";
2642
2643         final int mUid;
2644         final ArrayMap<String, T> mMap = new ArrayMap<>();
2645         T mCurOverflow;
2646         ArrayMap<String, MutableInt> mActiveOverflow;
2647         long mLastOverflowTime;
2648         long mLastOverflowFinishTime;
2649         long mLastClearTime;
2650         long mLastCleanupTime;
2651
2652         public OverflowArrayMap(int uid) {
2653             mUid = uid;
2654         }
2655
2656         public ArrayMap<String, T> getMap() {
2657             return mMap;
2658         }
2659
2660         public void clear() {
2661             mLastClearTime = SystemClock.elapsedRealtime();
2662             mMap.clear();
2663             mCurOverflow = null;
2664             mActiveOverflow = null;
2665         }
2666
2667         public void add(String name, T obj) {
2668             if (name == null) {
2669                 name = "";
2670             }
2671             mMap.put(name, obj);
2672             if (OVERFLOW_NAME.equals(name)) {
2673                 mCurOverflow = obj;
2674             }
2675         }
2676
2677         public void cleanup() {
2678             mLastCleanupTime = SystemClock.elapsedRealtime();
2679             if (mActiveOverflow != null) {
2680                 if (mActiveOverflow.size() == 0) {
2681                     mActiveOverflow = null;
2682                 }
2683             }
2684             if (mActiveOverflow == null) {
2685                 // There is no currently active overflow, so we should no longer have
2686                 // an overflow entry.
2687                 if (mMap.containsKey(OVERFLOW_NAME)) {
2688                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
2689                             + mMap.get(OVERFLOW_NAME));
2690                     mMap.remove(OVERFLOW_NAME);
2691                 }
2692                 mCurOverflow = null;
2693             } else {
2694                 // There is currently active overflow, so we should still have an overflow entry.
2695                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
2696                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
2697                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
2698                 }
2699             }
2700         }
2701
2702         public T startObject(String name) {
2703             if (name == null) {
2704                 name = "";
2705             }
2706             T obj = mMap.get(name);
2707             if (obj != null) {
2708                 return obj;
2709             }
2710
2711             // No object exists for the given name, but do we currently have it
2712             // running as part of the overflow?
2713             if (mActiveOverflow != null) {
2714                 MutableInt over = mActiveOverflow.get(name);
2715                 if (over != null) {
2716                     // We are already actively counting this name in the overflow object.
2717                     obj = mCurOverflow;
2718                     if (obj == null) {
2719                         // Shouldn't be here, but we'll try to recover.
2720                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
2721                         obj = mCurOverflow = instantiateObject();
2722                         mMap.put(OVERFLOW_NAME, obj);
2723                     }
2724                     over.value++;
2725                     return obj;
2726                 }
2727             }
2728
2729             // No object exists for given name nor in the overflow; we need to make
2730             // a new one.
2731             final int N = mMap.size();
2732             if (N >= MAX_WAKELOCKS_PER_UID) {
2733                 // Went over the limit on number of objects to track; this one goes
2734                 // in to the overflow.
2735                 obj = mCurOverflow;
2736                 if (obj == null) {
2737                     // Need to start overflow now...
2738                     obj = mCurOverflow = instantiateObject();
2739                     mMap.put(OVERFLOW_NAME, obj);
2740                 }
2741                 if (mActiveOverflow == null) {
2742                     mActiveOverflow = new ArrayMap<>();
2743                 }
2744                 mActiveOverflow.put(name, new MutableInt(1));
2745                 mLastOverflowTime = SystemClock.elapsedRealtime();
2746                 return obj;
2747             }
2748
2749             // Normal case where we just need to make a new object.
2750             obj = instantiateObject();
2751             mMap.put(name, obj);
2752             return obj;
2753         }
2754
2755         public T stopObject(String name) {
2756             if (name == null) {
2757                 name = "";
2758             }
2759             T obj = mMap.get(name);
2760             if (obj != null) {
2761                 return obj;
2762             }
2763
2764             // No object exists for the given name, but do we currently have it
2765             // running as part of the overflow?
2766             if (mActiveOverflow != null) {
2767                 MutableInt over = mActiveOverflow.get(name);
2768                 if (over != null) {
2769                     // We are already actively counting this name in the overflow object.
2770                     obj = mCurOverflow;
2771                     if (obj != null) {
2772                         over.value--;
2773                         if (over.value <= 0) {
2774                             mActiveOverflow.remove(name);
2775                             mLastOverflowFinishTime = SystemClock.elapsedRealtime();
2776                         }
2777                         return obj;
2778                     }
2779                 }
2780             }
2781
2782             // Huh, they are stopping an active operation but we can't find one!
2783             // That's not good.
2784             StringBuilder sb = new StringBuilder();
2785             sb.append("Unable to find object for ");
2786             sb.append(name);
2787             sb.append(" in uid ");
2788             sb.append(mUid);
2789             sb.append(" mapsize=");
2790             sb.append(mMap.size());
2791             sb.append(" activeoverflow=");
2792             sb.append(mActiveOverflow);
2793             sb.append(" curoverflow=");
2794             sb.append(mCurOverflow);
2795             long now = SystemClock.elapsedRealtime();
2796             if (mLastOverflowTime != 0) {
2797                 sb.append(" lastOverflowTime=");
2798                 TimeUtils.formatDuration(mLastOverflowTime-now, sb);
2799             }
2800             if (mLastOverflowFinishTime != 0) {
2801                 sb.append(" lastOverflowFinishTime=");
2802                 TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb);
2803             }
2804             if (mLastClearTime != 0) {
2805                 sb.append(" lastClearTime=");
2806                 TimeUtils.formatDuration(mLastClearTime-now, sb);
2807             }
2808             if (mLastCleanupTime != 0) {
2809                 sb.append(" lastCleanupTime=");
2810                 TimeUtils.formatDuration(mLastCleanupTime-now, sb);
2811             }
2812             Slog.wtf(TAG, sb.toString());
2813             return null;
2814         }
2815
2816         public abstract T instantiateObject();
2817     }
2818
2819     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
2820             implements Parcelable {
2821         private final LongSamplingCounter mIdleTimeMillis;
2822         private final LongSamplingCounter mScanTimeMillis;
2823         private final LongSamplingCounter mRxTimeMillis;
2824         private final LongSamplingCounter[] mTxTimeMillis;
2825         private final LongSamplingCounter mPowerDrainMaMs;
2826
2827         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
2828             mIdleTimeMillis = new LongSamplingCounter(timeBase);
2829             mScanTimeMillis = new LongSamplingCounter(timeBase);
2830             mRxTimeMillis = new LongSamplingCounter(timeBase);
2831             mTxTimeMillis = new LongSamplingCounter[numTxStates];
2832             for (int i = 0; i < numTxStates; i++) {
2833                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
2834             }
2835             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
2836         }
2837
2838         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
2839             mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
2840             mScanTimeMillis = new LongSamplingCounter(timeBase, in);
2841             mRxTimeMillis = new LongSamplingCounter(timeBase, in);
2842             final int recordedTxStates = in.readInt();
2843             if (recordedTxStates != numTxStates) {
2844                 throw new ParcelFormatException("inconsistent tx state lengths");
2845             }
2846
2847             mTxTimeMillis = new LongSamplingCounter[numTxStates];
2848             for (int i = 0; i < numTxStates; i++) {
2849                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
2850             }
2851             mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
2852         }
2853
2854         public void readSummaryFromParcel(Parcel in) {
2855             mIdleTimeMillis.readSummaryFromParcelLocked(in);
2856             mScanTimeMillis.readSummaryFromParcelLocked(in);
2857             mRxTimeMillis.readSummaryFromParcelLocked(in);
2858             final int recordedTxStates = in.readInt();
2859             if (recordedTxStates != mTxTimeMillis.length) {
2860                 throw new ParcelFormatException("inconsistent tx state lengths");
2861             }
2862             for (LongSamplingCounter counter : mTxTimeMillis) {
2863                 counter.readSummaryFromParcelLocked(in);
2864             }
2865             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
2866         }
2867
2868         @Override
2869         public int describeContents() {
2870             return 0;
2871         }
2872
2873         public void writeSummaryToParcel(Parcel dest) {
2874             mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
2875             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
2876             mRxTimeMillis.writeSummaryFromParcelLocked(dest);
2877             dest.writeInt(mTxTimeMillis.length);
2878             for (LongSamplingCounter counter : mTxTimeMillis) {
2879                 counter.writeSummaryFromParcelLocked(dest);
2880             }
2881             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
2882         }
2883
2884         @Override
2885         public void writeToParcel(Parcel dest, int flags) {
2886             mIdleTimeMillis.writeToParcel(dest);
2887             mScanTimeMillis.writeToParcel(dest);
2888             mRxTimeMillis.writeToParcel(dest);
2889             dest.writeInt(mTxTimeMillis.length);
2890             for (LongSamplingCounter counter : mTxTimeMillis) {
2891                 counter.writeToParcel(dest);
2892             }
2893             mPowerDrainMaMs.writeToParcel(dest);
2894         }
2895
2896         public void reset(boolean detachIfReset) {
2897             mIdleTimeMillis.reset(detachIfReset);
2898             mScanTimeMillis.reset(detachIfReset);
2899             mRxTimeMillis.reset(detachIfReset);
2900             for (LongSamplingCounter counter : mTxTimeMillis) {
2901                 counter.reset(detachIfReset);
2902             }
2903             mPowerDrainMaMs.reset(detachIfReset);
2904         }
2905
2906         public void detach() {
2907             mIdleTimeMillis.detach();
2908             mScanTimeMillis.detach();
2909             mRxTimeMillis.detach();
2910             for (LongSamplingCounter counter : mTxTimeMillis) {
2911                 counter.detach();
2912             }
2913             mPowerDrainMaMs.detach();
2914         }
2915
2916         /**
2917          * @return a LongSamplingCounter, measuring time spent in the idle state in
2918          * milliseconds.
2919          */
2920         @Override
2921         public LongSamplingCounter getIdleTimeCounter() {
2922             return mIdleTimeMillis;
2923         }
2924
2925         /**
2926          * @return a LongSamplingCounter, measuring time spent in the scan state in
2927          * milliseconds.
2928          */
2929         @Override
2930         public LongSamplingCounter getScanTimeCounter() {
2931             return mScanTimeMillis;
2932         }
2933
2934         /**
2935          * @return a LongSamplingCounter, measuring time spent in the receive state in
2936          * milliseconds.
2937          */
2938         @Override
2939         public LongSamplingCounter getRxTimeCounter() {
2940             return mRxTimeMillis;
2941         }
2942
2943         /**
2944          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
2945          * milliseconds.
2946          */
2947         @Override
2948         public LongSamplingCounter[] getTxTimeCounters() {
2949             return mTxTimeMillis;
2950         }
2951
2952         /**
2953          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
2954          */
2955         @Override
2956         public LongSamplingCounter getPowerCounter() {
2957             return mPowerDrainMaMs;
2958         }
2959     }
2960
2961     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
2962     public SamplingTimer getRpmTimerLocked(String name) {
2963         SamplingTimer rpmt = mRpmStats.get(name);
2964         if (rpmt == null) {
2965             rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
2966             mRpmStats.put(name, rpmt);
2967         }
2968         return rpmt;
2969     }
2970
2971     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
2972     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
2973         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
2974         if (rpmt == null) {
2975             rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
2976             mScreenOffRpmStats.put(name, rpmt);
2977         }
2978         return rpmt;
2979     }
2980
2981     /*
2982      * Get the wakeup reason counter, and create a new one if one
2983      * doesn't already exist.
2984      */
2985     public SamplingTimer getWakeupReasonTimerLocked(String name) {
2986         SamplingTimer timer = mWakeupReasonStats.get(name);
2987         if (timer == null) {
2988             timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
2989             mWakeupReasonStats.put(name, timer);
2990         }
2991         return timer;
2992     }
2993
2994     /*
2995      * Get the KernelWakelockTimer associated with name, and create a new one if one
2996      * doesn't already exist.
2997      */
2998     public SamplingTimer getKernelWakelockTimerLocked(String name) {
2999         SamplingTimer kwlt = mKernelWakelockStats.get(name);
3000         if (kwlt == null) {
3001             kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3002             mKernelWakelockStats.put(name, kwlt);
3003         }
3004         return kwlt;
3005     }
3006
3007     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
3008         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
3009         if (kmt == null) {
3010             kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3011             mKernelMemoryStats.put(bucket, kmt);
3012         }
3013         return kmt;
3014     }
3015
3016     private int writeHistoryTag(HistoryTag tag) {
3017         Integer idxObj = mHistoryTagPool.get(tag);
3018         int idx;
3019         if (idxObj != null) {
3020             idx = idxObj;
3021         } else {
3022             idx = mNextHistoryTagIdx;
3023             HistoryTag key = new HistoryTag();
3024             key.setTo(tag);
3025             tag.poolIdx = idx;
3026             mHistoryTagPool.put(key, idx);
3027             mNextHistoryTagIdx++;
3028             mNumHistoryTagChars += key.string.length() + 1;
3029         }
3030         return idx;
3031     }
3032
3033     private void readHistoryTag(int index, HistoryTag tag) {
3034         tag.string = mReadHistoryStrings[index];
3035         tag.uid = mReadHistoryUids[index];
3036         tag.poolIdx = index;
3037     }
3038
3039     /*
3040         The history delta format uses flags to denote further data in subsequent ints in the parcel.
3041
3042         There is always the first token, which may contain the delta time, or an indicator of
3043         the length of the time (int or long) following this token.
3044
3045         First token: always present,
3046         31              23              15               7             0
3047         â–ˆM|L|K|J|I|H|G|Fâ–ˆE|D|C|B|A|T|T|Tâ–ˆT|T|T|T|T|T|T|Tâ–ˆT|T|T|T|T|T|T|Tâ–ˆ
3048
3049         T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
3050            follows containing the time, and 0x7ffff indicates a long immediately follows with the
3051            delta time.
3052         A: battery level changed and an int follows with battery data.
3053         B: state changed and an int follows with state change data.
3054         C: state2 has changed and an int follows with state2 change data.
3055         D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
3056         E: event data has changed and an event struct follows.
3057         F: battery charge in coulombs has changed and an int with the charge follows.
3058         G: state flag denoting that the mobile radio was active.
3059         H: state flag denoting that the wifi radio was active.
3060         I: state flag denoting that a wifi scan occurred.
3061         J: state flag denoting that a wifi full lock was held.
3062         K: state flag denoting that the gps was on.
3063         L: state flag denoting that a wakelock was held.
3064         M: state flag denoting that the cpu was running.
3065
3066         Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
3067         with the time delta.
3068
3069         Battery level int: if A in the first token is set,
3070         31              23              15               7             0
3071         â–ˆL|L|L|L|L|L|L|Tâ–ˆT|T|T|T|T|T|T|Tâ–ˆT|V|V|V|V|V|V|Vâ–ˆV|V|V|V|V|V|V|Dâ–ˆ
3072
3073         D: indicates that extra history details follow.
3074         V: the battery voltage.
3075         T: the battery temperature.
3076         L: the battery level (out of 100).
3077
3078         State change int: if B in the first token is set,
3079         31              23              15               7             0
3080         â–ˆS|S|S|H|H|H|P|Pâ–ˆF|E|D|C|B| | |Aâ–ˆ | | | | | | | â–ˆ | | | | | | | â–ˆ
3081
3082         A: wifi multicast was on.
3083         B: battery was plugged in.
3084         C: screen was on.
3085         D: phone was scanning for signal.
3086         E: audio was on.
3087         F: a sensor was active.
3088
3089         State2 change int: if C in the first token is set,
3090         31              23              15               7             0
3091         â–ˆM|L|K|J|I|H|H|Gâ–ˆF|E|D|C| | | | â–ˆ | | | | | | | â–ˆ |B|B|B|A|A|A|Aâ–ˆ
3092
3093         A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
3094         B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
3095         C: a bluetooth scan was active.
3096         D: the camera was active.
3097         E: bluetooth was on.
3098         F: a phone call was active.
3099         G: the device was charging.
3100         H: 2 bits indicating the device-idle (doze) state: off, light, full
3101         I: the flashlight was on.
3102         J: wifi was on.
3103         K: wifi was running.
3104         L: video was playing.
3105         M: power save mode was on.
3106
3107         Wakelock/wakereason struct: if D in the first token is set,
3108         TODO(adamlesinski): describe wakelock/wakereason struct.
3109
3110         Event struct: if E in the first token is set,
3111         TODO(adamlesinski): describe the event struct.
3112
3113         History step details struct: if D in the battery level int is set,
3114         TODO(adamlesinski): describe the history step details struct.
3115
3116         Battery charge int: if F in the first token is set, an int representing the battery charge
3117         in coulombs follows.
3118      */
3119
3120     // Part of initial delta int that specifies the time delta.
3121     static final int DELTA_TIME_MASK = 0x7ffff;
3122     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
3123     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
3124     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
3125     // Flag in delta int: a new battery level int follows.
3126     static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
3127     // Flag in delta int: a new full state and battery status int follows.
3128     static final int DELTA_STATE_FLAG                       = 0x00100000;
3129     // Flag in delta int: a new full state2 int follows.
3130     static final int DELTA_STATE2_FLAG                      = 0x00200000;
3131     // Flag in delta int: contains a wakelock or wakeReason tag.
3132     static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
3133     // Flag in delta int: contains an event description.
3134     static final int DELTA_EVENT_FLAG                       = 0x00800000;
3135     // Flag in delta int: contains the battery charge count in uAh.
3136     static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
3137     // These upper bits are the frequently changing state bits.
3138     static final int DELTA_STATE_MASK                       = 0xfe000000;
3139
3140     // These are the pieces of battery state that are packed in to the upper bits of
3141     // the state int that have been packed in to the first delta int.  They must fit
3142     // in STATE_BATTERY_MASK.
3143     static final int STATE_BATTERY_MASK         = 0xff000000;
3144     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
3145     static final int STATE_BATTERY_STATUS_SHIFT = 29;
3146     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
3147     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
3148     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
3149     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
3150
3151     // We use the low bit of the battery state int to indicate that we have full details
3152     // from a battery level change.
3153     static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
3154
3155     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
3156         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
3157             dest.writeInt(DELTA_TIME_ABS);
3158             cur.writeToParcel(dest, 0);
3159             return;
3160         }
3161
3162         final long deltaTime = cur.time - last.time;
3163         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
3164         final int lastStateInt = buildStateInt(last);
3165
3166         int deltaTimeToken;
3167         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
3168             deltaTimeToken = DELTA_TIME_LONG;
3169         } else if (deltaTime >= DELTA_TIME_ABS) {
3170             deltaTimeToken = DELTA_TIME_INT;
3171         } else {
3172             deltaTimeToken = (int)deltaTime;
3173         }
3174         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
3175         final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
3176                 ? BATTERY_DELTA_LEVEL_FLAG : 0;
3177         final boolean computeStepDetails = includeStepDetails != 0
3178                 || mLastHistoryStepDetails == null;
3179         final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
3180         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
3181         if (batteryLevelIntChanged) {
3182             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
3183         }
3184         final int stateInt = buildStateInt(cur);
3185         final boolean stateIntChanged = stateInt != lastStateInt;
3186         if (stateIntChanged) {
3187             firstToken |= DELTA_STATE_FLAG;
3188         }
3189         final boolean state2IntChanged = cur.states2 != last.states2;
3190         if (state2IntChanged) {
3191             firstToken |= DELTA_STATE2_FLAG;
3192         }
3193         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3194             firstToken |= DELTA_WAKELOCK_FLAG;
3195         }
3196         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3197             firstToken |= DELTA_EVENT_FLAG;
3198         }
3199
3200         final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
3201         if (batteryChargeChanged) {
3202             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
3203         }
3204         dest.writeInt(firstToken);
3205         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3206                 + " deltaTime=" + deltaTime);
3207
3208         if (deltaTimeToken >= DELTA_TIME_INT) {
3209             if (deltaTimeToken == DELTA_TIME_INT) {
3210                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
3211                 dest.writeInt((int)deltaTime);
3212             } else {
3213                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
3214                 dest.writeLong(deltaTime);
3215             }
3216         }
3217         if (batteryLevelIntChanged) {
3218             dest.writeInt(batteryLevelInt);
3219             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
3220                     + Integer.toHexString(batteryLevelInt)
3221                     + " batteryLevel=" + cur.batteryLevel
3222                     + " batteryTemp=" + cur.batteryTemperature
3223                     + " batteryVolt=" + (int)cur.batteryVoltage);
3224         }
3225         if (stateIntChanged) {
3226             dest.writeInt(stateInt);
3227             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
3228                     + Integer.toHexString(stateInt)
3229                     + " batteryStatus=" + cur.batteryStatus
3230                     + " batteryHealth=" + cur.batteryHealth
3231                     + " batteryPlugType=" + cur.batteryPlugType
3232                     + " states=0x" + Integer.toHexString(cur.states));
3233         }
3234         if (state2IntChanged) {
3235             dest.writeInt(cur.states2);
3236             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
3237                     + Integer.toHexString(cur.states2));
3238         }
3239         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3240             int wakeLockIndex;
3241             int wakeReasonIndex;
3242             if (cur.wakelockTag != null) {
3243                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
3244                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3245                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3246             } else {
3247                 wakeLockIndex = 0xffff;
3248             }
3249             if (cur.wakeReasonTag != null) {
3250                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
3251                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3252                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3253             } else {
3254                 wakeReasonIndex = 0xffff;
3255             }
3256             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
3257         }
3258         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3259             int index = writeHistoryTag(cur.eventTag);
3260             int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
3261             dest.writeInt(codeAndIndex);
3262             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
3263                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3264                     + cur.eventTag.string);
3265         }
3266         if (computeStepDetails) {
3267             if (mPlatformIdleStateCallback != null) {
3268                 mCurHistoryStepDetails.statPlatformIdleState =
3269                         mPlatformIdleStateCallback.getPlatformLowPowerStats();
3270                 if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
3271                         mCurHistoryStepDetails.statPlatformIdleState);
3272
3273                 mCurHistoryStepDetails.statSubsystemPowerState =
3274                         mPlatformIdleStateCallback.getSubsystemLowPowerStats();
3275                 if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
3276                         mCurHistoryStepDetails.statSubsystemPowerState);
3277
3278             }
3279             computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
3280             if (includeStepDetails != 0) {
3281                 mCurHistoryStepDetails.writeToParcel(dest);
3282             }
3283             cur.stepDetails = mCurHistoryStepDetails;
3284             mLastHistoryStepDetails = mCurHistoryStepDetails;
3285         } else {
3286             cur.stepDetails = null;
3287         }
3288         if (mLastHistoryStepLevel < cur.batteryLevel) {
3289             mLastHistoryStepDetails = null;
3290         }
3291         mLastHistoryStepLevel = cur.batteryLevel;
3292
3293         if (batteryChargeChanged) {
3294             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
3295             dest.writeInt(cur.batteryChargeUAh);
3296         }
3297     }
3298
3299     private int buildBatteryLevelInt(HistoryItem h) {
3300         return ((((int)h.batteryLevel)<<25)&0xfe000000)
3301                 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
3302                 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
3303     }
3304
3305     private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
3306         out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
3307         out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
3308         out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
3309     }
3310
3311     private int buildStateInt(HistoryItem h) {
3312         int plugType = 0;
3313         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
3314             plugType = 1;
3315         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
3316             plugType = 2;
3317         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
3318             plugType = 3;
3319         }
3320         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
3321                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
3322                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
3323                 | (h.states&(~STATE_BATTERY_MASK));
3324     }
3325
3326     private void computeHistoryStepDetails(final HistoryStepDetails out,
3327             final HistoryStepDetails last) {
3328         final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
3329
3330         // Perform a CPU update right after we do this collection, so we have started
3331         // collecting good data for the next step.
3332         requestImmediateCpuUpdate();
3333
3334         if (last == null) {
3335             // We are not generating a delta, so all we need to do is reset the stats
3336             // we will later be doing a delta from.
3337             final int NU = mUidStats.size();
3338             for (int i=0; i<NU; i++) {
3339                 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3340                 uid.mLastStepUserTime = uid.mCurStepUserTime;
3341                 uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3342             }
3343             mLastStepCpuUserTime = mCurStepCpuUserTime;
3344             mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3345             mLastStepStatUserTime = mCurStepStatUserTime;
3346             mLastStepStatSystemTime = mCurStepStatSystemTime;
3347             mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3348             mLastStepStatIrqTime = mCurStepStatIrqTime;
3349             mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3350             mLastStepStatIdleTime = mCurStepStatIdleTime;
3351             tmp.clear();
3352             return;
3353         }
3354         if (DEBUG) {
3355             Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
3356                     + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
3357                     + " irq=" + mLastStepStatIrqTime + " sirq="
3358                     + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
3359             Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
3360                     + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
3361                     + " irq=" + mCurStepStatIrqTime + " sirq="
3362                     + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
3363         }
3364         out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
3365         out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
3366         out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
3367         out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
3368         out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
3369         out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
3370         out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
3371         out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
3372         out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
3373         out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
3374         out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
3375         final int NU = mUidStats.size();
3376         for (int i=0; i<NU; i++) {
3377             final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3378             final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
3379             final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
3380             final int totalTime = totalUTime + totalSTime;
3381             uid.mLastStepUserTime = uid.mCurStepUserTime;
3382             uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3383             if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
3384                 continue;
3385             }
3386             if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
3387                 out.appCpuUid3 = uid.mUid;
3388                 out.appCpuUTime3 = totalUTime;
3389                 out.appCpuSTime3 = totalSTime;
3390             } else {
3391                 out.appCpuUid3 = out.appCpuUid2;
3392                 out.appCpuUTime3 = out.appCpuUTime2;
3393                 out.appCpuSTime3 = out.appCpuSTime2;
3394                 if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
3395                     out.appCpuUid2 = uid.mUid;
3396                     out.appCpuUTime2 = totalUTime;
3397                     out.appCpuSTime2 = totalSTime;
3398                 } else {
3399                     out.appCpuUid2 = out.appCpuUid1;
3400                     out.appCpuUTime2 = out.appCpuUTime1;
3401                     out.appCpuSTime2 = out.appCpuSTime1;
3402                     out.appCpuUid1 = uid.mUid;
3403                     out.appCpuUTime1 = totalUTime;
3404                     out.appCpuSTime1 = totalSTime;
3405                 }
3406             }
3407         }
3408         mLastStepCpuUserTime = mCurStepCpuUserTime;
3409         mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3410         mLastStepStatUserTime = mCurStepStatUserTime;
3411         mLastStepStatSystemTime = mCurStepStatSystemTime;
3412         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3413         mLastStepStatIrqTime = mCurStepStatIrqTime;
3414         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3415         mLastStepStatIdleTime = mCurStepStatIdleTime;
3416     }
3417
3418     public void readHistoryDelta(Parcel src, HistoryItem cur) {
3419         int firstToken = src.readInt();
3420         int deltaTimeToken = firstToken&DELTA_TIME_MASK;
3421         cur.cmd = HistoryItem.CMD_UPDATE;
3422         cur.numReadInts = 1;
3423         if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3424                 + " deltaTimeToken=" + deltaTimeToken);
3425
3426         if (deltaTimeToken < DELTA_TIME_ABS) {
3427             cur.time += deltaTimeToken;
3428         } else if (deltaTimeToken == DELTA_TIME_ABS) {
3429             cur.time = src.readLong();
3430             cur.numReadInts += 2;
3431             if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
3432             cur.readFromParcel(src);
3433             return;
3434         } else if (deltaTimeToken == DELTA_TIME_INT) {
3435             int delta = src.readInt();
3436             cur.time += delta;
3437             cur.numReadInts += 1;
3438             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3439         } else {
3440             long delta = src.readLong();
3441             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3442             cur.time += delta;
3443             cur.numReadInts += 2;
3444         }
3445
3446         final int batteryLevelInt;
3447         if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
3448             batteryLevelInt = src.readInt();
3449             readBatteryLevelInt(batteryLevelInt, cur);
3450             cur.numReadInts += 1;
3451             if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
3452                     + Integer.toHexString(batteryLevelInt)
3453                     + " batteryLevel=" + cur.batteryLevel
3454                     + " batteryTemp=" + cur.batteryTemperature
3455                     + " batteryVolt=" + (int)cur.batteryVoltage);
3456         } else {
3457             batteryLevelInt = 0;
3458         }
3459
3460         if ((firstToken&DELTA_STATE_FLAG) != 0) {
3461             int stateInt = src.readInt();
3462             cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
3463             cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
3464                     & STATE_BATTERY_STATUS_MASK);
3465             cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
3466                     & STATE_BATTERY_HEALTH_MASK);
3467             cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
3468                     & STATE_BATTERY_PLUG_MASK);
3469             switch (cur.batteryPlugType) {
3470                 case 1:
3471                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
3472                     break;
3473                 case 2:
3474                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
3475                     break;
3476                 case 3:
3477                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
3478                     break;
3479             }
3480             cur.numReadInts += 1;
3481             if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
3482                     + Integer.toHexString(stateInt)
3483                     + " batteryStatus=" + cur.batteryStatus
3484                     + " batteryHealth=" + cur.batteryHealth
3485                     + " batteryPlugType=" + cur.batteryPlugType
3486                     + " states=0x" + Integer.toHexString(cur.states));
3487         } else {
3488             cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
3489         }
3490
3491         if ((firstToken&DELTA_STATE2_FLAG) != 0) {
3492             cur.states2 = src.readInt();
3493             if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
3494                     + Integer.toHexString(cur.states2));
3495         }
3496
3497         if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
3498             int indexes = src.readInt();
3499             int wakeLockIndex = indexes&0xffff;
3500             int wakeReasonIndex = (indexes>>16)&0xffff;
3501             if (wakeLockIndex != 0xffff) {
3502                 cur.wakelockTag = cur.localWakelockTag;
3503                 readHistoryTag(wakeLockIndex, cur.wakelockTag);
3504                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3505                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3506             } else {
3507                 cur.wakelockTag = null;
3508             }
3509             if (wakeReasonIndex != 0xffff) {
3510                 cur.wakeReasonTag = cur.localWakeReasonTag;
3511                 readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
3512                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3513                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3514             } else {
3515                 cur.wakeReasonTag = null;
3516             }
3517             cur.numReadInts += 1;
3518         } else {
3519             cur.wakelockTag = null;
3520             cur.wakeReasonTag = null;
3521         }
3522
3523         if ((firstToken&DELTA_EVENT_FLAG) != 0) {
3524             cur.eventTag = cur.localEventTag;
3525             final int codeAndIndex = src.readInt();
3526             cur.eventCode = (codeAndIndex&0xffff);
3527             final int index = ((codeAndIndex>>16)&0xffff);
3528             readHistoryTag(index, cur.eventTag);
3529             cur.numReadInts += 1;
3530             if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
3531                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3532                     + cur.eventTag.string);
3533         } else {
3534             cur.eventCode = HistoryItem.EVENT_NONE;
3535         }
3536
3537         if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
3538             cur.stepDetails = mReadHistoryStepDetails;
3539             cur.stepDetails.readFromParcel(src);
3540         } else {
3541             cur.stepDetails = null;
3542         }
3543
3544         if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
3545             cur.batteryChargeUAh = src.readInt();
3546         }
3547     }
3548
3549     @Override
3550     public void commitCurrentHistoryBatchLocked() {
3551         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
3552     }
3553
3554     void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) {
3555         if (!mHaveBatteryLevel || !mRecordingHistory) {
3556             return;
3557         }
3558
3559         final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
3560         final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
3561         final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
3562         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
3563         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
3564         if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
3565                 + Integer.toHexString(diffStates) + " lastDiff="
3566                 + Integer.toHexString(lastDiffStates) + " diff2="
3567                 + Integer.toHexString(diffStates2) + " lastDiff2="
3568                 + Integer.toHexString(lastDiffStates2));
3569         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
3570                 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
3571                 && (diffStates2&lastDiffStates2) == 0
3572                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
3573                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
3574                 && mHistoryLastWritten.stepDetails == null
3575                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
3576                         || cur.eventCode == HistoryItem.EVENT_NONE)
3577                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
3578                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
3579                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
3580                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
3581                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
3582                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
3583             // We can merge this new change in with the last one.  Merging is
3584             // allowed as long as only the states have changed, and within those states
3585             // as long as no bit has changed both between now and the last entry, as
3586             // well as the last entry and the one before it (so we capture any toggles).
3587             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
3588             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
3589             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
3590             mHistoryBufferLastPos = -1;
3591             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
3592             // If the last written history had a wakelock tag, we need to retain it.
3593             // Note that the condition above made sure that we aren't in a case where
3594             // both it and the current history item have a wakelock tag.
3595             if (mHistoryLastWritten.wakelockTag != null) {
3596                 cur.wakelockTag = cur.localWakelockTag;
3597                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
3598             }
3599             // If the last written history had a wake reason tag, we need to retain it.
3600             // Note that the condition above made sure that we aren't in a case where
3601             // both it and the current history item have a wakelock tag.
3602             if (mHistoryLastWritten.wakeReasonTag != null) {
3603                 cur.wakeReasonTag = cur.localWakeReasonTag;
3604                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
3605             }
3606             // If the last written history had an event, we need to retain it.
3607             // Note that the condition above made sure that we aren't in a case where
3608             // both it and the current history item have an event.
3609             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
3610                 cur.eventCode = mHistoryLastWritten.eventCode;
3611                 cur.eventTag = cur.localEventTag;
3612                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
3613             }
3614             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
3615         }
3616
3617         boolean recordResetDueToOverflow = false;
3618         final int dataSize = mHistoryBuffer.dataSize();
3619         if (dataSize >= MAX_MAX_HISTORY_BUFFER*3) {
3620             // Clients can't deal with history buffers this large. This only
3621             // really happens when the device is on charger and interacted with
3622             // for long periods of time, like in retail mode. Since the device is
3623             // most likely charged, when unplugged, stats would have reset anyways.
3624             // Reset the stats and mark that we overflowed.
3625             // b/32540341
3626             resetAllStatsLocked();
3627
3628             // Mark that we want to set *OVERFLOW* event and the RESET:START
3629             // events.
3630             recordResetDueToOverflow = true;
3631
3632         } else if (dataSize >= MAX_HISTORY_BUFFER) {
3633             if (!mHistoryOverflow) {
3634                 mHistoryOverflow = true;
3635                 addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3636                 addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
3637                 return;
3638             }
3639
3640             // After overflow, we allow various bit-wise states to settle to 0.
3641             boolean writeAnyway = false;
3642             final int curStates = cur.states & HistoryItem.SETTLE_TO_ZERO_STATES
3643                     & mActiveHistoryStates;
3644             if (mHistoryLastWritten.states != curStates) {
3645                 // mActiveHistoryStates keeps track of which bits in .states are now being
3646                 // forced to 0.
3647                 int old = mActiveHistoryStates;
3648                 mActiveHistoryStates &= curStates | ~HistoryItem.SETTLE_TO_ZERO_STATES;
3649                 writeAnyway |= old != mActiveHistoryStates;
3650             }
3651             final int curStates2 = cur.states2 & HistoryItem.SETTLE_TO_ZERO_STATES2
3652                     & mActiveHistoryStates2;
3653             if (mHistoryLastWritten.states2 != curStates2) {
3654                 // mActiveHistoryStates2 keeps track of which bits in .states2 are now being
3655                 // forced to 0.
3656                 int old = mActiveHistoryStates2;
3657                 mActiveHistoryStates2 &= curStates2 | ~HistoryItem.SETTLE_TO_ZERO_STATES2;
3658                 writeAnyway |= old != mActiveHistoryStates2;
3659             }
3660
3661             // Once we've reached the maximum number of items, we only
3662             // record changes to the battery level and the most interesting states.
3663             // Once we've reached the maximum maximum number of items, we only
3664             // record changes to the battery level.
3665             if (!writeAnyway && mHistoryLastWritten.batteryLevel == cur.batteryLevel &&
3666                     (dataSize >= MAX_MAX_HISTORY_BUFFER
3667                             || ((mHistoryLastWritten.states^cur.states)
3668                                     & HistoryItem.MOST_INTERESTING_STATES) == 0
3669                             || ((mHistoryLastWritten.states2^cur.states2)
3670                                     & HistoryItem.MOST_INTERESTING_STATES2) == 0)) {
3671                 return;
3672             }
3673
3674             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3675             return;
3676         }
3677
3678         if (dataSize == 0 || recordResetDueToOverflow) {
3679             // The history is currently empty; we need it to start with a time stamp.
3680             cur.currentTime = System.currentTimeMillis();
3681             if (recordResetDueToOverflow) {
3682                 addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
3683             }
3684             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
3685         }
3686         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3687     }
3688
3689     private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
3690         if (mIteratingHistory) {
3691             throw new IllegalStateException("Can't do this while iterating history!");
3692         }
3693         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
3694         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
3695         mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3696         mHistoryLastWritten.states &= mActiveHistoryStates;
3697         mHistoryLastWritten.states2 &= mActiveHistoryStates2;
3698         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
3699         mLastHistoryElapsedRealtime = elapsedRealtimeMs;
3700         cur.wakelockTag = null;
3701         cur.wakeReasonTag = null;
3702         cur.eventCode = HistoryItem.EVENT_NONE;
3703         cur.eventTag = null;
3704         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
3705                 + " now " + mHistoryBuffer.dataPosition()
3706                 + " size is now " + mHistoryBuffer.dataSize());
3707     }
3708
3709     int mChangedStates = 0;
3710     int mChangedStates2 = 0;
3711
3712     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
3713         if (mTrackRunningHistoryElapsedRealtime != 0) {
3714             final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
3715             final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
3716             if (diffUptime < (diffElapsed-20)) {
3717                 final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
3718                 mHistoryAddTmp.setTo(mHistoryLastWritten);
3719                 mHistoryAddTmp.wakelockTag = null;
3720                 mHistoryAddTmp.wakeReasonTag = null;
3721                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
3722                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
3723                 addHistoryRecordInnerLocked(wakeElapsedTime, mHistoryAddTmp);
3724             }
3725         }
3726         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
3727         mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
3728         mTrackRunningHistoryUptime = uptimeMs;
3729         addHistoryRecordInnerLocked(elapsedRealtimeMs, mHistoryCur);
3730     }
3731
3732     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur) {
3733         addHistoryBufferLocked(elapsedRealtimeMs, cur);
3734
3735         if (!USE_OLD_HISTORY) {
3736             return;
3737         }
3738
3739         if (!mHaveBatteryLevel || !mRecordingHistory) {
3740             return;
3741         }
3742
3743         // If the current time is basically the same as the last time,
3744         // and no states have since the last recorded entry changed and
3745         // are now resetting back to their original value, then just collapse
3746         // into one record.
3747         if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
3748                 && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
3749                 && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
3750                 && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
3751             // If the current is the same as the one before, then we no
3752             // longer need the entry.
3753             if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
3754                     && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
3755                     && mHistoryLastEnd.sameNonEvent(cur)) {
3756                 mHistoryLastEnd.next = null;
3757                 mHistoryEnd.next = mHistoryCache;
3758                 mHistoryCache = mHistoryEnd;
3759                 mHistoryEnd = mHistoryLastEnd;
3760                 mHistoryLastEnd = null;
3761             } else {
3762                 mChangedStates |= mHistoryEnd.states^(cur.states&mActiveHistoryStates);
3763                 mChangedStates2 |= mHistoryEnd.states^(cur.states2&mActiveHistoryStates2);
3764                 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
3765             }
3766             return;
3767         }
3768
3769         mChangedStates = 0;
3770         mChangedStates2 = 0;
3771
3772         if (mNumHistoryItems == MAX_HISTORY_ITEMS
3773                 || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
3774             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
3775         }
3776
3777         if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
3778             // Once we've reached the maximum number of items, we only
3779             // record changes to the battery level and the most interesting states.
3780             // Once we've reached the maximum maximum number of items, we only
3781             // record changes to the battery level.
3782             if (mHistoryEnd != null && mHistoryEnd.batteryLevel
3783                     == cur.batteryLevel &&
3784                     (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
3785                             || ((mHistoryEnd.states^(cur.states&mActiveHistoryStates))
3786                                     & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
3787                 return;
3788             }
3789         }
3790
3791         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3792     }
3793
3794     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
3795             String name, int uid) {
3796         mHistoryCur.eventCode = code;
3797         mHistoryCur.eventTag = mHistoryCur.localEventTag;
3798         mHistoryCur.eventTag.string = name;
3799         mHistoryCur.eventTag.uid = uid;
3800         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
3801     }
3802
3803     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
3804         HistoryItem rec = mHistoryCache;
3805         if (rec != null) {
3806             mHistoryCache = rec.next;
3807         } else {
3808             rec = new HistoryItem();
3809         }
3810         rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3811
3812         addHistoryRecordLocked(rec);
3813     }
3814
3815     void addHistoryRecordLocked(HistoryItem rec) {
3816         mNumHistoryItems++;
3817         rec.next = null;
3818         mHistoryLastEnd = mHistoryEnd;
3819         if (mHistoryEnd != null) {
3820             mHistoryEnd.next = rec;
3821             mHistoryEnd = rec;
3822         } else {
3823             mHistory = mHistoryEnd = rec;
3824         }
3825     }
3826
3827     void clearHistoryLocked() {
3828         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
3829         if (USE_OLD_HISTORY) {
3830             if (mHistory != null) {
3831                 mHistoryEnd.next = mHistoryCache;
3832                 mHistoryCache = mHistory;
3833                 mHistory = mHistoryLastEnd = mHistoryEnd = null;
3834             }
3835             mNumHistoryItems = 0;
3836         }
3837
3838         mHistoryBaseTime = 0;
3839         mLastHistoryElapsedRealtime = 0;
3840         mTrackRunningHistoryElapsedRealtime = 0;
3841         mTrackRunningHistoryUptime = 0;
3842
3843         mHistoryBuffer.setDataSize(0);
3844         mHistoryBuffer.setDataPosition(0);
3845         mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER / 2);
3846         mHistoryLastLastWritten.clear();
3847         mHistoryLastWritten.clear();
3848         mHistoryTagPool.clear();
3849         mNextHistoryTagIdx = 0;
3850         mNumHistoryTagChars = 0;
3851         mHistoryBufferLastPos = -1;
3852         mHistoryOverflow = false;
3853         mActiveHistoryStates = 0xffffffff;
3854         mActiveHistoryStates2 = 0xffffffff;
3855     }
3856
3857     @GuardedBy("this")
3858     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
3859             long realtime) {
3860         final boolean screenOff = !isScreenOn(screenState);
3861         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
3862         final boolean updateOnBatteryScreenOffTimeBase =
3863                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
3864
3865         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
3866             if (updateOnBatteryScreenOffTimeBase) {
3867                 updateKernelWakelocksLocked();
3868                 updateBatteryPropertiesLocked();
3869             }
3870             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
3871             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
3872             // improved, remove the surrounding if{}.
3873             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
3874                 updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes.
3875             }
3876             if (DEBUG_ENERGY_CPU) {
3877                 Slog.d(TAG, "Updating cpu time because screen is now "
3878                         + Display.stateToString(screenState)
3879                         + " and battery is " + (unplugged ? "on" : "off"));
3880             }
3881
3882             mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
3883             if (updateOnBatteryTimeBase) {
3884                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3885                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime);
3886                 }
3887             }
3888             if (updateOnBatteryScreenOffTimeBase) {
3889                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, uptime, realtime);
3890                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3891                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime);
3892                 }
3893             }
3894         }
3895     }
3896
3897     private void updateBatteryPropertiesLocked() {
3898         try {
3899             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
3900                     ServiceManager.getService("batteryproperties"));
3901             registrar.scheduleUpdate();
3902         } catch (RemoteException e) {
3903             // Ignore.
3904         }
3905     }
3906
3907     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
3908         mIsolatedUids.put(isolatedUid, appUid);
3909         StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, appUid, isolatedUid,
3910                 StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
3911         final Uid u = getUidStatsLocked(appUid);
3912         u.addIsolatedUid(isolatedUid);
3913     }
3914
3915     /**
3916      * Schedules a read of the latest cpu times before removing the isolated UID.
3917      * @see #removeIsolatedUidLocked(int)
3918      */
3919     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
3920         int curUid = mIsolatedUids.get(isolatedUid, -1);
3921         if (curUid == appUid) {
3922             if (mExternalSync != null) {
3923                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
3924             }
3925         }
3926     }
3927
3928     /**
3929      * This should only be called after the cpu times have been read.
3930      * @see #scheduleRemoveIsolatedUidLocked(int, int)
3931      */
3932     @GuardedBy("this")
3933     public void removeIsolatedUidLocked(int isolatedUid) {
3934         StatsLog.write(
3935                 StatsLog.ISOLATED_UID_CHANGED, mIsolatedUids.get(isolatedUid, -1),
3936                 isolatedUid, StatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED);
3937         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
3938         if (idx >= 0) {
3939             final int ownerUid = mIsolatedUids.valueAt(idx);
3940             final Uid u = getUidStatsLocked(ownerUid);
3941             u.removeIsolatedUid(isolatedUid);
3942             mIsolatedUids.removeAt(idx);
3943         }
3944         mKernelUidCpuTimeReader.removeUid(isolatedUid);
3945         mKernelUidCpuFreqTimeReader.removeUid(isolatedUid);
3946         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
3947             mKernelUidCpuActiveTimeReader.removeUid(isolatedUid);
3948             mKernelUidCpuClusterTimeReader.removeUid(isolatedUid);
3949         }
3950     }
3951
3952     public int mapUid(int uid) {
3953         int isolated = mIsolatedUids.get(uid, -1);
3954         return isolated > 0 ? isolated : uid;
3955     }
3956
3957     public void noteEventLocked(int code, String name, int uid) {
3958         uid = mapUid(uid);
3959         if (!mActiveEvents.updateState(code, name, uid, 0)) {
3960             return;
3961         }
3962         final long elapsedRealtime = mClocks.elapsedRealtime();
3963         final long uptime = mClocks.uptimeMillis();
3964         addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
3965     }
3966
3967     boolean ensureStartClockTime(final long currentTime) {
3968         final long ABOUT_ONE_YEAR = 365*24*60*60*1000L;
3969         if (currentTime > ABOUT_ONE_YEAR && mStartClockTime < (currentTime-ABOUT_ONE_YEAR)) {
3970             // If the start clock time has changed by more than a year, then presumably
3971             // the previous time was completely bogus.  So we are going to figure out a
3972             // new time based on how much time has elapsed since we started counting.
3973             mStartClockTime = currentTime - (mClocks.elapsedRealtime()-(mRealtimeStart/1000));
3974             return true;
3975         }
3976         return false;
3977     }
3978
3979     public void noteCurrentTimeChangedLocked() {
3980         final long currentTime = System.currentTimeMillis();
3981         final long elapsedRealtime = mClocks.elapsedRealtime();
3982         final long uptime = mClocks.uptimeMillis();
3983         recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
3984         ensureStartClockTime(currentTime);
3985     }
3986
3987     public void noteProcessStartLocked(String name, int uid) {
3988         uid = mapUid(uid);
3989         if (isOnBattery()) {
3990             Uid u = getUidStatsLocked(uid);
3991             u.getProcessStatsLocked(name).incStartsLocked();
3992         }
3993         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
3994             return;
3995         }
3996         if (!mRecordAllHistory) {
3997             return;
3998         }
3999         final long elapsedRealtime = mClocks.elapsedRealtime();
4000         final long uptime = mClocks.uptimeMillis();
4001         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
4002     }
4003
4004     public void noteProcessCrashLocked(String name, int uid) {
4005         uid = mapUid(uid);
4006         if (isOnBattery()) {
4007             Uid u = getUidStatsLocked(uid);
4008             u.getProcessStatsLocked(name).incNumCrashesLocked();
4009         }
4010     }
4011
4012     public void noteProcessAnrLocked(String name, int uid) {
4013         uid = mapUid(uid);
4014         if (isOnBattery()) {
4015             Uid u = getUidStatsLocked(uid);
4016             u.getProcessStatsLocked(name).incNumAnrsLocked();
4017         }
4018     }
4019
4020     public void noteUidProcessStateLocked(int uid, int state) {
4021         int parentUid = mapUid(uid);
4022         if (uid != parentUid) {
4023             // Isolated UIDs process state is already rolled up into parent, so no need to track
4024             // Otherwise the parent's process state will get downgraded incorrectly
4025             return;
4026         }
4027         getUidStatsLocked(uid).updateUidProcessStateLocked(state);
4028     }
4029
4030     public void noteProcessFinishLocked(String name, int uid) {
4031         uid = mapUid(uid);
4032         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4033             return;
4034         }
4035         if (!mRecordAllHistory) {
4036             return;
4037         }
4038         final long elapsedRealtime = mClocks.elapsedRealtime();
4039         final long uptime = mClocks.uptimeMillis();
4040         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
4041     }
4042
4043     public void noteSyncStartLocked(String name, int uid) {
4044         uid = mapUid(uid);
4045         final long elapsedRealtime = mClocks.elapsedRealtime();
4046         final long uptime = mClocks.uptimeMillis();
4047         getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
4048         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4049             return;
4050         }
4051         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
4052     }
4053
4054     public void noteSyncFinishLocked(String name, int uid) {
4055         uid = mapUid(uid);
4056         final long elapsedRealtime = mClocks.elapsedRealtime();
4057         final long uptime = mClocks.uptimeMillis();
4058         getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
4059         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4060             return;
4061         }
4062         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
4063     }
4064
4065     public void noteJobStartLocked(String name, int uid) {
4066         uid = mapUid(uid);
4067         final long elapsedRealtime = mClocks.elapsedRealtime();
4068         final long uptime = mClocks.uptimeMillis();
4069         getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
4070         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4071             return;
4072         }
4073         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
4074     }
4075
4076     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4077         uid = mapUid(uid);
4078         final long elapsedRealtime = mClocks.elapsedRealtime();
4079         final long uptime = mClocks.uptimeMillis();
4080         getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason);
4081         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4082             return;
4083         }
4084         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
4085     }
4086
4087     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
4088         uid = mapUid(uid);
4089         getUidStatsLocked(uid).noteJobsDeferredLocked(numDeferred, sinceLast);
4090     }
4091
4092     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4093         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid);
4094     }
4095
4096     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4097         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid);
4098     }
4099
4100     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4101             int uid) {
4102         if (!mRecordAllHistory) {
4103             return;
4104         }
4105
4106         final long elapsedRealtime = mClocks.elapsedRealtime();
4107         final long uptime = mClocks.uptimeMillis();
4108
4109         if (workSource != null) {
4110             for (int i = 0; i < workSource.size(); ++i) {
4111                 uid = mapUid(workSource.get(i));
4112                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4113                     addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4114                 }
4115             }
4116
4117             List<WorkChain> workChains = workSource.getWorkChains();
4118             if (workChains != null) {
4119                 for (int i = 0; i < workChains.size(); ++i) {
4120                     uid = mapUid(workChains.get(i).getAttributionUid());
4121                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4122                         addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4123                     }
4124                 }
4125             }
4126         } else {
4127             uid = mapUid(uid);
4128
4129             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4130                 addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4131             }
4132         }
4133     }
4134
4135     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4136             String tag) {
4137         if (workSource != null) {
4138             for (int i = 0; i < workSource.size(); ++i) {
4139                 uid = workSource.get(i);
4140                 final String workSourceName = workSource.getName(i);
4141
4142                 if (isOnBattery()) {
4143                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4144                             workSourceName != null ? workSourceName : packageName);
4145                     pkg.noteWakeupAlarmLocked(tag);
4146                 }
4147                 StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, workSource.get(i),
4148                         workSource.getName(i), tag);
4149             }
4150
4151             ArrayList<WorkChain> workChains = workSource.getWorkChains();
4152             if (workChains != null) {
4153                 for (int i = 0; i < workChains.size(); ++i) {
4154                     final WorkChain wc = workChains.get(i);
4155                     uid = wc.getAttributionUid();
4156
4157                     if (isOnBattery()) {
4158                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4159                         pkg.noteWakeupAlarmLocked(tag);
4160                     }
4161                     StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, wc.getUids(), wc.getTags(), tag);
4162                 }
4163             }
4164         } else {
4165             if (isOnBattery()) {
4166                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4167                 pkg.noteWakeupAlarmLocked(tag);
4168             }
4169             StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, uid, null, tag);
4170         }
4171     }
4172
4173     private void requestWakelockCpuUpdate() {
4174         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4175     }
4176
4177     private void requestImmediateCpuUpdate() {
4178         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4179     }
4180
4181     public void setRecordAllHistoryLocked(boolean enabled) {
4182         mRecordAllHistory = enabled;
4183         if (!enabled) {
4184             // Clear out any existing state.
4185             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4186             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4187             // Record the currently running processes as stopping, now that we are no
4188             // longer tracking them.
4189             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4190                     HistoryItem.EVENT_PROC);
4191             if (active != null) {
4192                 long mSecRealtime = mClocks.elapsedRealtime();
4193                 final long mSecUptime = mClocks.uptimeMillis();
4194                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4195                     SparseIntArray uids = ent.getValue();
4196                     for (int j=0; j<uids.size(); j++) {
4197                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4198                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4199                     }
4200                 }
4201             }
4202         } else {
4203             // Record the currently running processes as starting, now that we are tracking them.
4204             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4205                     HistoryItem.EVENT_PROC);
4206             if (active != null) {
4207                 long mSecRealtime = mClocks.elapsedRealtime();
4208                 final long mSecUptime = mClocks.uptimeMillis();
4209                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4210                     SparseIntArray uids = ent.getValue();
4211                     for (int j=0; j<uids.size(); j++) {
4212                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4213                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
4214                     }
4215                 }
4216             }
4217         }
4218     }
4219
4220     public void setNoAutoReset(boolean enabled) {
4221         mNoAutoReset = enabled;
4222     }
4223
4224     public void setPretendScreenOff(boolean pretendScreenOff) {
4225         if (mPretendScreenOff != pretendScreenOff) {
4226             mPretendScreenOff = pretendScreenOff;
4227             noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON);
4228         }
4229     }
4230
4231     private String mInitialAcquireWakeName;
4232     private int mInitialAcquireWakeUid = -1;
4233
4234     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4235         int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) {
4236         uid = mapUid(uid);
4237         if (type == WAKE_TYPE_PARTIAL) {
4238             // Only care about partial wake locks, since full wake locks
4239             // will be canceled when the user puts the screen to sleep.
4240             aggregateLastWakeupUptimeLocked(uptime);
4241             if (historyName == null) {
4242                 historyName = name;
4243             }
4244             if (mRecordAllHistory) {
4245                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
4246                         uid, 0)) {
4247                     addHistoryEventLocked(elapsedRealtime, uptime,
4248                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
4249                 }
4250             }
4251             if (mWakeLockNesting == 0) {
4252                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
4253                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
4254                         + Integer.toHexString(mHistoryCur.states));
4255                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4256                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4257                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4258                 mWakeLockImportant = !unimportantForLogging;
4259                 addHistoryRecordLocked(elapsedRealtime, uptime);
4260             } else if (!mWakeLockImportant && !unimportantForLogging
4261                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
4262                 if (mHistoryLastWritten.wakelockTag != null) {
4263                     // We'll try to update the last tag.
4264                     mHistoryLastWritten.wakelockTag = null;
4265                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4266                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4267                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4268                     addHistoryRecordLocked(elapsedRealtime, uptime);
4269                 }
4270                 mWakeLockImportant = true;
4271             }
4272             mWakeLockNesting++;
4273         }
4274         if (uid >= 0) {
4275             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4276                 // We only update the cpu time when a wake lock is acquired if the screen is off.
4277                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
4278                 if (DEBUG_ENERGY_CPU) {
4279                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
4280                 }
4281                 requestWakelockCpuUpdate();
4282             }
4283
4284             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
4285
4286             if (wc != null) {
4287                 StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
4288                         getPowerManagerWakeLockLevel(type), name,
4289                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4290             } else {
4291                 StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
4292                         getPowerManagerWakeLockLevel(type), name,
4293                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4294             }
4295         }
4296     }
4297
4298     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4299             int type, long elapsedRealtime, long uptime) {
4300         uid = mapUid(uid);
4301         if (type == WAKE_TYPE_PARTIAL) {
4302             mWakeLockNesting--;
4303             if (mRecordAllHistory) {
4304                 if (historyName == null) {
4305                     historyName = name;
4306                 }
4307                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
4308                         uid, 0)) {
4309                     addHistoryEventLocked(elapsedRealtime, uptime,
4310                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
4311                 }
4312             }
4313             if (mWakeLockNesting == 0) {
4314                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
4315                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
4316                         + Integer.toHexString(mHistoryCur.states));
4317                 mInitialAcquireWakeName = null;
4318                 mInitialAcquireWakeUid = -1;
4319                 addHistoryRecordLocked(elapsedRealtime, uptime);
4320             }
4321         }
4322         if (uid >= 0) {
4323             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4324                 if (DEBUG_ENERGY_CPU) {
4325                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
4326                 }
4327                 requestWakelockCpuUpdate();
4328             }
4329
4330             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
4331             if (wc != null) {
4332                 StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
4333                         getPowerManagerWakeLockLevel(type), name,
4334                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4335             } else {
4336                 StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
4337                         getPowerManagerWakeLockLevel(type), name,
4338                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4339             }
4340         }
4341     }
4342
4343     /**
4344      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
4345      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
4346      * These are estimations, since batterystats loses some of the original data.
4347      * TODO: Delete this. Instead, StatsLog.write should be called from PowerManager's Notifier.
4348      */
4349     private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
4350         switch (battertStatsWakelockType) {
4351             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
4352             case BatteryStats.WAKE_TYPE_PARTIAL:
4353                 return PowerManager.PARTIAL_WAKE_LOCK;
4354
4355             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
4356             case BatteryStats.WAKE_TYPE_FULL:
4357                 return PowerManager.FULL_WAKE_LOCK;
4358
4359             case BatteryStats.WAKE_TYPE_DRAW:
4360                 return PowerManager.DRAW_WAKE_LOCK;
4361
4362             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
4363             case BatteryStats.WAKE_TYPE_WINDOW:
4364                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
4365                 return -1;
4366
4367             default:
4368                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
4369                 return -1;
4370         }
4371     }
4372
4373     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4374             String historyName, int type, boolean unimportantForLogging) {
4375         final long elapsedRealtime = mClocks.elapsedRealtime();
4376         final long uptime = mClocks.uptimeMillis();
4377         final int N = ws.size();
4378         for (int i=0; i<N; i++) {
4379             noteStartWakeLocked(ws.get(i), pid, null, name, historyName, type,
4380                     unimportantForLogging, elapsedRealtime, uptime);
4381         }
4382
4383         List<WorkChain> wcs = ws.getWorkChains();
4384         if (wcs != null) {
4385             for (int i = 0; i < wcs.size(); ++i) {
4386                 final WorkChain wc = wcs.get(i);
4387                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4388                         unimportantForLogging, elapsedRealtime, uptime);
4389             }
4390         }
4391     }
4392
4393     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4394             String historyName, int type, WorkSource newWs, int newPid, String newName,
4395             String newHistoryName, int newType, boolean newUnimportantForLogging) {
4396         final long elapsedRealtime = mClocks.elapsedRealtime();
4397         final long uptime = mClocks.uptimeMillis();
4398
4399         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
4400
4401         // For correct semantics, we start the need worksources first, so that we won't
4402         // make inappropriate history items as if all wake locks went away and new ones
4403         // appeared.  This is okay because tracking of wake locks allows nesting.
4404         //
4405         // First the starts :
4406         final int NN = newWs.size();
4407         for (int i=0; i<NN; i++) {
4408             noteStartWakeLocked(newWs.get(i), newPid, null, newName, newHistoryName, newType,
4409                     newUnimportantForLogging, elapsedRealtime, uptime);
4410         }
4411         if (wcs != null) {
4412             List<WorkChain> newChains = wcs[0];
4413             if (newChains != null) {
4414                 for (int i = 0; i < newChains.size(); ++i) {
4415                     final WorkChain newChain = newChains.get(i);
4416                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
4417                         newHistoryName, newType, newUnimportantForLogging, elapsedRealtime,
4418                         uptime);
4419                 }
4420             }
4421         }
4422
4423         // Then the stops :
4424         final int NO = ws.size();
4425         for (int i=0; i<NO; i++) {
4426             noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
4427                     uptime);
4428         }
4429         if (wcs != null) {
4430             List<WorkChain> goneChains = wcs[1];
4431             if (goneChains != null) {
4432                 for (int i = 0; i < goneChains.size(); ++i) {
4433                     final WorkChain goneChain = goneChains.get(i);
4434                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
4435                             historyName, type, elapsedRealtime, uptime);
4436                 }
4437             }
4438         }
4439     }
4440
4441     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4442             String historyName, int type) {
4443         final long elapsedRealtime = mClocks.elapsedRealtime();
4444         final long uptime = mClocks.uptimeMillis();
4445         final int N = ws.size();
4446         for (int i=0; i<N; i++) {
4447             noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
4448                     uptime);
4449         }
4450
4451         List<WorkChain> wcs = ws.getWorkChains();
4452         if (wcs != null) {
4453             for (int i = 0; i < wcs.size(); ++i) {
4454                 final WorkChain wc = wcs.get(i);
4455                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4456                         elapsedRealtime, uptime);
4457             }
4458         }
4459     }
4460
4461     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
4462         StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4463                 uid, null, name, historyName,
4464                 StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
4465
4466         uid = mapUid(uid);
4467         noteLongPartialWakeLockStartInternal(name, historyName, uid);
4468     }
4469
4470     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4471             WorkSource workSource) {
4472         final int N = workSource.size();
4473         for (int i = 0; i < N; ++i) {
4474             final int uid = mapUid(workSource.get(i));
4475             noteLongPartialWakeLockStartInternal(name, historyName, uid);
4476             StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4477                     workSource.get(i), workSource.getName(i), name, historyName,
4478                     StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
4479         }
4480
4481         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
4482         if (workChains != null) {
4483             for (int i = 0; i < workChains.size(); ++i) {
4484                 final WorkChain workChain = workChains.get(i);
4485                 final int uid = workChain.getAttributionUid();
4486                 noteLongPartialWakeLockStartInternal(name, historyName, uid);
4487
4488                 StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4489                         workChain.getUids(), workChain.getTags(), name, historyName,
4490                         StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
4491             }
4492         }
4493     }
4494
4495     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid) {
4496         final long elapsedRealtime = mClocks.elapsedRealtime();
4497         final long uptime = mClocks.uptimeMillis();
4498         if (historyName == null) {
4499             historyName = name;
4500         }
4501         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
4502                 0)) {
4503             return;
4504         }
4505         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
4506                 historyName, uid);
4507     }
4508
4509     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
4510         StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, null,
4511                 name, historyName, StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
4512
4513         uid = mapUid(uid);
4514         noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4515     }
4516
4517     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
4518             WorkSource workSource) {
4519         final int N = workSource.size();
4520         for (int i = 0; i < N; ++i) {
4521             final int uid = mapUid(workSource.get(i));
4522             noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4523             StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4524                     workSource.get(i), workSource.getName(i), name, historyName,
4525                     StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
4526         }
4527
4528         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
4529         if (workChains != null) {
4530             for (int i = 0; i < workChains.size(); ++i) {
4531                 final WorkChain workChain = workChains.get(i);
4532                 final int uid = workChain.getAttributionUid();
4533                 noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4534                 StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4535                         workChain.getUids(), workChain.getTags(), name, historyName,
4536                         StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
4537             }
4538         }
4539     }
4540
4541     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid) {
4542         final long elapsedRealtime = mClocks.elapsedRealtime();
4543         final long uptime = mClocks.uptimeMillis();
4544         if (historyName == null) {
4545             historyName = name;
4546         }
4547         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
4548                 0)) {
4549             return;
4550         }
4551         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
4552                 historyName, uid);
4553     }
4554
4555     void aggregateLastWakeupUptimeLocked(long uptimeMs) {
4556         if (mLastWakeupReason != null) {
4557             long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
4558             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
4559             timer.add(deltaUptime * 1000, 1); // time in in microseconds
4560             StatsLog.write(StatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
4561                     /* duration_usec */ deltaUptime * 1000);
4562             mLastWakeupReason = null;
4563         }
4564     }
4565
4566     public void noteWakeupReasonLocked(String reason) {
4567         final long elapsedRealtime = mClocks.elapsedRealtime();
4568         final long uptime = mClocks.uptimeMillis();
4569         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
4570                 + Integer.toHexString(mHistoryCur.states));
4571         aggregateLastWakeupUptimeLocked(uptime);
4572         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
4573         mHistoryCur.wakeReasonTag.string = reason;
4574         mHistoryCur.wakeReasonTag.uid = 0;
4575         mLastWakeupReason = reason;
4576         mLastWakeupUptimeMs = uptime;
4577         addHistoryRecordLocked(elapsedRealtime, uptime);
4578     }
4579
4580     public boolean startAddingCpuLocked() {
4581         mExternalSync.cancelCpuSyncDueToWakelockChange();
4582         return mOnBatteryInternal;
4583     }
4584
4585     public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
4586                                       int statSystemTime, int statIOWaitTime, int statIrqTime,
4587                                       int statSoftIrqTime, int statIdleTime) {
4588         if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
4589                 + " user=" + statUserTime + " sys=" + statSystemTime
4590                 + " io=" + statIOWaitTime + " irq=" + statIrqTime
4591                 + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
4592         mCurStepCpuUserTime += totalUTime;
4593         mCurStepCpuSystemTime += totalSTime;
4594         mCurStepStatUserTime += statUserTime;
4595         mCurStepStatSystemTime += statSystemTime;
4596         mCurStepStatIOWaitTime += statIOWaitTime;
4597         mCurStepStatIrqTime += statIrqTime;
4598         mCurStepStatSoftIrqTime += statSoftIrqTime;
4599         mCurStepStatIdleTime += statIdleTime;
4600     }
4601
4602     public void noteProcessDiedLocked(int uid, int pid) {
4603         uid = mapUid(uid);
4604         Uid u = mUidStats.get(uid);
4605         if (u != null) {
4606             u.mPids.remove(pid);
4607         }
4608     }
4609
4610     public long getProcessWakeTime(int uid, int pid, long realtime) {
4611         uid = mapUid(uid);
4612         Uid u = mUidStats.get(uid);
4613         if (u != null) {
4614             Uid.Pid p = u.mPids.get(pid);
4615             if (p != null) {
4616                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
4617             }
4618         }
4619         return 0;
4620     }
4621
4622     public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
4623         uid = mapUid(uid);
4624         Uid u = mUidStats.get(uid);
4625         if (u != null) {
4626             u.reportExcessiveCpuLocked(proc, overTime, usedTime);
4627         }
4628     }
4629
4630     int mSensorNesting;
4631
4632     public void noteStartSensorLocked(int uid, int sensor) {
4633         uid = mapUid(uid);
4634         final long elapsedRealtime = mClocks.elapsedRealtime();
4635         final long uptime = mClocks.uptimeMillis();
4636         if (mSensorNesting == 0) {
4637             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
4638             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
4639                     + Integer.toHexString(mHistoryCur.states));
4640             addHistoryRecordLocked(elapsedRealtime, uptime);
4641         }
4642         mSensorNesting++;
4643         getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
4644     }
4645
4646     public void noteStopSensorLocked(int uid, int sensor) {
4647         uid = mapUid(uid);
4648         final long elapsedRealtime = mClocks.elapsedRealtime();
4649         final long uptime = mClocks.uptimeMillis();
4650         mSensorNesting--;
4651         if (mSensorNesting == 0) {
4652             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
4653             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
4654                     + Integer.toHexString(mHistoryCur.states));
4655             addHistoryRecordLocked(elapsedRealtime, uptime);
4656         }
4657         getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
4658     }
4659
4660     int mGpsNesting;
4661
4662     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
4663         for (int i = 0; i < newWs.size(); ++i) {
4664             noteStartGpsLocked(newWs.get(i), null);
4665         }
4666
4667         for (int i = 0; i < oldWs.size(); ++i) {
4668             noteStopGpsLocked((oldWs.get(i)), null);
4669         }
4670
4671         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
4672         if (wcs != null) {
4673             if (wcs[0] != null) {
4674                 final List<WorkChain> newChains = wcs[0];
4675                 for (int i = 0; i < newChains.size(); ++i) {
4676                     noteStartGpsLocked(-1, newChains.get(i));
4677                 }
4678             }
4679
4680             if (wcs[1] != null) {
4681                 final List<WorkChain> goneChains = wcs[1];
4682                 for (int i = 0; i < goneChains.size(); ++i) {
4683                     noteStopGpsLocked(-1, goneChains.get(i));
4684                 }
4685             }
4686         }
4687     }
4688
4689     private void noteStartGpsLocked(int uid, WorkChain workChain) {
4690         uid = getAttributionUid(uid, workChain);
4691         final long elapsedRealtime = mClocks.elapsedRealtime();
4692         final long uptime = mClocks.uptimeMillis();
4693         if (mGpsNesting == 0) {
4694             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
4695             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
4696                     + Integer.toHexString(mHistoryCur.states));
4697             addHistoryRecordLocked(elapsedRealtime, uptime);
4698         }
4699         mGpsNesting++;
4700
4701         if (workChain == null) {
4702             StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4703                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4704         } else {
4705             StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED,
4706                     workChain.getUids(), workChain.getTags(),
4707                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4708         }
4709
4710         getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
4711     }
4712
4713     private void noteStopGpsLocked(int uid, WorkChain workChain) {
4714         uid = getAttributionUid(uid, workChain);
4715         final long elapsedRealtime = mClocks.elapsedRealtime();
4716         final long uptime = mClocks.uptimeMillis();
4717         mGpsNesting--;
4718         if (mGpsNesting == 0) {
4719             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
4720             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
4721                     + Integer.toHexString(mHistoryCur.states));
4722             addHistoryRecordLocked(elapsedRealtime, uptime);
4723             stopAllGpsSignalQualityTimersLocked(-1);
4724             mGpsSignalQualityBin = -1;
4725         }
4726
4727         if (workChain == null) {
4728             StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4729                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4730         } else {
4731             StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
4732                     workChain.getTags(), StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4733         }
4734
4735         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
4736     }
4737
4738     public void noteGpsSignalQualityLocked(int signalLevel) {
4739         if (mGpsNesting == 0) {
4740             return;
4741         }
4742         if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
4743             stopAllGpsSignalQualityTimersLocked(-1);
4744             return;
4745         }
4746         final long elapsedRealtime = mClocks.elapsedRealtime();
4747         final long uptime = mClocks.uptimeMillis();
4748         if (mGpsSignalQualityBin != signalLevel) {
4749             if (mGpsSignalQualityBin >= 0) {
4750                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
4751             }
4752             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
4753                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
4754             }
4755             mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
4756                     | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
4757             addHistoryRecordLocked(elapsedRealtime, uptime);
4758             mGpsSignalQualityBin = signalLevel;
4759         }
4760         return;
4761     }
4762
4763     @GuardedBy("this")
4764     public void noteScreenStateLocked(int state) {
4765         state = mPretendScreenOff ? Display.STATE_OFF : state;
4766
4767         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
4768         // original 4 are mapped to one of the originals.
4769         if (state > MAX_TRACKED_SCREEN_STATE) {
4770             switch (state) {
4771                 case Display.STATE_VR:
4772                     state = Display.STATE_ON;
4773                     break;
4774                 default:
4775                     Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
4776                     break;
4777             }
4778         }
4779
4780         if (mScreenState != state) {
4781             recordDailyStatsIfNeededLocked(true);
4782             final int oldState = mScreenState;
4783             mScreenState = state;
4784             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
4785                     + ", newState=" + Display.stateToString(state));
4786
4787             if (state != Display.STATE_UNKNOWN) {
4788                 int stepState = state-1;
4789                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
4790                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
4791                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
4792                 } else {
4793                     Slog.wtf(TAG, "Unexpected screen state: " + state);
4794                 }
4795             }
4796
4797             final long elapsedRealtime = mClocks.elapsedRealtime();
4798             final long uptime = mClocks.uptimeMillis();
4799
4800             boolean updateHistory = false;
4801             if (isScreenDoze(state)) {
4802                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
4803                 mScreenDozeTimer.startRunningLocked(elapsedRealtime);
4804                 updateHistory = true;
4805             } else if (isScreenDoze(oldState)) {
4806                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
4807                 mScreenDozeTimer.stopRunningLocked(elapsedRealtime);
4808                 updateHistory = true;
4809             }
4810             if (isScreenOn(state)) {
4811                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
4812                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
4813                         + Integer.toHexString(mHistoryCur.states));
4814                 mScreenOnTimer.startRunningLocked(elapsedRealtime);
4815                 if (mScreenBrightnessBin >= 0) {
4816                     mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
4817                 }
4818                 updateHistory = true;
4819             } else if (isScreenOn(oldState)) {
4820                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
4821                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
4822                         + Integer.toHexString(mHistoryCur.states));
4823                 mScreenOnTimer.stopRunningLocked(elapsedRealtime);
4824                 if (mScreenBrightnessBin >= 0) {
4825                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4826                 }
4827                 updateHistory = true;
4828             }
4829             if (updateHistory) {
4830                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
4831                         + Display.stateToString(state));
4832                 addHistoryRecordLocked(elapsedRealtime, uptime);
4833             }
4834             mExternalSync.scheduleCpuSyncDueToScreenStateChange(
4835                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
4836             if (isScreenOn(state)) {
4837                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4838                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4839                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
4840                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
4841                         elapsedRealtime, uptime);
4842             } else if (isScreenOn(oldState)) {
4843                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
4844                         elapsedRealtime, uptime);
4845                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4846                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4847             }
4848             // Update discharge amounts.
4849             if (mOnBatteryInternal) {
4850                 updateDischargeScreenLevelsLocked(oldState, state);
4851             }
4852         }
4853     }
4854
4855     public void noteScreenBrightnessLocked(int brightness) {
4856         // Bin the brightness.
4857         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
4858         if (bin < 0) bin = 0;
4859         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
4860         if (mScreenBrightnessBin != bin) {
4861             final long elapsedRealtime = mClocks.elapsedRealtime();
4862             final long uptime = mClocks.uptimeMillis();
4863             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
4864                     | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
4865             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
4866                     + Integer.toHexString(mHistoryCur.states));
4867             addHistoryRecordLocked(elapsedRealtime, uptime);
4868             if (mScreenState == Display.STATE_ON) {
4869                 if (mScreenBrightnessBin >= 0) {
4870                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4871                 }
4872                 mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
4873             }
4874             mScreenBrightnessBin = bin;
4875         }
4876     }
4877
4878     public void noteUserActivityLocked(int uid, int event) {
4879         if (mOnBatteryInternal) {
4880             uid = mapUid(uid);
4881             getUidStatsLocked(uid).noteUserActivityLocked(event);
4882         }
4883     }
4884
4885     public void noteWakeUpLocked(String reason, int reasonUid) {
4886         final long elapsedRealtime = mClocks.elapsedRealtime();
4887         final long uptime = mClocks.uptimeMillis();
4888         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
4889                 reason, reasonUid);
4890     }
4891
4892     public void noteInteractiveLocked(boolean interactive) {
4893         if (mInteractive != interactive) {
4894             final long elapsedRealtime = mClocks.elapsedRealtime();
4895             mInteractive = interactive;
4896             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
4897             if (interactive) {
4898                 mInteractiveTimer.startRunningLocked(elapsedRealtime);
4899             } else {
4900                 mInteractiveTimer.stopRunningLocked(elapsedRealtime);
4901             }
4902         }
4903     }
4904
4905     public void noteConnectivityChangedLocked(int type, String extra) {
4906         final long elapsedRealtime = mClocks.elapsedRealtime();
4907         final long uptime = mClocks.uptimeMillis();
4908         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
4909                 extra, type);
4910         mNumConnectivityChange++;
4911     }
4912
4913     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
4914             final long uptimeMillis, int uid) {
4915         uid = mapUid(uid);
4916         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
4917                 uid);
4918         getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
4919     }
4920
4921     /**
4922      * Updates the radio power state and returns true if an external stats collection should occur.
4923      */
4924     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
4925         final long elapsedRealtime = mClocks.elapsedRealtime();
4926         final long uptime = mClocks.uptimeMillis();
4927         if (mMobileRadioPowerState != powerState) {
4928             long realElapsedRealtimeMs;
4929             final boolean active =
4930                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
4931                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
4932             if (active) {
4933                 if (uid > 0) {
4934                     noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid);
4935                 }
4936
4937                 mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
4938                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
4939             } else {
4940                 realElapsedRealtimeMs = timestampNs / (1000*1000);
4941                 long lastUpdateTimeMs = mMobileRadioActiveStartTime;
4942                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
4943                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
4944                             + " is before start time " + lastUpdateTimeMs);
4945                     realElapsedRealtimeMs = elapsedRealtime;
4946                 } else if (realElapsedRealtimeMs < elapsedRealtime) {
4947                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
4948                             - realElapsedRealtimeMs);
4949                 }
4950                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
4951             }
4952             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
4953                     + Integer.toHexString(mHistoryCur.states));
4954             addHistoryRecordLocked(elapsedRealtime, uptime);
4955             mMobileRadioPowerState = powerState;
4956             StatsLog.write(StatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, powerState);
4957             if (active) {
4958                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
4959                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
4960             } else {
4961                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
4962                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
4963                 // Tell the caller to collect radio network/power stats.
4964                 return true;
4965             }
4966         }
4967         return false;
4968     }
4969
4970     public void notePowerSaveModeLocked(boolean enabled) {
4971         if (mPowerSaveModeEnabled != enabled) {
4972             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
4973             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
4974             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
4975             final long elapsedRealtime = mClocks.elapsedRealtime();
4976             final long uptime = mClocks.uptimeMillis();
4977             mPowerSaveModeEnabled = enabled;
4978             if (enabled) {
4979                 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
4980                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
4981                         + Integer.toHexString(mHistoryCur.states2));
4982                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
4983             } else {
4984                 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
4985                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
4986                         + Integer.toHexString(mHistoryCur.states2));
4987                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
4988             }
4989             addHistoryRecordLocked(elapsedRealtime, uptime);
4990             StatsLog.write(StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ?
4991                     StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON :
4992                     StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
4993         }
4994     }
4995
4996     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
4997         final long elapsedRealtime = mClocks.elapsedRealtime();
4998         final long uptime = mClocks.uptimeMillis();
4999         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
5000         if (mDeviceIdling && !nowIdling && activeReason == null) {
5001             // We don't go out of general idling mode until explicitly taken out of
5002             // device idle through going active or significant motion.
5003             nowIdling = true;
5004         }
5005         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
5006         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
5007             // We don't go out of general light idling mode until explicitly taken out of
5008             // device idle through going active or significant motion.
5009             nowLightIdling = true;
5010         }
5011         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
5012             addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
5013                     activeReason, activeUid);
5014         }
5015         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
5016             int statsmode;
5017             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
5018             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
5019             else                     statsmode = DEVICE_IDLE_MODE_OFF;
5020             StatsLog.write(StatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
5021         }
5022         if (mDeviceIdling != nowIdling) {
5023             mDeviceIdling = nowIdling;
5024             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
5025             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
5026             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
5027             if (nowIdling) {
5028                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
5029             } else {
5030                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
5031             }
5032         }
5033         if (mDeviceLightIdling != nowLightIdling) {
5034             mDeviceLightIdling = nowLightIdling;
5035             if (nowLightIdling) {
5036                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
5037             } else {
5038                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
5039             }
5040         }
5041         if (mDeviceIdleMode != mode) {
5042             mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
5043                     | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
5044             if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
5045                     + Integer.toHexString(mHistoryCur.states2));
5046             addHistoryRecordLocked(elapsedRealtime, uptime);
5047             long lastDuration = elapsedRealtime - mLastIdleTimeStart;
5048             mLastIdleTimeStart = elapsedRealtime;
5049             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
5050                 if (lastDuration > mLongestLightIdleTime) {
5051                     mLongestLightIdleTime = lastDuration;
5052                 }
5053                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
5054             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
5055                 if (lastDuration > mLongestFullIdleTime) {
5056                     mLongestFullIdleTime = lastDuration;
5057                 }
5058                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
5059             }
5060             if (mode == DEVICE_IDLE_MODE_LIGHT) {
5061                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
5062             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
5063                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
5064             }
5065             mDeviceIdleMode = mode;
5066             StatsLog.write(StatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
5067         }
5068     }
5069
5070     public void notePackageInstalledLocked(String pkgName, long versionCode) {
5071         final long elapsedRealtime = mClocks.elapsedRealtime();
5072         final long uptime = mClocks.uptimeMillis();
5073         // XXX need to figure out what to do with long version codes.
5074         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
5075                 pkgName, (int)versionCode);
5076         PackageChange pc = new PackageChange();
5077         pc.mPackageName = pkgName;
5078         pc.mUpdate = true;
5079         pc.mVersionCode = versionCode;
5080         addPackageChange(pc);
5081     }
5082
5083     public void notePackageUninstalledLocked(String pkgName) {
5084         final long elapsedRealtime = mClocks.elapsedRealtime();
5085         final long uptime = mClocks.uptimeMillis();
5086         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
5087                 pkgName, 0);
5088         PackageChange pc = new PackageChange();
5089         pc.mPackageName = pkgName;
5090         pc.mUpdate = true;
5091         addPackageChange(pc);
5092     }
5093
5094     private void addPackageChange(PackageChange pc) {
5095         if (mDailyPackageChanges == null) {
5096             mDailyPackageChanges = new ArrayList<>();
5097         }
5098         mDailyPackageChanges.add(pc);
5099     }
5100
5101     void stopAllGpsSignalQualityTimersLocked(int except) {
5102         final long elapsedRealtime = mClocks.elapsedRealtime();
5103         for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
5104             if (i == except) {
5105                 continue;
5106             }
5107             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
5108                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
5109             }
5110         }
5111     }
5112
5113     public void notePhoneOnLocked() {
5114         if (!mPhoneOn) {
5115             final long elapsedRealtime = mClocks.elapsedRealtime();
5116             final long uptime = mClocks.uptimeMillis();
5117             mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5118             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
5119                     + Integer.toHexString(mHistoryCur.states));
5120             addHistoryRecordLocked(elapsedRealtime, uptime);
5121             mPhoneOn = true;
5122             mPhoneOnTimer.startRunningLocked(elapsedRealtime);
5123         }
5124     }
5125
5126     public void notePhoneOffLocked() {
5127         if (mPhoneOn) {
5128             final long elapsedRealtime = mClocks.elapsedRealtime();
5129             final long uptime = mClocks.uptimeMillis();
5130             mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5131             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
5132                     + Integer.toHexString(mHistoryCur.states));
5133             addHistoryRecordLocked(elapsedRealtime, uptime);
5134             mPhoneOn = false;
5135             mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
5136         }
5137     }
5138
5139     void stopAllPhoneSignalStrengthTimersLocked(int except) {
5140         final long elapsedRealtime = mClocks.elapsedRealtime();
5141         for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
5142             if (i == except) {
5143                 continue;
5144             }
5145             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
5146                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5147             }
5148         }
5149     }
5150
5151     private int fixPhoneServiceState(int state, int signalBin) {
5152         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
5153             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5154             // to infer that we are scanning from other data.
5155             if (state == ServiceState.STATE_OUT_OF_SERVICE
5156                     && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5157                 state = ServiceState.STATE_IN_SERVICE;
5158             }
5159         }
5160
5161         return state;
5162     }
5163
5164     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
5165         boolean scanning = false;
5166         boolean newHistory = false;
5167
5168         mPhoneServiceStateRaw = state;
5169         mPhoneSimStateRaw = simState;
5170         mPhoneSignalStrengthBinRaw = strengthBin;
5171
5172         final long elapsedRealtime = mClocks.elapsedRealtime();
5173         final long uptime = mClocks.uptimeMillis();
5174
5175         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
5176             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5177             // to infer that we are scanning from other data.
5178             if (state == ServiceState.STATE_OUT_OF_SERVICE
5179                     && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5180                 state = ServiceState.STATE_IN_SERVICE;
5181             }
5182         }
5183
5184         // If the phone is powered off, stop all timers.
5185         if (state == ServiceState.STATE_POWER_OFF) {
5186             strengthBin = -1;
5187
5188         // If we are in service, make sure the correct signal string timer is running.
5189         } else if (state == ServiceState.STATE_IN_SERVICE) {
5190             // Bin will be changed below.
5191
5192         // If we're out of service, we are in the lowest signal strength
5193         // bin and have the scanning bit set.
5194         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
5195             scanning = true;
5196             strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
5197             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
5198                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
5199                 newHistory = true;
5200                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
5201                         + Integer.toHexString(mHistoryCur.states));
5202                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
5203             }
5204         }
5205
5206         if (!scanning) {
5207             // If we are no longer scanning, then stop the scanning timer.
5208             if (mPhoneSignalScanningTimer.isRunningLocked()) {
5209                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
5210                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
5211                         + Integer.toHexString(mHistoryCur.states));
5212                 newHistory = true;
5213                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
5214             }
5215         }
5216
5217         if (mPhoneServiceState != state) {
5218             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
5219                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
5220             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
5221                     + Integer.toHexString(mHistoryCur.states));
5222             newHistory = true;
5223             mPhoneServiceState = state;
5224         }
5225
5226         if (mPhoneSignalStrengthBin != strengthBin) {
5227             if (mPhoneSignalStrengthBin >= 0) {
5228                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
5229                         elapsedRealtime);
5230             }
5231             if (strengthBin >= 0) {
5232                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5233                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5234                 }
5235                 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
5236                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
5237                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
5238                         + Integer.toHexString(mHistoryCur.states));
5239                 newHistory = true;
5240                 StatsLog.write(StatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
5241             } else {
5242                 stopAllPhoneSignalStrengthTimersLocked(-1);
5243             }
5244             mPhoneSignalStrengthBin = strengthBin;
5245         }
5246
5247         if (newHistory) {
5248             addHistoryRecordLocked(elapsedRealtime, uptime);
5249         }
5250     }
5251
5252     /**
5253      * Telephony stack updates the phone state.
5254      * @param state phone state from ServiceState.getState()
5255      */
5256     public void notePhoneStateLocked(int state, int simState) {
5257         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
5258     }
5259
5260     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
5261         // Bin the strength.
5262         int bin = signalStrength.getLevel();
5263         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
5264     }
5265
5266     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
5267         int bin = DATA_CONNECTION_NONE;
5268         if (hasData) {
5269             switch (dataType) {
5270                 case TelephonyManager.NETWORK_TYPE_EDGE:
5271                     bin = DATA_CONNECTION_EDGE;
5272                     break;
5273                 case TelephonyManager.NETWORK_TYPE_GPRS:
5274                     bin = DATA_CONNECTION_GPRS;
5275                     break;
5276                 case TelephonyManager.NETWORK_TYPE_UMTS:
5277                     bin = DATA_CONNECTION_UMTS;
5278                     break;
5279                 case TelephonyManager.NETWORK_TYPE_CDMA:
5280                     bin = DATA_CONNECTION_CDMA;
5281                     break;
5282                 case TelephonyManager.NETWORK_TYPE_EVDO_0:
5283                     bin = DATA_CONNECTION_EVDO_0;
5284                     break;
5285                 case TelephonyManager.NETWORK_TYPE_EVDO_A:
5286                     bin = DATA_CONNECTION_EVDO_A;
5287                     break;
5288                 case TelephonyManager.NETWORK_TYPE_1xRTT:
5289                     bin = DATA_CONNECTION_1xRTT;
5290                     break;
5291                 case TelephonyManager.NETWORK_TYPE_HSDPA:
5292                     bin = DATA_CONNECTION_HSDPA;
5293                     break;
5294                 case TelephonyManager.NETWORK_TYPE_HSUPA:
5295                     bin = DATA_CONNECTION_HSUPA;
5296                     break;
5297                 case TelephonyManager.NETWORK_TYPE_HSPA:
5298                     bin = DATA_CONNECTION_HSPA;
5299                     break;
5300                 case TelephonyManager.NETWORK_TYPE_IDEN:
5301                     bin = DATA_CONNECTION_IDEN;
5302                     break;
5303                 case TelephonyManager.NETWORK_TYPE_EVDO_B:
5304                     bin = DATA_CONNECTION_EVDO_B;
5305                     break;
5306                 case TelephonyManager.NETWORK_TYPE_LTE:
5307                     bin = DATA_CONNECTION_LTE;
5308                     break;
5309                 case TelephonyManager.NETWORK_TYPE_EHRPD:
5310                     bin = DATA_CONNECTION_EHRPD;
5311                     break;
5312                 case TelephonyManager.NETWORK_TYPE_HSPAP:
5313                     bin = DATA_CONNECTION_HSPAP;
5314                     break;
5315                 case TelephonyManager.NETWORK_TYPE_GSM:
5316                     bin = DATA_CONNECTION_GSM;
5317                     break;
5318                 case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
5319                     bin = DATA_CONNECTION_TD_SCDMA;
5320                     break;
5321                 case TelephonyManager.NETWORK_TYPE_IWLAN:
5322                     bin = DATA_CONNECTION_IWLAN;
5323                     break;
5324                 case TelephonyManager.NETWORK_TYPE_LTE_CA:
5325                     bin = DATA_CONNECTION_LTE_CA;
5326                     break;
5327                 default:
5328                     bin = DATA_CONNECTION_OTHER;
5329                     break;
5330             }
5331         }
5332         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
5333         if (mPhoneDataConnectionType != bin) {
5334             final long elapsedRealtime = mClocks.elapsedRealtime();
5335             final long uptime = mClocks.uptimeMillis();
5336             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
5337                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
5338             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
5339                     + Integer.toHexString(mHistoryCur.states));
5340             addHistoryRecordLocked(elapsedRealtime, uptime);
5341             if (mPhoneDataConnectionType >= 0) {
5342                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
5343                         elapsedRealtime);
5344             }
5345             mPhoneDataConnectionType = bin;
5346             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
5347         }
5348     }
5349
5350     public void noteWifiOnLocked() {
5351         if (!mWifiOn) {
5352             final long elapsedRealtime = mClocks.elapsedRealtime();
5353             final long uptime = mClocks.uptimeMillis();
5354             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
5355             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
5356                     + Integer.toHexString(mHistoryCur.states));
5357             addHistoryRecordLocked(elapsedRealtime, uptime);
5358             mWifiOn = true;
5359             mWifiOnTimer.startRunningLocked(elapsedRealtime);
5360             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
5361         }
5362     }
5363
5364     public void noteWifiOffLocked() {
5365         final long elapsedRealtime = mClocks.elapsedRealtime();
5366         final long uptime = mClocks.uptimeMillis();
5367         if (mWifiOn) {
5368             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
5369             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
5370                     + Integer.toHexString(mHistoryCur.states));
5371             addHistoryRecordLocked(elapsedRealtime, uptime);
5372             mWifiOn = false;
5373             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
5374             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
5375         }
5376     }
5377
5378     public void noteAudioOnLocked(int uid) {
5379         uid = mapUid(uid);
5380         final long elapsedRealtime = mClocks.elapsedRealtime();
5381         final long uptime = mClocks.uptimeMillis();
5382         if (mAudioOnNesting == 0) {
5383             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
5384             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
5385                     + Integer.toHexString(mHistoryCur.states));
5386             addHistoryRecordLocked(elapsedRealtime, uptime);
5387             mAudioOnTimer.startRunningLocked(elapsedRealtime);
5388         }
5389         mAudioOnNesting++;
5390         getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
5391     }
5392
5393     public void noteAudioOffLocked(int uid) {
5394         if (mAudioOnNesting == 0) {
5395             return;
5396         }
5397         uid = mapUid(uid);
5398         final long elapsedRealtime = mClocks.elapsedRealtime();
5399         final long uptime = mClocks.uptimeMillis();
5400         if (--mAudioOnNesting == 0) {
5401             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5402             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5403                     + Integer.toHexString(mHistoryCur.states));
5404             addHistoryRecordLocked(elapsedRealtime, uptime);
5405             mAudioOnTimer.stopRunningLocked(elapsedRealtime);
5406         }
5407         getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
5408     }
5409
5410     public void noteVideoOnLocked(int uid) {
5411         uid = mapUid(uid);
5412         final long elapsedRealtime = mClocks.elapsedRealtime();
5413         final long uptime = mClocks.uptimeMillis();
5414         if (mVideoOnNesting == 0) {
5415             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
5416             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
5417                     + Integer.toHexString(mHistoryCur.states));
5418             addHistoryRecordLocked(elapsedRealtime, uptime);
5419             mVideoOnTimer.startRunningLocked(elapsedRealtime);
5420         }
5421         mVideoOnNesting++;
5422         getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
5423     }
5424
5425     public void noteVideoOffLocked(int uid) {
5426         if (mVideoOnNesting == 0) {
5427             return;
5428         }
5429         uid = mapUid(uid);
5430         final long elapsedRealtime = mClocks.elapsedRealtime();
5431         final long uptime = mClocks.uptimeMillis();
5432         if (--mVideoOnNesting == 0) {
5433             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5434             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5435                     + Integer.toHexString(mHistoryCur.states));
5436             addHistoryRecordLocked(elapsedRealtime, uptime);
5437             mVideoOnTimer.stopRunningLocked(elapsedRealtime);
5438         }
5439         getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
5440     }
5441
5442     public void noteResetAudioLocked() {
5443         if (mAudioOnNesting > 0) {
5444             final long elapsedRealtime = mClocks.elapsedRealtime();
5445             final long uptime = mClocks.uptimeMillis();
5446             mAudioOnNesting = 0;
5447             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5448             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5449                     + Integer.toHexString(mHistoryCur.states));
5450             addHistoryRecordLocked(elapsedRealtime, uptime);
5451             mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
5452             for (int i=0; i<mUidStats.size(); i++) {
5453                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5454                 uid.noteResetAudioLocked(elapsedRealtime);
5455             }
5456         }
5457     }
5458
5459     public void noteResetVideoLocked() {
5460         if (mVideoOnNesting > 0) {
5461             final long elapsedRealtime = mClocks.elapsedRealtime();
5462             final long uptime = mClocks.uptimeMillis();
5463             mAudioOnNesting = 0;
5464             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5465             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5466                     + Integer.toHexString(mHistoryCur.states));
5467             addHistoryRecordLocked(elapsedRealtime, uptime);
5468             mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
5469             for (int i=0; i<mUidStats.size(); i++) {
5470                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5471                 uid.noteResetVideoLocked(elapsedRealtime);
5472             }
5473         }
5474     }
5475
5476     public void noteActivityResumedLocked(int uid) {
5477         uid = mapUid(uid);
5478         getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
5479     }
5480
5481     public void noteActivityPausedLocked(int uid) {
5482         uid = mapUid(uid);
5483         getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
5484     }
5485
5486     public void noteVibratorOnLocked(int uid, long durationMillis) {
5487         uid = mapUid(uid);
5488         getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
5489     }
5490
5491     public void noteVibratorOffLocked(int uid) {
5492         uid = mapUid(uid);
5493         getUidStatsLocked(uid).noteVibratorOffLocked();
5494     }
5495
5496     public void noteFlashlightOnLocked(int uid) {
5497         uid = mapUid(uid);
5498         final long elapsedRealtime = mClocks.elapsedRealtime();
5499         final long uptime = mClocks.uptimeMillis();
5500         if (mFlashlightOnNesting++ == 0) {
5501             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
5502             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
5503                     + Integer.toHexString(mHistoryCur.states2));
5504             addHistoryRecordLocked(elapsedRealtime, uptime);
5505             mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
5506         }
5507         getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
5508     }
5509
5510     public void noteFlashlightOffLocked(int uid) {
5511         if (mFlashlightOnNesting == 0) {
5512             return;
5513         }
5514         uid = mapUid(uid);
5515         final long elapsedRealtime = mClocks.elapsedRealtime();
5516         final long uptime = mClocks.uptimeMillis();
5517         if (--mFlashlightOnNesting == 0) {
5518             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5519             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5520                     + Integer.toHexString(mHistoryCur.states2));
5521             addHistoryRecordLocked(elapsedRealtime, uptime);
5522             mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
5523         }
5524         getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
5525     }
5526
5527     public void noteCameraOnLocked(int uid) {
5528         uid = mapUid(uid);
5529         final long elapsedRealtime = mClocks.elapsedRealtime();
5530         final long uptime = mClocks.uptimeMillis();
5531         if (mCameraOnNesting++ == 0) {
5532             mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
5533             if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
5534                     + Integer.toHexString(mHistoryCur.states2));
5535             addHistoryRecordLocked(elapsedRealtime, uptime);
5536             mCameraOnTimer.startRunningLocked(elapsedRealtime);
5537         }
5538         getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
5539     }
5540
5541     public void noteCameraOffLocked(int uid) {
5542         if (mCameraOnNesting == 0) {
5543             return;
5544         }
5545         uid = mapUid(uid);
5546         final long elapsedRealtime = mClocks.elapsedRealtime();
5547         final long uptime = mClocks.uptimeMillis();
5548         if (--mCameraOnNesting == 0) {
5549             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5550             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5551                     + Integer.toHexString(mHistoryCur.states2));
5552             addHistoryRecordLocked(elapsedRealtime, uptime);
5553             mCameraOnTimer.stopRunningLocked(elapsedRealtime);
5554         }
5555         getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
5556     }
5557
5558     public void noteResetCameraLocked() {
5559         if (mCameraOnNesting > 0) {
5560             final long elapsedRealtime = mClocks.elapsedRealtime();
5561             final long uptime = mClocks.uptimeMillis();
5562             mCameraOnNesting = 0;
5563             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5564             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5565                     + Integer.toHexString(mHistoryCur.states2));
5566             addHistoryRecordLocked(elapsedRealtime, uptime);
5567             mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
5568             for (int i=0; i<mUidStats.size(); i++) {
5569                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5570                 uid.noteResetCameraLocked(elapsedRealtime);
5571             }
5572         }
5573     }
5574
5575     public void noteResetFlashlightLocked() {
5576         if (mFlashlightOnNesting > 0) {
5577             final long elapsedRealtime = mClocks.elapsedRealtime();
5578             final long uptime = mClocks.uptimeMillis();
5579             mFlashlightOnNesting = 0;
5580             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5581             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5582                     + Integer.toHexString(mHistoryCur.states2));
5583             addHistoryRecordLocked(elapsedRealtime, uptime);
5584             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
5585             for (int i=0; i<mUidStats.size(); i++) {
5586                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5587                 uid.noteResetFlashlightLocked(elapsedRealtime);
5588             }
5589         }
5590     }
5591
5592     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
5593             boolean isUnoptimized) {
5594         uid = getAttributionUid(uid, workChain);
5595         final long elapsedRealtime = mClocks.elapsedRealtime();
5596         final long uptime = mClocks.uptimeMillis();
5597         if (mBluetoothScanNesting == 0) {
5598             mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5599             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
5600                     + Integer.toHexString(mHistoryCur.states2));
5601             addHistoryRecordLocked(elapsedRealtime, uptime);
5602             mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
5603         }
5604         mBluetoothScanNesting++;
5605
5606         if (workChain != null) {
5607             StatsLog.write(StatsLog.BLE_SCAN_STATE_CHANGED,
5608                     workChain.getUids(), workChain.getTags(),
5609                     StatsLog.BLE_SCAN_STATE_CHANGED__STATE__ON);
5610             if (isUnoptimized) {
5611                 StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED,
5612                         workChain.getUids(), workChain.getTags(),
5613                         StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED__STATE__ON);
5614             }
5615         } else {
5616             StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, uid, null,
5617                     StatsLog.BLE_SCAN_STATE_CHANGED__STATE__ON);
5618             if (isUnoptimized) {
5619                 StatsLog.write_non_chained(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, uid, null,
5620                         StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED__STATE__ON);
5621             }
5622         }
5623
5624         getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized);
5625         if (workChain != null) {
5626             getUidStatsLocked(uid).addBluetoothWorkChain(workChain, isUnoptimized);
5627         }
5628     }
5629
5630     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5631         final int N = ws.size();
5632         for (int i = 0; i < N; i++) {
5633             noteBluetoothScanStartedLocked(null, ws.get(i), isUnoptimized);
5634         }
5635
5636         final List<WorkChain> workChains = ws.getWorkChains();
5637         if (workChains != null) {
5638             for (int i = 0; i < workChains.size(); ++i) {
5639                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized);
5640             }
5641         }
5642     }
5643
5644     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
5645             boolean isUnoptimized) {
5646         uid = getAttributionUid(uid, workChain);
5647         final long elapsedRealtime = mClocks.elapsedRealtime();
5648         final long uptime = mClocks.uptimeMillis();
5649         mBluetoothScanNesting--;
5650         if (mBluetoothScanNesting == 0) {
5651             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5652             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
5653                     + Integer.toHexString(mHistoryCur.states2));
5654             addHistoryRecordLocked(elapsedRealtime, uptime);
5655             mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
5656         }
5657
5658         if (workChain != null) {
5659             StatsLog.write(
5660                     StatsLog.BLE_SCAN_STATE_CHANGED, workChain.getUids(), workChain.getTags(),
5661                     StatsLog.BLE_SCAN_STATE_CHANGED__STATE__OFF);
5662             if (isUnoptimized) {
5663                 StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED,
5664                         workChain.getUids(), workChain.getTags(),
5665                         StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED__STATE__OFF);
5666             }
5667         } else {
5668             StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, uid, null,
5669                     StatsLog.BLE_SCAN_STATE_CHANGED__STATE__OFF);
5670             if (isUnoptimized) {
5671                 StatsLog.write_non_chained(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, uid, null,
5672                         StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED__STATE__OFF);
5673             }
5674         }
5675
5676         getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime, isUnoptimized);
5677         if (workChain != null) {
5678             getUidStatsLocked(uid).removeBluetoothWorkChain(workChain, isUnoptimized);
5679         }
5680     }
5681
5682     private int getAttributionUid(int uid, WorkChain workChain) {
5683         if (workChain != null) {
5684             return mapUid(workChain.getAttributionUid());
5685         }
5686
5687         return mapUid(uid);
5688     }
5689
5690     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5691         final int N = ws.size();
5692         for (int i = 0; i < N; i++) {
5693             noteBluetoothScanStoppedLocked(null, ws.get(i), isUnoptimized);
5694         }
5695
5696         final List<WorkChain> workChains = ws.getWorkChains();
5697         if (workChains != null) {
5698             for (int i = 0; i < workChains.size(); ++i) {
5699                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized);
5700             }
5701         }
5702     }
5703
5704     public void noteResetBluetoothScanLocked() {
5705         if (mBluetoothScanNesting > 0) {
5706             final long elapsedRealtime = mClocks.elapsedRealtime();
5707             final long uptime = mClocks.uptimeMillis();
5708             mBluetoothScanNesting = 0;
5709             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5710             if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
5711                     + Integer.toHexString(mHistoryCur.states2));
5712             addHistoryRecordLocked(elapsedRealtime, uptime);
5713             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
5714
5715
5716             for (int i=0; i<mUidStats.size(); i++) {
5717                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5718                 uid.noteResetBluetoothScanLocked(elapsedRealtime);
5719
5720                 List<WorkChain> allWorkChains = uid.getAllBluetoothWorkChains();
5721                 if (allWorkChains != null) {
5722                     for (int j = 0; j < allWorkChains.size(); ++j) {
5723                         StatsLog.write(StatsLog.BLE_SCAN_STATE_CHANGED,
5724                                 allWorkChains.get(j).getUids(),
5725                                 allWorkChains.get(j).getTags(),
5726                                 StatsLog.BLE_SCAN_STATE_CHANGED__STATE__OFF);
5727                     }
5728                     allWorkChains.clear();
5729                 }
5730
5731                 List<WorkChain> unoptimizedWorkChains = uid.getUnoptimizedBluetoothWorkChains();
5732                 if (unoptimizedWorkChains != null) {
5733                     for (int j = 0; j < unoptimizedWorkChains.size(); ++j) {
5734                         StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED,
5735                                 unoptimizedWorkChains.get(j).getUids(),
5736                                 unoptimizedWorkChains.get(j).getTags(),
5737                                 StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED__STATE__OFF);
5738                     }
5739                     unoptimizedWorkChains.clear();
5740                 }
5741             }
5742         }
5743     }
5744
5745     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
5746         final int N = ws.size();
5747         for (int i = 0; i < N; i++) {
5748             int uid = mapUid(ws.get(i));
5749             getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5750             StatsLog.write_non_chained(StatsLog.BLE_SCAN_RESULT_RECEIVED, ws.get(i), ws.getName(i),
5751                     numNewResults);
5752         }
5753
5754         final List<WorkChain> workChains = ws.getWorkChains();
5755         if (workChains != null) {
5756             for (int i = 0; i < workChains.size(); ++i) {
5757                 final WorkChain wc = workChains.get(i);
5758                 int uid = mapUid(wc.getAttributionUid());
5759                 getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5760                 StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED,
5761                         wc.getUids(), wc.getTags(), numNewResults);
5762             }
5763         }
5764     }
5765
5766     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
5767             final long uptimeMillis, int uid) {
5768         uid = mapUid(uid);
5769         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5770                 uid);
5771         getUidStatsLocked(uid).noteWifiRadioApWakeupLocked();
5772     }
5773
5774     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
5775         final long elapsedRealtime = mClocks.elapsedRealtime();
5776         final long uptime = mClocks.uptimeMillis();
5777         if (mWifiRadioPowerState != powerState) {
5778             final boolean active =
5779                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5780                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5781             if (active) {
5782                 if (uid > 0) {
5783                     noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid);
5784                 }
5785                 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5786                 mWifiActiveTimer.startRunningLocked(elapsedRealtime);
5787             } else {
5788                 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5789                 mWifiActiveTimer.stopRunningLocked(
5790                     timestampNs / (1000 * 1000));
5791             }
5792             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
5793                     + Integer.toHexString(mHistoryCur.states));
5794             addHistoryRecordLocked(elapsedRealtime, uptime);
5795             mWifiRadioPowerState = powerState;
5796             StatsLog.write(StatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, powerState);
5797         }
5798     }
5799
5800     public void noteWifiRunningLocked(WorkSource ws) {
5801         if (!mGlobalWifiRunning) {
5802             final long elapsedRealtime = mClocks.elapsedRealtime();
5803             final long uptime = mClocks.uptimeMillis();
5804             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5805             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
5806                     + Integer.toHexString(mHistoryCur.states));
5807             addHistoryRecordLocked(elapsedRealtime, uptime);
5808             mGlobalWifiRunning = true;
5809             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
5810             int N = ws.size();
5811             for (int i=0; i<N; i++) {
5812                 int uid = mapUid(ws.get(i));
5813                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5814             }
5815
5816             List<WorkChain> workChains = ws.getWorkChains();
5817             if (workChains != null) {
5818                 for (int i = 0; i < workChains.size(); ++i) {
5819                     int uid = mapUid(workChains.get(i).getAttributionUid());
5820                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5821                 }
5822             }
5823
5824             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
5825         } else {
5826             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
5827         }
5828     }
5829
5830     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
5831         if (mGlobalWifiRunning) {
5832             final long elapsedRealtime = mClocks.elapsedRealtime();
5833             int N = oldWs.size();
5834             for (int i=0; i<N; i++) {
5835                 int uid = mapUid(oldWs.get(i));
5836                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5837             }
5838
5839             List<WorkChain> workChains = oldWs.getWorkChains();
5840             if (workChains != null) {
5841                 for (int i = 0; i < workChains.size(); ++i) {
5842                     int uid = mapUid(workChains.get(i).getAttributionUid());
5843                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5844                 }
5845             }
5846
5847             N = newWs.size();
5848             for (int i=0; i<N; i++) {
5849                 int uid = mapUid(newWs.get(i));
5850                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5851             }
5852
5853             workChains = newWs.getWorkChains();
5854             if (workChains != null) {
5855                 for (int i = 0; i < workChains.size(); ++i) {
5856                     int uid = mapUid(workChains.get(i).getAttributionUid());
5857                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5858                 }
5859             }
5860         } else {
5861             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
5862         }
5863     }
5864
5865     public void noteWifiStoppedLocked(WorkSource ws) {
5866         if (mGlobalWifiRunning) {
5867             final long elapsedRealtime = mClocks.elapsedRealtime();
5868             final long uptime = mClocks.uptimeMillis();
5869             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5870             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
5871                     + Integer.toHexString(mHistoryCur.states));
5872             addHistoryRecordLocked(elapsedRealtime, uptime);
5873             mGlobalWifiRunning = false;
5874             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
5875             int N = ws.size();
5876             for (int i=0; i<N; i++) {
5877                 int uid = mapUid(ws.get(i));
5878                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5879             }
5880
5881             List<WorkChain> workChains = ws.getWorkChains();
5882             if (workChains != null) {
5883                 for (int i = 0; i < workChains.size(); ++i) {
5884                     int uid = mapUid(workChains.get(i).getAttributionUid());
5885                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5886                 }
5887             }
5888
5889             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
5890         } else {
5891             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
5892         }
5893     }
5894
5895     public void noteWifiStateLocked(int wifiState, String accessPoint) {
5896         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
5897         if (mWifiState != wifiState) {
5898             final long elapsedRealtime = mClocks.elapsedRealtime();
5899             if (mWifiState >= 0) {
5900                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
5901             }
5902             mWifiState = wifiState;
5903             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
5904             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
5905         }
5906     }
5907
5908     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
5909         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
5910         if (mWifiSupplState != supplState) {
5911             final long elapsedRealtime = mClocks.elapsedRealtime();
5912             final long uptime = mClocks.uptimeMillis();
5913             if (mWifiSupplState >= 0) {
5914                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
5915             }
5916             mWifiSupplState = supplState;
5917             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
5918             mHistoryCur.states2 =
5919                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
5920                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
5921             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
5922                     + Integer.toHexString(mHistoryCur.states2));
5923             addHistoryRecordLocked(elapsedRealtime, uptime);
5924         }
5925     }
5926
5927     void stopAllWifiSignalStrengthTimersLocked(int except) {
5928         final long elapsedRealtime = mClocks.elapsedRealtime();
5929         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
5930             if (i == except) {
5931                 continue;
5932             }
5933             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
5934                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5935             }
5936         }
5937     }
5938
5939     public void noteWifiRssiChangedLocked(int newRssi) {
5940         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
5941         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
5942         if (mWifiSignalStrengthBin != strengthBin) {
5943             final long elapsedRealtime = mClocks.elapsedRealtime();
5944             final long uptime = mClocks.uptimeMillis();
5945             if (mWifiSignalStrengthBin >= 0) {
5946                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
5947                         elapsedRealtime);
5948             }
5949             if (strengthBin >= 0) {
5950                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5951                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5952                     StatsLog.write(StatsLog.WIFI_SIGNAL_STRENGTH_CHANGED, strengthBin);
5953                 }
5954                 mHistoryCur.states2 =
5955                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
5956                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
5957                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
5958                         + Integer.toHexString(mHistoryCur.states2));
5959                 addHistoryRecordLocked(elapsedRealtime, uptime);
5960             } else {
5961                 stopAllWifiSignalStrengthTimersLocked(-1);
5962             }
5963             mWifiSignalStrengthBin = strengthBin;
5964         }
5965     }
5966
5967     int mWifiFullLockNesting = 0;
5968
5969     public void noteFullWifiLockAcquiredLocked(int uid) {
5970         final long elapsedRealtime = mClocks.elapsedRealtime();
5971         final long uptime = mClocks.uptimeMillis();
5972         if (mWifiFullLockNesting == 0) {
5973             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
5974             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
5975                     + Integer.toHexString(mHistoryCur.states));
5976             addHistoryRecordLocked(elapsedRealtime, uptime);
5977         }
5978         mWifiFullLockNesting++;
5979         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
5980     }
5981
5982     public void noteFullWifiLockReleasedLocked(int uid) {
5983         final long elapsedRealtime = mClocks.elapsedRealtime();
5984         final long uptime = mClocks.uptimeMillis();
5985         mWifiFullLockNesting--;
5986         if (mWifiFullLockNesting == 0) {
5987             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
5988             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
5989                     + Integer.toHexString(mHistoryCur.states));
5990             addHistoryRecordLocked(elapsedRealtime, uptime);
5991         }
5992         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
5993     }
5994
5995     int mWifiScanNesting = 0;
5996
5997     public void noteWifiScanStartedLocked(int uid) {
5998         final long elapsedRealtime = mClocks.elapsedRealtime();
5999         final long uptime = mClocks.uptimeMillis();
6000         if (mWifiScanNesting == 0) {
6001             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
6002             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
6003                     + Integer.toHexString(mHistoryCur.states));
6004             addHistoryRecordLocked(elapsedRealtime, uptime);
6005         }
6006         mWifiScanNesting++;
6007         getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
6008     }
6009
6010     public void noteWifiScanStoppedLocked(int uid) {
6011         final long elapsedRealtime = mClocks.elapsedRealtime();
6012         final long uptime = mClocks.uptimeMillis();
6013         mWifiScanNesting--;
6014         if (mWifiScanNesting == 0) {
6015             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
6016             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
6017                     + Integer.toHexString(mHistoryCur.states));
6018             addHistoryRecordLocked(elapsedRealtime, uptime);
6019         }
6020         getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
6021     }
6022
6023     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
6024         uid = mapUid(uid);
6025         final long elapsedRealtime = mClocks.elapsedRealtime();
6026         getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
6027     }
6028
6029     public void noteWifiBatchedScanStoppedLocked(int uid) {
6030         uid = mapUid(uid);
6031         final long elapsedRealtime = mClocks.elapsedRealtime();
6032         getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
6033     }
6034
6035     int mWifiMulticastNesting = 0;
6036
6037     public void noteWifiMulticastEnabledLocked(int uid) {
6038         uid = mapUid(uid);
6039         final long elapsedRealtime = mClocks.elapsedRealtime();
6040         final long uptime = mClocks.uptimeMillis();
6041         if (mWifiMulticastNesting == 0) {
6042             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
6043             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
6044                     + Integer.toHexString(mHistoryCur.states));
6045             addHistoryRecordLocked(elapsedRealtime, uptime);
6046
6047             // Start Wifi Multicast overall timer
6048             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
6049                 if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
6050                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtime);
6051             }
6052         }
6053         mWifiMulticastNesting++;
6054         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
6055     }
6056
6057     public void noteWifiMulticastDisabledLocked(int uid) {
6058         uid = mapUid(uid);
6059         final long elapsedRealtime = mClocks.elapsedRealtime();
6060         final long uptime = mClocks.uptimeMillis();
6061         mWifiMulticastNesting--;
6062         if (mWifiMulticastNesting == 0) {
6063             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
6064             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
6065                     + Integer.toHexString(mHistoryCur.states));
6066             addHistoryRecordLocked(elapsedRealtime, uptime);
6067
6068             // Stop Wifi Multicast overall timer
6069             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
6070                 if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
6071                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtime);
6072             }
6073         }
6074         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
6075     }
6076
6077     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
6078         int N = ws.size();
6079         for (int i=0; i<N; i++) {
6080             final int uid = mapUid(ws.get(i));
6081             noteFullWifiLockAcquiredLocked(uid);
6082             StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
6083                     StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
6084         }
6085
6086         final List<WorkChain> workChains = ws.getWorkChains();
6087         if (workChains != null) {
6088             for (int i = 0; i < workChains.size(); ++i) {
6089                 final WorkChain workChain = workChains.get(i);
6090                 final int uid = mapUid(workChain.getAttributionUid());
6091                 noteFullWifiLockAcquiredLocked(uid);
6092                 StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
6093                         workChain.getUids(), workChain.getTags(),
6094                         StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
6095             }
6096         }
6097     }
6098
6099     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
6100         int N = ws.size();
6101         for (int i=0; i<N; i++) {
6102             final int uid = mapUid(ws.get(i));
6103             noteFullWifiLockReleasedLocked(uid);
6104             StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
6105                     StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
6106         }
6107
6108         final List<WorkChain> workChains = ws.getWorkChains();
6109         if (workChains != null) {
6110             for (int i = 0; i < workChains.size(); ++i) {
6111                 final WorkChain workChain = workChains.get(i);
6112                 final int uid = mapUid(workChain.getAttributionUid());
6113                 noteFullWifiLockReleasedLocked(uid);
6114                 StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
6115                         workChain.getUids(), workChain.getTags(),
6116                         StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
6117             }
6118         }
6119     }
6120
6121     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
6122         int N = ws.size();
6123         for (int i=0; i<N; i++) {
6124             final int uid = mapUid(ws.get(i));
6125             noteWifiScanStartedLocked(uid);
6126             StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i),
6127                     StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON);
6128         }
6129
6130         final List<WorkChain> workChains = ws.getWorkChains();
6131         if (workChains != null) {
6132             for (int i = 0; i < workChains.size(); ++i) {
6133                 final WorkChain workChain = workChains.get(i);
6134                 final int uid = mapUid(workChain.getAttributionUid());
6135                 noteWifiScanStartedLocked(uid);
6136                 StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED, workChain.getUids(),
6137                         workChain.getTags(), StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON);
6138             }
6139         }
6140     }
6141
6142     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
6143         int N = ws.size();
6144         for (int i=0; i<N; i++) {
6145             final int uid = mapUid(ws.get(i));
6146             noteWifiScanStoppedLocked(uid);
6147             StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i),
6148                     StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF);
6149         }
6150
6151         final List<WorkChain> workChains = ws.getWorkChains();
6152         if (workChains != null) {
6153             for (int i = 0; i < workChains.size(); ++i) {
6154                 final WorkChain workChain = workChains.get(i);
6155                 final int uid = mapUid(workChain.getAttributionUid());
6156                 noteWifiScanStoppedLocked(uid);
6157                 StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED,
6158                         workChain.getUids(), workChain.getTags(),
6159                         StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF);
6160             }
6161         }
6162     }
6163
6164     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
6165         int N = ws.size();
6166         for (int i=0; i<N; i++) {
6167             noteWifiBatchedScanStartedLocked(ws.get(i), csph);
6168         }
6169
6170         final List<WorkChain> workChains = ws.getWorkChains();
6171         if (workChains != null) {
6172             for (int i = 0; i < workChains.size(); ++i) {
6173                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph);
6174             }
6175         }
6176     }
6177
6178     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
6179         int N = ws.size();
6180         for (int i=0; i<N; i++) {
6181             noteWifiBatchedScanStoppedLocked(ws.get(i));
6182         }
6183
6184         final List<WorkChain> workChains = ws.getWorkChains();
6185         if (workChains != null) {
6186             for (int i = 0; i < workChains.size(); ++i) {
6187                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid());
6188             }
6189         }
6190     }
6191
6192     private static String[] includeInStringArray(String[] array, String str) {
6193         if (ArrayUtils.indexOf(array, str) >= 0) {
6194             return array;
6195         }
6196         String[] newArray = new String[array.length+1];
6197         System.arraycopy(array, 0, newArray, 0, array.length);
6198         newArray[array.length] = str;
6199         return newArray;
6200     }
6201
6202     private static String[] excludeFromStringArray(String[] array, String str) {
6203         int index = ArrayUtils.indexOf(array, str);
6204         if (index >= 0) {
6205             String[] newArray = new String[array.length-1];
6206             if (index > 0) {
6207                 System.arraycopy(array, 0, newArray, 0, index);
6208             }
6209             if (index < array.length-1) {
6210                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
6211             }
6212             return newArray;
6213         }
6214         return array;
6215     }
6216
6217     public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
6218         if (TextUtils.isEmpty(iface)) return;
6219
6220         synchronized (mModemNetworkLock) {
6221             if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
6222                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
6223                 if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
6224             } else {
6225                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
6226                 if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
6227             }
6228         }
6229
6230         synchronized (mWifiNetworkLock) {
6231             if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
6232                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
6233                 if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
6234             } else {
6235                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
6236                 if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
6237             }
6238         }
6239     }
6240
6241     public String[] getWifiIfaces() {
6242         synchronized (mWifiNetworkLock) {
6243             return mWifiIfaces;
6244         }
6245     }
6246
6247     public String[] getMobileIfaces() {
6248         synchronized (mModemNetworkLock) {
6249             return mModemIfaces;
6250         }
6251     }
6252
6253     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
6254         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6255     }
6256
6257     @Override public int getScreenOnCount(int which) {
6258         return mScreenOnTimer.getCountLocked(which);
6259     }
6260
6261     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
6262         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6263     }
6264
6265     @Override public int getScreenDozeCount(int which) {
6266         return mScreenDozeTimer.getCountLocked(which);
6267     }
6268
6269     @Override public long getScreenBrightnessTime(int brightnessBin,
6270             long elapsedRealtimeUs, int which) {
6271         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
6272                 elapsedRealtimeUs, which);
6273     }
6274
6275     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
6276         return mScreenBrightnessTimer[brightnessBin];
6277     }
6278
6279     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
6280         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6281     }
6282
6283     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
6284         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6285     }
6286
6287     @Override public int getPowerSaveModeEnabledCount(int which) {
6288         return mPowerSaveModeEnabledTimer.getCountLocked(which);
6289     }
6290
6291     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
6292             int which) {
6293         switch (mode) {
6294             case DEVICE_IDLE_MODE_LIGHT:
6295                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6296             case DEVICE_IDLE_MODE_DEEP:
6297                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6298         }
6299         return 0;
6300     }
6301
6302     @Override public int getDeviceIdleModeCount(int mode, int which) {
6303         switch (mode) {
6304             case DEVICE_IDLE_MODE_LIGHT:
6305                 return mDeviceIdleModeLightTimer.getCountLocked(which);
6306             case DEVICE_IDLE_MODE_DEEP:
6307                 return mDeviceIdleModeFullTimer.getCountLocked(which);
6308         }
6309         return 0;
6310     }
6311
6312     @Override public long getLongestDeviceIdleModeTime(int mode) {
6313         switch (mode) {
6314             case DEVICE_IDLE_MODE_LIGHT:
6315                 return mLongestLightIdleTime;
6316             case DEVICE_IDLE_MODE_DEEP:
6317                 return mLongestFullIdleTime;
6318         }
6319         return 0;
6320     }
6321
6322     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
6323         switch (mode) {
6324             case DEVICE_IDLE_MODE_LIGHT:
6325                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6326             case DEVICE_IDLE_MODE_DEEP:
6327                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6328         }
6329         return 0;
6330     }
6331
6332     @Override public int getDeviceIdlingCount(int mode, int which) {
6333         switch (mode) {
6334             case DEVICE_IDLE_MODE_LIGHT:
6335                 return mDeviceLightIdlingTimer.getCountLocked(which);
6336             case DEVICE_IDLE_MODE_DEEP:
6337                 return mDeviceIdlingTimer.getCountLocked(which);
6338         }
6339         return 0;
6340     }
6341
6342     @Override public int getNumConnectivityChange(int which) {
6343         int val = mNumConnectivityChange;
6344         if (which == STATS_CURRENT) {
6345             val -= mLoadedNumConnectivityChange;
6346         } else if (which == STATS_SINCE_UNPLUGGED) {
6347             val -= mUnpluggedNumConnectivityChange;
6348         }
6349         return val;
6350     }
6351
6352     @Override public long getGpsSignalQualityTime(int strengthBin,
6353         long elapsedRealtimeUs, int which) {
6354         if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
6355             return 0;
6356         }
6357         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
6358             elapsedRealtimeUs, which);
6359     }
6360
6361     @Override public long getGpsBatteryDrainMaMs() {
6362         final double opVolt = mPowerProfile.getAveragePower(
6363             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
6364         if (opVolt == 0) {
6365             return 0;
6366         }
6367         double energyUsedMaMs = 0.0;
6368         final int which = STATS_SINCE_CHARGED;
6369         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
6370         for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
6371             energyUsedMaMs
6372                 += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
6373                 * (getGpsSignalQualityTime(i, rawRealtime, which) / 1000);
6374         }
6375         return (long) energyUsedMaMs;
6376     }
6377
6378     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
6379         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6380     }
6381
6382     @Override public int getPhoneOnCount(int which) {
6383         return mPhoneOnTimer.getCountLocked(which);
6384     }
6385
6386     @Override public long getPhoneSignalStrengthTime(int strengthBin,
6387             long elapsedRealtimeUs, int which) {
6388         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6389                 elapsedRealtimeUs, which);
6390     }
6391
6392     @Override public long getPhoneSignalScanningTime(
6393             long elapsedRealtimeUs, int which) {
6394         return mPhoneSignalScanningTimer.getTotalTimeLocked(
6395                 elapsedRealtimeUs, which);
6396     }
6397
6398     @Override public Timer getPhoneSignalScanningTimer() {
6399         return mPhoneSignalScanningTimer;
6400     }
6401
6402     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
6403         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
6404     }
6405
6406     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
6407         return mPhoneSignalStrengthsTimer[strengthBin];
6408     }
6409
6410     @Override public long getPhoneDataConnectionTime(int dataType,
6411             long elapsedRealtimeUs, int which) {
6412         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
6413                 elapsedRealtimeUs, which);
6414     }
6415
6416     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
6417         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
6418     }
6419
6420     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
6421         return mPhoneDataConnectionsTimer[dataType];
6422     }
6423
6424     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
6425         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6426     }
6427
6428     @Override public int getMobileRadioActiveCount(int which) {
6429         return mMobileRadioActiveTimer.getCountLocked(which);
6430     }
6431
6432     @Override public long getMobileRadioActiveAdjustedTime(int which) {
6433         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
6434     }
6435
6436     @Override public long getMobileRadioActiveUnknownTime(int which) {
6437         return mMobileRadioActiveUnknownTime.getCountLocked(which);
6438     }
6439
6440     @Override public int getMobileRadioActiveUnknownCount(int which) {
6441         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
6442     }
6443
6444     @Override public long getWifiMulticastWakelockTime(
6445             long elapsedRealtimeUs, int which) {
6446         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
6447                 elapsedRealtimeUs, which);
6448     }
6449
6450     @Override public int getWifiMulticastWakelockCount(int which) {
6451         return mWifiMulticastWakelockTimer.getCountLocked(which);
6452     }
6453
6454     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
6455         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6456     }
6457
6458     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
6459         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6460     }
6461
6462     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
6463         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6464     }
6465
6466     @Override public long getWifiStateTime(int wifiState,
6467             long elapsedRealtimeUs, int which) {
6468         return mWifiStateTimer[wifiState].getTotalTimeLocked(
6469                 elapsedRealtimeUs, which);
6470     }
6471
6472     @Override public int getWifiStateCount(int wifiState, int which) {
6473         return mWifiStateTimer[wifiState].getCountLocked(which);
6474     }
6475
6476     @Override public Timer getWifiStateTimer(int wifiState) {
6477         return mWifiStateTimer[wifiState];
6478     }
6479
6480     @Override public long getWifiSupplStateTime(int state,
6481             long elapsedRealtimeUs, int which) {
6482         return mWifiSupplStateTimer[state].getTotalTimeLocked(
6483                 elapsedRealtimeUs, which);
6484     }
6485
6486     @Override public int getWifiSupplStateCount(int state, int which) {
6487         return mWifiSupplStateTimer[state].getCountLocked(which);
6488     }
6489
6490     @Override public Timer getWifiSupplStateTimer(int state) {
6491         return mWifiSupplStateTimer[state];
6492     }
6493
6494     @Override public long getWifiSignalStrengthTime(int strengthBin,
6495             long elapsedRealtimeUs, int which) {
6496         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6497                 elapsedRealtimeUs, which);
6498     }
6499
6500     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
6501         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
6502     }
6503
6504     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
6505         return mWifiSignalStrengthsTimer[strengthBin];
6506     }
6507
6508     @Override
6509     public ControllerActivityCounter getBluetoothControllerActivity() {
6510         return mBluetoothActivity;
6511     }
6512
6513     @Override
6514     public ControllerActivityCounter getWifiControllerActivity() {
6515         return mWifiActivity;
6516     }
6517
6518     @Override
6519     public ControllerActivityCounter getModemControllerActivity() {
6520         return mModemActivity;
6521     }
6522
6523     @Override
6524     public boolean hasBluetoothActivityReporting() {
6525         return mHasBluetoothReporting;
6526     }
6527
6528     @Override
6529     public boolean hasWifiActivityReporting() {
6530         return mHasWifiReporting;
6531     }
6532
6533     @Override
6534     public boolean hasModemActivityReporting() {
6535         return mHasModemReporting;
6536     }
6537
6538     @Override
6539     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
6540         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6541     }
6542
6543     @Override
6544     public long getFlashlightOnCount(int which) {
6545         return mFlashlightOnTimer.getCountLocked(which);
6546     }
6547
6548     @Override
6549     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
6550         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6551     }
6552
6553     @Override
6554     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
6555         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6556     }
6557
6558     @Override
6559     public long getNetworkActivityBytes(int type, int which) {
6560         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
6561             return mNetworkByteActivityCounters[type].getCountLocked(which);
6562         } else {
6563             return 0;
6564         }
6565     }
6566
6567     @Override
6568     public long getNetworkActivityPackets(int type, int which) {
6569         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
6570             return mNetworkPacketActivityCounters[type].getCountLocked(which);
6571         } else {
6572             return 0;
6573         }
6574     }
6575
6576     @Override public long getStartClockTime() {
6577         final long currentTime = System.currentTimeMillis();
6578         if (ensureStartClockTime(currentTime)) {
6579             recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
6580                     mClocks.uptimeMillis());
6581         }
6582         return mStartClockTime;
6583     }
6584
6585     @Override public String getStartPlatformVersion() {
6586         return mStartPlatformVersion;
6587     }
6588
6589     @Override public String getEndPlatformVersion() {
6590         return mEndPlatformVersion;
6591     }
6592
6593     @Override public int getParcelVersion() {
6594         return VERSION;
6595     }
6596
6597     @Override public boolean getIsOnBattery() {
6598         return mOnBattery;
6599     }
6600
6601     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
6602         return mUidStats;
6603     }
6604
6605     private static void detachTimerIfNotNull(BatteryStatsImpl.Timer timer) {
6606         if (timer != null) {
6607             timer.detach();
6608         }
6609     }
6610
6611     private static boolean resetTimerIfNotNull(BatteryStatsImpl.Timer timer,
6612             boolean detachIfReset) {
6613         if (timer != null) {
6614             return timer.reset(detachIfReset);
6615         }
6616         return true;
6617     }
6618
6619     private static boolean resetTimerIfNotNull(DualTimer timer, boolean detachIfReset) {
6620         if (timer != null) {
6621             return timer.reset(detachIfReset);
6622         }
6623         return true;
6624     }
6625
6626     private static void detachLongCounterIfNotNull(LongSamplingCounter counter) {
6627         if (counter != null) {
6628             counter.detach();
6629         }
6630     }
6631
6632     private static void resetLongCounterIfNotNull(LongSamplingCounter counter,
6633             boolean detachIfReset) {
6634         if (counter != null) {
6635             counter.reset(detachIfReset);
6636         }
6637     }
6638
6639     /**
6640      * The statistics associated with a particular uid.
6641      */
6642     public static class Uid extends BatteryStats.Uid {
6643         /**
6644          * BatteryStatsImpl that we are associated with.
6645          */
6646         protected BatteryStatsImpl mBsi;
6647
6648         final int mUid;
6649
6650         /** TimeBase for when uid is in background and device is on battery. */
6651         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6652         public final TimeBase mOnBatteryBackgroundTimeBase;
6653         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6654         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
6655
6656         boolean mWifiRunning;
6657         StopwatchTimer mWifiRunningTimer;
6658
6659         boolean mFullWifiLockOut;
6660         StopwatchTimer mFullWifiLockTimer;
6661
6662         boolean mWifiScanStarted;
6663         DualTimer mWifiScanTimer;
6664
6665         static final int NO_BATCHED_SCAN_STARTED = -1;
6666         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
6667         StopwatchTimer[] mWifiBatchedScanTimer;
6668
6669         boolean mWifiMulticastEnabled;
6670         StopwatchTimer mWifiMulticastTimer;
6671
6672         StopwatchTimer mAudioTurnedOnTimer;
6673         StopwatchTimer mVideoTurnedOnTimer;
6674         StopwatchTimer mFlashlightTurnedOnTimer;
6675         StopwatchTimer mCameraTurnedOnTimer;
6676         StopwatchTimer mForegroundActivityTimer;
6677         StopwatchTimer mForegroundServiceTimer;
6678         /** Total time spent by the uid holding any partial wakelocks. */
6679         DualTimer mAggregatedPartialWakelockTimer;
6680         DualTimer mBluetoothScanTimer;
6681         DualTimer mBluetoothUnoptimizedScanTimer;
6682         Counter mBluetoothScanResultCounter;
6683         Counter mBluetoothScanResultBgCounter;
6684
6685         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
6686         StopwatchTimer[] mProcessStateTimer;
6687
6688         boolean mInForegroundService = false;
6689
6690         BatchTimer mVibratorOnTimer;
6691
6692         Counter[] mUserActivityCounters;
6693
6694         LongSamplingCounter[] mNetworkByteActivityCounters;
6695         LongSamplingCounter[] mNetworkPacketActivityCounters;
6696         LongSamplingCounter mMobileRadioActiveTime;
6697         LongSamplingCounter mMobileRadioActiveCount;
6698
6699         /**
6700          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
6701          */
6702         private LongSamplingCounter mMobileRadioApWakeupCount;
6703
6704         /**
6705          * How many times this UID woke up the Application Processor due to a Wifi packet.
6706          */
6707         private LongSamplingCounter mWifiRadioApWakeupCount;
6708
6709         /**
6710          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
6711          * Can be null if the UID has had no such activity.
6712          */
6713         private ControllerActivityCounterImpl mWifiControllerActivity;
6714
6715         /**
6716          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
6717          * Can be null if the UID has had no such activity.
6718          */
6719         private ControllerActivityCounterImpl mBluetoothControllerActivity;
6720
6721         /**
6722          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
6723          * Can be null if the UID has had no such activity.
6724          */
6725         private ControllerActivityCounterImpl mModemControllerActivity;
6726
6727         /**
6728          * The CPU times we had at the last history details update.
6729          */
6730         long mLastStepUserTime;
6731         long mLastStepSystemTime;
6732         long mCurStepUserTime;
6733         long mCurStepSystemTime;
6734
6735         LongSamplingCounter mUserCpuTime;
6736         LongSamplingCounter mSystemCpuTime;
6737         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
6738         LongSamplingCounter mCpuActiveTimeMs;
6739
6740         LongSamplingCounterArray mCpuFreqTimeMs;
6741         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
6742         LongSamplingCounterArray mCpuClusterTimesMs;
6743
6744         LongSamplingCounterArray[] mProcStateTimeMs;
6745         LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
6746
6747         IntArray mChildUids;
6748
6749         /**
6750          * The statistics we have collected for this uid's wake locks.
6751          */
6752         final OverflowArrayMap<Wakelock> mWakelockStats;
6753
6754         /**
6755          * The statistics we have collected for this uid's syncs.
6756          */
6757         final OverflowArrayMap<DualTimer> mSyncStats;
6758
6759         /**
6760          * The statistics we have collected for this uid's jobs.
6761          */
6762         final OverflowArrayMap<DualTimer> mJobStats;
6763
6764         /**
6765          * Count of the jobs that have completed and the reasons why they completed.
6766          */
6767         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
6768
6769         /**
6770          * Count of app launch events that had associated deferred job counts or info about
6771          * last time a job was run.
6772          */
6773         Counter mJobsDeferredEventCount;
6774
6775         /**
6776          * Count of deferred jobs that were pending when the app was launched or brought to
6777          * the foreground through a user interaction.
6778          */
6779         Counter mJobsDeferredCount;
6780
6781         /**
6782          * Sum of time since the last time a job was run for this app before it was launched.
6783          */
6784         LongSamplingCounter mJobsFreshnessTimeMs;
6785
6786         /**
6787          * Array of counts of instances where the time since the last job was run for the app
6788          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
6789          */
6790         final Counter[] mJobsFreshnessBuckets;
6791
6792         /**
6793          * The statistics we have collected for this uid's sensor activations.
6794          */
6795         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
6796
6797         /**
6798          * The statistics we have collected for this uid's processes.
6799          */
6800         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
6801
6802         /**
6803          * The statistics we have collected for this uid's processes.
6804          */
6805         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
6806
6807         /**
6808          * The transient wake stats we have collected for this uid's pids.
6809          */
6810         final SparseArray<Pid> mPids = new SparseArray<>();
6811
6812         /**
6813          * The list of WorkChains associated with active bluetooth scans.
6814          *
6815          * NOTE: This is a hack and it only needs to exist because there's a "reset" API that is
6816          * supposed to stop and log all WorkChains that were currently active.
6817          */
6818         ArrayList<WorkChain> mAllBluetoothChains = null;
6819         ArrayList<WorkChain> mUnoptimizedBluetoothChains = null;
6820
6821         public Uid(BatteryStatsImpl bsi, int uid) {
6822             mBsi = bsi;
6823             mUid = uid;
6824
6825             mOnBatteryBackgroundTimeBase = new TimeBase();
6826             mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6827                     mBsi.mClocks.elapsedRealtime() * 1000);
6828
6829             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase();
6830             mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6831                     mBsi.mClocks.elapsedRealtime() * 1000);
6832
6833             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6834             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6835             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6836             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
6837
6838             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
6839                 @Override public Wakelock instantiateObject() {
6840                     return new Wakelock(mBsi, Uid.this);
6841                 }
6842             };
6843             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6844                 @Override public DualTimer instantiateObject() {
6845                     return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
6846                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6847                 }
6848             };
6849             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6850                 @Override public DualTimer instantiateObject() {
6851                     return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
6852                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6853                 }
6854             };
6855
6856             mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
6857                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
6858             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
6859                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
6860             mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
6861                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6862             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
6863             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
6864                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
6865             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
6866             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
6867             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
6868             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6869             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
6870         }
6871
6872         @VisibleForTesting
6873         public void setProcessStateForTest(int procState) {
6874             mProcessState = procState;
6875         }
6876
6877         @Override
6878         public long[] getCpuFreqTimes(int which) {
6879             return nullIfAllZeros(mCpuFreqTimeMs, which);
6880         }
6881
6882         @Override
6883         public long[] getScreenOffCpuFreqTimes(int which) {
6884             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
6885         }
6886
6887         @Override
6888         public long getCpuActiveTime() {
6889             return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
6890         }
6891
6892         @Override
6893         public long[] getCpuClusterTimes() {
6894             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
6895         }
6896
6897
6898         @Override
6899         public long[] getCpuFreqTimes(int which, int procState) {
6900             if (which < 0 || which >= NUM_PROCESS_STATE) {
6901                 return null;
6902             }
6903             if (mProcStateTimeMs == null) {
6904                 return null;
6905             }
6906             if (!mBsi.mPerProcStateCpuTimesAvailable) {
6907                 mProcStateTimeMs = null;
6908                 return null;
6909             }
6910             return nullIfAllZeros(mProcStateTimeMs[procState], which);
6911         }
6912
6913         @Override
6914         public long[] getScreenOffCpuFreqTimes(int which, int procState) {
6915             if (which < 0 || which >= NUM_PROCESS_STATE) {
6916                 return null;
6917             }
6918             if (mProcStateScreenOffTimeMs == null) {
6919                 return null;
6920             }
6921             if (!mBsi.mPerProcStateCpuTimesAvailable) {
6922                 mProcStateScreenOffTimeMs = null;
6923                 return null;
6924             }
6925             return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which);
6926         }
6927
6928         public void addIsolatedUid(int isolatedUid) {
6929             if (mChildUids == null) {
6930                 mChildUids = new IntArray();
6931             } else if (mChildUids.indexOf(isolatedUid) >= 0) {
6932                 return;
6933             }
6934             mChildUids.add(isolatedUid);
6935         }
6936
6937         public void removeIsolatedUid(int isolatedUid) {
6938             final int idx = mChildUids == null ? -1 : mChildUids.indexOf(isolatedUid);
6939             if (idx < 0) {
6940                 return;
6941             }
6942             mChildUids.remove(idx);
6943         }
6944
6945         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
6946             if (cpuTimesMs == null) {
6947                 return null;
6948             }
6949             final long[] counts = cpuTimesMs.getCountsLocked(which);
6950             if (counts == null) {
6951                 return null;
6952             }
6953             // Return counts only if at least one of the elements is non-zero.
6954             for (int i = counts.length - 1; i >= 0; --i) {
6955                 if (counts[i] != 0) {
6956                     return counts;
6957                 }
6958             }
6959             return null;
6960         }
6961
6962         private void addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery) {
6963             if (mProcStateTimeMs == null) {
6964                 mProcStateTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
6965             }
6966             if (mProcStateTimeMs[procState] == null
6967                     || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
6968                 mProcStateTimeMs[procState] = new LongSamplingCounterArray(
6969                         mBsi.mOnBatteryTimeBase);
6970             }
6971             mProcStateTimeMs[procState].addCountLocked(cpuTimesMs, onBattery);
6972         }
6973
6974         private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs,
6975                 boolean onBatteryScreenOff) {
6976             if (mProcStateScreenOffTimeMs == null) {
6977                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
6978             }
6979             if (mProcStateScreenOffTimeMs[procState] == null
6980                     || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) {
6981                 mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
6982                         mBsi.mOnBatteryScreenOffTimeBase);
6983             }
6984             mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs, onBatteryScreenOff);
6985         }
6986
6987         @Override
6988         public Timer getAggregatedPartialWakelockTimer() {
6989             return mAggregatedPartialWakelockTimer;
6990         }
6991
6992         @Override
6993         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
6994             return mWakelockStats.getMap();
6995         }
6996
6997         @Override
6998         public Timer getMulticastWakelockStats() {
6999             return mWifiMulticastTimer;
7000         }
7001
7002         @Override
7003         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
7004             return mSyncStats.getMap();
7005         }
7006
7007         @Override
7008         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
7009             return mJobStats.getMap();
7010         }
7011
7012         @Override
7013         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
7014             return mJobCompletions;
7015         }
7016
7017         @Override
7018         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
7019             return mSensorStats;
7020         }
7021
7022         @Override
7023         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
7024             return mProcessStats;
7025         }
7026
7027         @Override
7028         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
7029             return mPackageStats;
7030         }
7031
7032         @Override
7033         public int getUid() {
7034             return mUid;
7035         }
7036
7037         @Override
7038         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
7039             if (!mWifiRunning) {
7040                 mWifiRunning = true;
7041                 if (mWifiRunningTimer == null) {
7042                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
7043                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
7044                 }
7045                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
7046             }
7047         }
7048
7049         @Override
7050         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
7051             if (mWifiRunning) {
7052                 mWifiRunning = false;
7053                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
7054             }
7055         }
7056
7057         @Override
7058         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
7059             if (!mFullWifiLockOut) {
7060                 mFullWifiLockOut = true;
7061                 if (mFullWifiLockTimer == null) {
7062                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
7063                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
7064                 }
7065                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
7066             }
7067         }
7068
7069         @Override
7070         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
7071             if (mFullWifiLockOut) {
7072                 mFullWifiLockOut = false;
7073                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
7074             }
7075         }
7076
7077         @Override
7078         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
7079             if (!mWifiScanStarted) {
7080                 mWifiScanStarted = true;
7081                 if (mWifiScanTimer == null) {
7082                     mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
7083                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
7084                             mOnBatteryBackgroundTimeBase);
7085                 }
7086                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
7087             }
7088         }
7089
7090         @Override
7091         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
7092             if (mWifiScanStarted) {
7093                 mWifiScanStarted = false;
7094                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
7095             }
7096         }
7097
7098         @Override
7099         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
7100             int bin = 0;
7101             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
7102                 csph = csph >> 3;
7103                 bin++;
7104             }
7105
7106             if (mWifiBatchedScanBinStarted == bin) return;
7107
7108             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7109                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7110                         stopRunningLocked(elapsedRealtimeMs);
7111             }
7112             mWifiBatchedScanBinStarted = bin;
7113             if (mWifiBatchedScanTimer[bin] == null) {
7114                 makeWifiBatchedScanBin(bin, null);
7115             }
7116             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
7117         }
7118
7119         @Override
7120         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
7121             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7122                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7123                         stopRunningLocked(elapsedRealtimeMs);
7124                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7125             }
7126         }
7127
7128         @Override
7129         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
7130             if (!mWifiMulticastEnabled) {
7131                 mWifiMulticastEnabled = true;
7132                 if (mWifiMulticastTimer == null) {
7133                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7134                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
7135                 }
7136                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
7137                 StatsLog.write_non_chained(
7138                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null,
7139                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__ON);
7140             }
7141         }
7142
7143         @Override
7144         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
7145             if (mWifiMulticastEnabled) {
7146                 mWifiMulticastEnabled = false;
7147                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
7148                 StatsLog.write_non_chained(
7149                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null,
7150                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__OFF);
7151             }
7152         }
7153
7154         @Override
7155         public ControllerActivityCounter getWifiControllerActivity() {
7156             return mWifiControllerActivity;
7157         }
7158
7159         @Override
7160         public ControllerActivityCounter getBluetoothControllerActivity() {
7161             return mBluetoothControllerActivity;
7162         }
7163
7164         @Override
7165         public ControllerActivityCounter getModemControllerActivity() {
7166             return mModemControllerActivity;
7167         }
7168
7169         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
7170             if (mWifiControllerActivity == null) {
7171                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7172                         NUM_BT_TX_LEVELS);
7173             }
7174             return mWifiControllerActivity;
7175         }
7176
7177         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
7178             if (mBluetoothControllerActivity == null) {
7179                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7180                         NUM_BT_TX_LEVELS);
7181             }
7182             return mBluetoothControllerActivity;
7183         }
7184
7185         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
7186             if (mModemControllerActivity == null) {
7187                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7188                         ModemActivityInfo.TX_POWER_LEVELS);
7189             }
7190             return mModemControllerActivity;
7191         }
7192
7193         public StopwatchTimer createAudioTurnedOnTimerLocked() {
7194             if (mAudioTurnedOnTimer == null) {
7195                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
7196                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7197             }
7198             return mAudioTurnedOnTimer;
7199         }
7200
7201         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
7202             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7203             StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null,
7204                     StatsLog.AUDIO_STATE_CHANGED__STATE__ON);
7205         }
7206
7207         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
7208             if (mAudioTurnedOnTimer != null) {
7209                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7210                 if (!mAudioTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
7211                     StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null,
7212                             StatsLog.AUDIO_STATE_CHANGED__STATE__OFF);
7213                 }
7214             }
7215         }
7216
7217         public void noteResetAudioLocked(long elapsedRealtimeMs) {
7218             if (mAudioTurnedOnTimer != null) {
7219                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7220                 StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null,
7221                         StatsLog.AUDIO_STATE_CHANGED__STATE__OFF);
7222             }
7223         }
7224
7225         public StopwatchTimer createVideoTurnedOnTimerLocked() {
7226             if (mVideoTurnedOnTimer == null) {
7227                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
7228                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7229             }
7230             return mVideoTurnedOnTimer;
7231         }
7232
7233         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
7234             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7235             StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), null,
7236                     StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__ON);
7237         }
7238
7239         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
7240             if (mVideoTurnedOnTimer != null) {
7241                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7242                 if (!mVideoTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
7243                     StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(),
7244                             null, StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__OFF);
7245                 }
7246             }
7247         }
7248
7249         public void noteResetVideoLocked(long elapsedRealtimeMs) {
7250             if (mVideoTurnedOnTimer != null) {
7251                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7252                 StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), null,
7253                         StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__OFF);
7254             }
7255         }
7256
7257         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
7258             if (mFlashlightTurnedOnTimer == null) {
7259                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7260                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7261             }
7262             return mFlashlightTurnedOnTimer;
7263         }
7264
7265         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
7266             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7267             StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null,
7268                     StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__ON);
7269         }
7270
7271         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
7272             if (mFlashlightTurnedOnTimer != null) {
7273                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7274                 if (!mFlashlightTurnedOnTimer.isRunningLocked()) {
7275                     StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null,
7276                             StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF);
7277                 }
7278             }
7279         }
7280
7281         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
7282             if (mFlashlightTurnedOnTimer != null) {
7283                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7284                 StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null,
7285                         StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF);
7286             }
7287         }
7288
7289         public StopwatchTimer createCameraTurnedOnTimerLocked() {
7290             if (mCameraTurnedOnTimer == null) {
7291                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
7292                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7293             }
7294             return mCameraTurnedOnTimer;
7295         }
7296
7297         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
7298             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7299             StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null,
7300                     StatsLog.CAMERA_STATE_CHANGED__STATE__ON);
7301         }
7302
7303         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
7304             if (mCameraTurnedOnTimer != null) {
7305                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7306                 if (!mCameraTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
7307                     StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null,
7308                             StatsLog.CAMERA_STATE_CHANGED__STATE__OFF);
7309                 }
7310             }
7311         }
7312
7313         public void noteResetCameraLocked(long elapsedRealtimeMs) {
7314             if (mCameraTurnedOnTimer != null) {
7315                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7316                 StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null,
7317                         StatsLog.CAMERA_STATE_CHANGED__STATE__OFF);
7318             }
7319         }
7320
7321         public StopwatchTimer createForegroundActivityTimerLocked() {
7322             if (mForegroundActivityTimer == null) {
7323                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7324                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
7325             }
7326             return mForegroundActivityTimer;
7327         }
7328
7329         public StopwatchTimer createForegroundServiceTimerLocked() {
7330             if (mForegroundServiceTimer == null) {
7331                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7332                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
7333             }
7334             return mForegroundServiceTimer;
7335         }
7336
7337         public DualTimer createAggregatedPartialWakelockTimerLocked() {
7338             if (mAggregatedPartialWakelockTimer == null) {
7339                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
7340                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
7341                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
7342             }
7343             return mAggregatedPartialWakelockTimer;
7344         }
7345
7346         public DualTimer createBluetoothScanTimerLocked() {
7347             if (mBluetoothScanTimer == null) {
7348                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
7349                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
7350                         mOnBatteryBackgroundTimeBase);
7351             }
7352             return mBluetoothScanTimer;
7353         }
7354
7355         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
7356             if (mBluetoothUnoptimizedScanTimer == null) {
7357                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
7358                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
7359                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7360             }
7361             return mBluetoothUnoptimizedScanTimer;
7362         }
7363
7364         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
7365                 boolean isUnoptimized) {
7366             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7367             if (isUnoptimized) {
7368                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7369             }
7370         }
7371
7372         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
7373             if (mBluetoothScanTimer != null) {
7374                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
7375             }
7376             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
7377                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
7378             }
7379         }
7380
7381         public void addBluetoothWorkChain(WorkChain workChain, boolean isUnoptimized) {
7382             if (mAllBluetoothChains == null) {
7383                 mAllBluetoothChains = new ArrayList<WorkChain>(4);
7384             }
7385
7386             if (isUnoptimized && mUnoptimizedBluetoothChains == null) {
7387                 mUnoptimizedBluetoothChains = new ArrayList<WorkChain>(4);
7388             }
7389
7390             mAllBluetoothChains.add(workChain);
7391             if (isUnoptimized) {
7392                 mUnoptimizedBluetoothChains.add(workChain);
7393             }
7394         }
7395
7396         public void removeBluetoothWorkChain(WorkChain workChain, boolean isUnoptimized) {
7397             if (mAllBluetoothChains != null) {
7398                 mAllBluetoothChains.remove(workChain);
7399             }
7400
7401             if (isUnoptimized && mUnoptimizedBluetoothChains != null) {
7402                 mUnoptimizedBluetoothChains.remove(workChain);
7403             }
7404         }
7405
7406         public List<WorkChain> getAllBluetoothWorkChains() {
7407             return mAllBluetoothChains;
7408         }
7409
7410         public List<WorkChain> getUnoptimizedBluetoothWorkChains() {
7411             return mUnoptimizedBluetoothChains;
7412         }
7413
7414
7415         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
7416             if (mBluetoothScanTimer != null) {
7417                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7418             }
7419             if (mBluetoothUnoptimizedScanTimer != null) {
7420                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7421             }
7422         }
7423
7424         public Counter createBluetoothScanResultCounterLocked() {
7425             if (mBluetoothScanResultCounter == null) {
7426                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
7427             }
7428             return mBluetoothScanResultCounter;
7429         }
7430
7431         public Counter createBluetoothScanResultBgCounterLocked() {
7432             if (mBluetoothScanResultBgCounter == null) {
7433                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
7434             }
7435             return mBluetoothScanResultBgCounter;
7436         }
7437
7438         public void noteBluetoothScanResultsLocked(int numNewResults) {
7439             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
7440             // Uses background timebase, so the count will only be incremented if uid in background.
7441             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
7442         }
7443
7444         @Override
7445         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
7446             // We always start, since we want multiple foreground PIDs to nest
7447             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
7448         }
7449
7450         @Override
7451         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
7452             if (mForegroundActivityTimer != null) {
7453                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
7454             }
7455         }
7456
7457         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
7458             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
7459         }
7460
7461         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
7462             if (mForegroundServiceTimer != null) {
7463                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
7464             }
7465         }
7466
7467         public BatchTimer createVibratorOnTimerLocked() {
7468             if (mVibratorOnTimer == null) {
7469                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
7470                         mBsi.mOnBatteryTimeBase);
7471             }
7472             return mVibratorOnTimer;
7473         }
7474
7475         public void noteVibratorOnLocked(long durationMillis) {
7476             createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
7477         }
7478
7479         public void noteVibratorOffLocked() {
7480             if (mVibratorOnTimer != null) {
7481                 mVibratorOnTimer.abortLastDuration(mBsi);
7482             }
7483         }
7484
7485         @Override
7486         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
7487             if (mWifiRunningTimer == null) {
7488                 return 0;
7489             }
7490             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7491         }
7492
7493         @Override
7494         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
7495             if (mFullWifiLockTimer == null) {
7496                 return 0;
7497             }
7498             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7499         }
7500
7501         @Override
7502         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
7503             if (mWifiScanTimer == null) {
7504                 return 0;
7505             }
7506             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7507         }
7508
7509         @Override
7510         public int getWifiScanCount(int which) {
7511             if (mWifiScanTimer == null) {
7512                 return 0;
7513             }
7514             return mWifiScanTimer.getCountLocked(which);
7515         }
7516
7517         @Override
7518         public Timer getWifiScanTimer() {
7519             return mWifiScanTimer;
7520         }
7521
7522         @Override
7523         public int getWifiScanBackgroundCount(int which) {
7524             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7525                 return 0;
7526             }
7527             return mWifiScanTimer.getSubTimer().getCountLocked(which);
7528         }
7529
7530         @Override
7531         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
7532             if (mWifiScanTimer == null) {
7533                 return 0;
7534             }
7535             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7536             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7537         }
7538
7539         @Override
7540         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
7541             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7542                 return 0;
7543             }
7544             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7545             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7546         }
7547
7548         @Override
7549         public Timer getWifiScanBackgroundTimer() {
7550             if (mWifiScanTimer == null) {
7551                 return null;
7552             }
7553             return mWifiScanTimer.getSubTimer();
7554         }
7555
7556         @Override
7557         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
7558             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7559             if (mWifiBatchedScanTimer[csphBin] == null) {
7560                 return 0;
7561             }
7562             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
7563         }
7564
7565         @Override
7566         public int getWifiBatchedScanCount(int csphBin, int which) {
7567             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7568             if (mWifiBatchedScanTimer[csphBin] == null) {
7569                 return 0;
7570             }
7571             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
7572         }
7573
7574         @Override
7575         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
7576             if (mWifiMulticastTimer == null) {
7577                 return 0;
7578             }
7579             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7580         }
7581
7582         @Override
7583         public Timer getAudioTurnedOnTimer() {
7584             return mAudioTurnedOnTimer;
7585         }
7586
7587         @Override
7588         public Timer getVideoTurnedOnTimer() {
7589             return mVideoTurnedOnTimer;
7590         }
7591
7592         @Override
7593         public Timer getFlashlightTurnedOnTimer() {
7594             return mFlashlightTurnedOnTimer;
7595         }
7596
7597         @Override
7598         public Timer getCameraTurnedOnTimer() {
7599             return mCameraTurnedOnTimer;
7600         }
7601
7602         @Override
7603         public Timer getForegroundActivityTimer() {
7604             return mForegroundActivityTimer;
7605         }
7606
7607         @Override
7608         public Timer getForegroundServiceTimer() {
7609             return mForegroundServiceTimer;
7610         }
7611
7612         @Override
7613         public Timer getBluetoothScanTimer() {
7614             return mBluetoothScanTimer;
7615         }
7616
7617         @Override
7618         public Timer getBluetoothScanBackgroundTimer() {
7619             if (mBluetoothScanTimer == null) {
7620                 return null;
7621             }
7622             return mBluetoothScanTimer.getSubTimer();
7623         }
7624
7625         @Override
7626         public Timer getBluetoothUnoptimizedScanTimer() {
7627             return mBluetoothUnoptimizedScanTimer;
7628         }
7629
7630         @Override
7631         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
7632             if (mBluetoothUnoptimizedScanTimer == null) {
7633                 return null;
7634             }
7635             return mBluetoothUnoptimizedScanTimer.getSubTimer();
7636         }
7637
7638         @Override
7639         public Counter getBluetoothScanResultCounter() {
7640             return mBluetoothScanResultCounter;
7641         }
7642
7643         @Override
7644         public Counter getBluetoothScanResultBgCounter() {
7645             return mBluetoothScanResultBgCounter;
7646         }
7647
7648         void makeProcessState(int i, Parcel in) {
7649             if (i < 0 || i >= NUM_PROCESS_STATE) return;
7650
7651             if (in == null) {
7652                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7653                         mBsi.mOnBatteryTimeBase);
7654             } else {
7655                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7656                         mBsi.mOnBatteryTimeBase, in);
7657             }
7658         }
7659
7660         @Override
7661         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
7662             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
7663             if (mProcessStateTimer[state] == null) {
7664                 return 0;
7665             }
7666             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
7667         }
7668
7669         @Override
7670         public Timer getProcessStateTimer(int state) {
7671             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
7672             return mProcessStateTimer[state];
7673         }
7674
7675         @Override
7676         public Timer getVibratorOnTimer() {
7677             return mVibratorOnTimer;
7678         }
7679
7680         @Override
7681         public void noteUserActivityLocked(int type) {
7682             if (mUserActivityCounters == null) {
7683                 initUserActivityLocked();
7684             }
7685             if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
7686                 mUserActivityCounters[type].stepAtomic();
7687             } else {
7688                 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
7689                         new Throwable());
7690             }
7691         }
7692
7693         @Override
7694         public boolean hasUserActivity() {
7695             return mUserActivityCounters != null;
7696         }
7697
7698         @Override
7699         public int getUserActivityCount(int type, int which) {
7700             if (mUserActivityCounters == null) {
7701                 return 0;
7702             }
7703             return mUserActivityCounters[type].getCountLocked(which);
7704         }
7705
7706         void makeWifiBatchedScanBin(int i, Parcel in) {
7707             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
7708
7709             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
7710             if (collected == null) {
7711                 collected = new ArrayList<StopwatchTimer>();
7712                 mBsi.mWifiBatchedScanTimers.put(i, collected);
7713             }
7714             if (in == null) {
7715                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7716                         collected, mBsi.mOnBatteryTimeBase);
7717             } else {
7718                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7719                         collected, mBsi.mOnBatteryTimeBase, in);
7720             }
7721         }
7722
7723
7724         void initUserActivityLocked() {
7725             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
7726             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7727                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
7728             }
7729         }
7730
7731         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
7732             if (mNetworkByteActivityCounters == null) {
7733                 initNetworkActivityLocked();
7734             }
7735             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
7736                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
7737                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
7738             } else {
7739                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
7740                         new Throwable());
7741             }
7742         }
7743
7744         void noteMobileRadioActiveTimeLocked(long batteryUptime) {
7745             if (mNetworkByteActivityCounters == null) {
7746                 initNetworkActivityLocked();
7747             }
7748             mMobileRadioActiveTime.addCountLocked(batteryUptime);
7749             mMobileRadioActiveCount.addCountLocked(1);
7750         }
7751
7752         @Override
7753         public boolean hasNetworkActivity() {
7754             return mNetworkByteActivityCounters != null;
7755         }
7756
7757         @Override
7758         public long getNetworkActivityBytes(int type, int which) {
7759             if (mNetworkByteActivityCounters != null && type >= 0
7760                     && type < mNetworkByteActivityCounters.length) {
7761                 return mNetworkByteActivityCounters[type].getCountLocked(which);
7762             } else {
7763                 return 0;
7764             }
7765         }
7766
7767         @Override
7768         public long getNetworkActivityPackets(int type, int which) {
7769             if (mNetworkPacketActivityCounters != null && type >= 0
7770                     && type < mNetworkPacketActivityCounters.length) {
7771                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
7772             } else {
7773                 return 0;
7774             }
7775         }
7776
7777         @Override
7778         public long getMobileRadioActiveTime(int which) {
7779             return mMobileRadioActiveTime != null
7780                     ? mMobileRadioActiveTime.getCountLocked(which) : 0;
7781         }
7782
7783         @Override
7784         public int getMobileRadioActiveCount(int which) {
7785             return mMobileRadioActiveCount != null
7786                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
7787         }
7788
7789         @Override
7790         public long getUserCpuTimeUs(int which) {
7791             return mUserCpuTime.getCountLocked(which);
7792         }
7793
7794         @Override
7795         public long getSystemCpuTimeUs(int which) {
7796             return mSystemCpuTime.getCountLocked(which);
7797         }
7798
7799         @Override
7800         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
7801             if (mCpuClusterSpeedTimesUs != null) {
7802                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
7803                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
7804                     if (cpuSpeedTimesUs != null) {
7805                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
7806                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
7807                             if (c != null) {
7808                                 return c.getCountLocked(which);
7809                             }
7810                         }
7811                     }
7812                 }
7813             }
7814             return 0;
7815         }
7816
7817         public void noteMobileRadioApWakeupLocked() {
7818             if (mMobileRadioApWakeupCount == null) {
7819                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7820             }
7821             mMobileRadioApWakeupCount.addCountLocked(1);
7822         }
7823
7824         @Override
7825         public long getMobileRadioApWakeupCount(int which) {
7826             if (mMobileRadioApWakeupCount != null) {
7827                 return mMobileRadioApWakeupCount.getCountLocked(which);
7828             }
7829             return 0;
7830         }
7831
7832         public void noteWifiRadioApWakeupLocked() {
7833             if (mWifiRadioApWakeupCount == null) {
7834                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7835             }
7836             mWifiRadioApWakeupCount.addCountLocked(1);
7837         }
7838
7839         @Override
7840         public long getWifiRadioApWakeupCount(int which) {
7841             if (mWifiRadioApWakeupCount != null) {
7842                 return mWifiRadioApWakeupCount.getCountLocked(which);
7843             }
7844             return 0;
7845         }
7846
7847         @Override
7848         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
7849             sb.setLength(0);
7850             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7851             if (deferredEventCount == 0) {
7852                 return;
7853             }
7854             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7855             final long averageLatency = deferredEventCount != 0
7856                     ? mJobsFreshnessTimeMs.getCountLocked(which) / deferredEventCount
7857                     : 0L;
7858             sb.append(deferredEventCount); sb.append(',');
7859             sb.append(deferredCount); sb.append(',');
7860             sb.append(averageLatency);
7861             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7862                 if (mJobsFreshnessBuckets[i] == null) {
7863                     sb.append(",0");
7864                 } else {
7865                     sb.append(",");
7866                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7867                 }
7868             }
7869         }
7870
7871         @Override
7872         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
7873             sb.setLength(0);
7874             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7875             if (deferredEventCount == 0) {
7876                 return;
7877             }
7878             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7879             final long averageLatency = deferredEventCount != 0
7880                     ? mJobsFreshnessTimeMs.getCountLocked(which) / deferredEventCount
7881                     : 0L;
7882             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
7883             sb.append("count="); sb.append(deferredCount); sb.append(", ");
7884             sb.append("avgLatency="); sb.append(averageLatency); sb.append(", ");
7885             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7886                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
7887                 if (mJobsFreshnessBuckets[i] == null) {
7888                     sb.append("0");
7889                 } else {
7890                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7891                 }
7892                 sb.append(" ");
7893             }
7894         }
7895
7896         void initNetworkActivityLocked() {
7897             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7898             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7899             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7900                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7901                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7902             }
7903             mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7904             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7905         }
7906
7907         /**
7908          * Clear all stats for this uid.  Returns true if the uid is completely
7909          * inactive so can be dropped.
7910          */
7911         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
7912         public boolean reset(long uptime, long realtime) {
7913             boolean active = false;
7914
7915             mOnBatteryBackgroundTimeBase.init(uptime, realtime);
7916             mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
7917
7918             if (mWifiRunningTimer != null) {
7919                 active |= !mWifiRunningTimer.reset(false);
7920                 active |= mWifiRunning;
7921             }
7922             if (mFullWifiLockTimer != null) {
7923                 active |= !mFullWifiLockTimer.reset(false);
7924                 active |= mFullWifiLockOut;
7925             }
7926             if (mWifiScanTimer != null) {
7927                 active |= !mWifiScanTimer.reset(false);
7928                 active |= mWifiScanStarted;
7929             }
7930             if (mWifiBatchedScanTimer != null) {
7931                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7932                     if (mWifiBatchedScanTimer[i] != null) {
7933                         active |= !mWifiBatchedScanTimer[i].reset(false);
7934                     }
7935                 }
7936                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
7937             }
7938             if (mWifiMulticastTimer != null) {
7939                 active |= !mWifiMulticastTimer.reset(false);
7940                 active |= mWifiMulticastEnabled;
7941             }
7942
7943             active |= !resetTimerIfNotNull(mAudioTurnedOnTimer, false);
7944             active |= !resetTimerIfNotNull(mVideoTurnedOnTimer, false);
7945             active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false);
7946             active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false);
7947             active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
7948             active |= !resetTimerIfNotNull(mForegroundServiceTimer, false);
7949             active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false);
7950             active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
7951             active |= !resetTimerIfNotNull(mBluetoothUnoptimizedScanTimer, false);
7952             if (mBluetoothScanResultCounter != null) {
7953                 mBluetoothScanResultCounter.reset(false);
7954             }
7955             if (mBluetoothScanResultBgCounter != null) {
7956                 mBluetoothScanResultBgCounter.reset(false);
7957             }
7958
7959             if (mProcessStateTimer != null) {
7960                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
7961                     if (mProcessStateTimer[i] != null) {
7962                         active |= !mProcessStateTimer[i].reset(false);
7963                     }
7964                 }
7965                 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
7966             }
7967             if (mVibratorOnTimer != null) {
7968                 if (mVibratorOnTimer.reset(false)) {
7969                     mVibratorOnTimer.detach();
7970                     mVibratorOnTimer = null;
7971                 } else {
7972                     active = true;
7973                 }
7974             }
7975
7976             if (mUserActivityCounters != null) {
7977                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7978                     mUserActivityCounters[i].reset(false);
7979                 }
7980             }
7981
7982             if (mNetworkByteActivityCounters != null) {
7983                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7984                     mNetworkByteActivityCounters[i].reset(false);
7985                     mNetworkPacketActivityCounters[i].reset(false);
7986                 }
7987                 mMobileRadioActiveTime.reset(false);
7988                 mMobileRadioActiveCount.reset(false);
7989             }
7990
7991             if (mWifiControllerActivity != null) {
7992                 mWifiControllerActivity.reset(false);
7993             }
7994
7995             if (mBluetoothControllerActivity != null) {
7996                 mBluetoothControllerActivity.reset(false);
7997             }
7998
7999             if (mModemControllerActivity != null) {
8000                 mModemControllerActivity.reset(false);
8001             }
8002
8003             mUserCpuTime.reset(false);
8004             mSystemCpuTime.reset(false);
8005
8006             if (mCpuClusterSpeedTimesUs != null) {
8007                 for (LongSamplingCounter[] speeds : mCpuClusterSpeedTimesUs) {
8008                     if (speeds != null) {
8009                         for (LongSamplingCounter speed : speeds) {
8010                             if (speed != null) {
8011                                 speed.reset(false);
8012                             }
8013                         }
8014                     }
8015                 }
8016             }
8017
8018             if (mCpuFreqTimeMs != null) {
8019                 mCpuFreqTimeMs.reset(false);
8020             }
8021             if (mScreenOffCpuFreqTimeMs != null) {
8022                 mScreenOffCpuFreqTimeMs.reset(false);
8023             }
8024
8025             mCpuActiveTimeMs.reset(false);
8026             mCpuClusterTimesMs.reset(false);
8027
8028             if (mProcStateTimeMs != null) {
8029                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
8030                     if (counters != null) {
8031                         counters.reset(false);
8032                     }
8033                 }
8034             }
8035             if (mProcStateScreenOffTimeMs != null) {
8036                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
8037                     if (counters != null) {
8038                         counters.reset(false);
8039                     }
8040                 }
8041             }
8042
8043             resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false);
8044             resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false);
8045
8046             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8047             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
8048                 Wakelock wl = wakeStats.valueAt(iw);
8049                 if (wl.reset()) {
8050                     wakeStats.removeAt(iw);
8051                 } else {
8052                     active = true;
8053                 }
8054             }
8055             mWakelockStats.cleanup();
8056             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8057             for (int is=syncStats.size()-1; is>=0; is--) {
8058                 DualTimer timer = syncStats.valueAt(is);
8059                 if (timer.reset(false)) {
8060                     syncStats.removeAt(is);
8061                     timer.detach();
8062                 } else {
8063                     active = true;
8064                 }
8065             }
8066             mSyncStats.cleanup();
8067             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8068             for (int ij=jobStats.size()-1; ij>=0; ij--) {
8069                 DualTimer timer = jobStats.valueAt(ij);
8070                 if (timer.reset(false)) {
8071                     jobStats.removeAt(ij);
8072                     timer.detach();
8073                 } else {
8074                     active = true;
8075                 }
8076             }
8077             mJobStats.cleanup();
8078             mJobCompletions.clear();
8079
8080             mJobsDeferredEventCount.reset(false);
8081             mJobsDeferredCount.reset(false);
8082             mJobsFreshnessTimeMs.reset(false);
8083             for (int ij = 0; ij < JOB_FRESHNESS_BUCKETS.length; ij++) {
8084                 if (mJobsFreshnessBuckets[ij] != null) {
8085                     mJobsFreshnessBuckets[ij].reset(false);
8086                 }
8087             }
8088
8089             for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
8090                 Sensor s = mSensorStats.valueAt(ise);
8091                 if (s.reset()) {
8092                     mSensorStats.removeAt(ise);
8093                 } else {
8094                     active = true;
8095                 }
8096             }
8097
8098             for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
8099                 Proc proc = mProcessStats.valueAt(ip);
8100                 proc.detach();
8101             }
8102             mProcessStats.clear();
8103             if (mPids.size() > 0) {
8104                 for (int i=mPids.size()-1; i>=0; i--) {
8105                     Pid pid = mPids.valueAt(i);
8106                     if (pid.mWakeNesting > 0) {
8107                         active = true;
8108                     } else {
8109                         mPids.removeAt(i);
8110                     }
8111                 }
8112             }
8113             if (mPackageStats.size() > 0) {
8114                 Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
8115                 while (it.hasNext()) {
8116                     Map.Entry<String, Pkg> pkgEntry = it.next();
8117                     Pkg p = pkgEntry.getValue();
8118                     p.detach();
8119                     if (p.mServiceStats.size() > 0) {
8120                         Iterator<Map.Entry<String, Pkg.Serv>> it2
8121                                 = p.mServiceStats.entrySet().iterator();
8122                         while (it2.hasNext()) {
8123                             Map.Entry<String, Pkg.Serv> servEntry = it2.next();
8124                             servEntry.getValue().detach();
8125                         }
8126                     }
8127                 }
8128                 mPackageStats.clear();
8129             }
8130
8131             mLastStepUserTime = mLastStepSystemTime = 0;
8132             mCurStepUserTime = mCurStepSystemTime = 0;
8133
8134             if (!active) {
8135                 if (mWifiRunningTimer != null) {
8136                     mWifiRunningTimer.detach();
8137                 }
8138                 if (mFullWifiLockTimer != null) {
8139                     mFullWifiLockTimer.detach();
8140                 }
8141                 if (mWifiScanTimer != null) {
8142                     mWifiScanTimer.detach();
8143                 }
8144                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8145                     if (mWifiBatchedScanTimer[i] != null) {
8146                         mWifiBatchedScanTimer[i].detach();
8147                     }
8148                 }
8149                 if (mWifiMulticastTimer != null) {
8150                     mWifiMulticastTimer.detach();
8151                 }
8152                 if (mAudioTurnedOnTimer != null) {
8153                     mAudioTurnedOnTimer.detach();
8154                     mAudioTurnedOnTimer = null;
8155                 }
8156                 if (mVideoTurnedOnTimer != null) {
8157                     mVideoTurnedOnTimer.detach();
8158                     mVideoTurnedOnTimer = null;
8159                 }
8160                 if (mFlashlightTurnedOnTimer != null) {
8161                     mFlashlightTurnedOnTimer.detach();
8162                     mFlashlightTurnedOnTimer = null;
8163                 }
8164                 if (mCameraTurnedOnTimer != null) {
8165                     mCameraTurnedOnTimer.detach();
8166                     mCameraTurnedOnTimer = null;
8167                 }
8168                 if (mForegroundActivityTimer != null) {
8169                     mForegroundActivityTimer.detach();
8170                     mForegroundActivityTimer = null;
8171                 }
8172                 if (mForegroundServiceTimer != null) {
8173                     mForegroundServiceTimer.detach();
8174                     mForegroundServiceTimer = null;
8175                 }
8176                 if (mAggregatedPartialWakelockTimer != null) {
8177                     mAggregatedPartialWakelockTimer.detach();
8178                     mAggregatedPartialWakelockTimer = null;
8179                 }
8180                 if (mBluetoothScanTimer != null) {
8181                     mBluetoothScanTimer.detach();
8182                     mBluetoothScanTimer = null;
8183                 }
8184                 if (mBluetoothUnoptimizedScanTimer != null) {
8185                     mBluetoothUnoptimizedScanTimer.detach();
8186                     mBluetoothUnoptimizedScanTimer = null;
8187                 }
8188                 if (mBluetoothScanResultCounter != null) {
8189                     mBluetoothScanResultCounter.detach();
8190                     mBluetoothScanResultCounter = null;
8191                 }
8192                 if (mBluetoothScanResultBgCounter != null) {
8193                     mBluetoothScanResultBgCounter.detach();
8194                     mBluetoothScanResultBgCounter = null;
8195                 }
8196                 if (mUserActivityCounters != null) {
8197                     for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8198                         mUserActivityCounters[i].detach();
8199                     }
8200                 }
8201                 if (mNetworkByteActivityCounters != null) {
8202                     for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8203                         mNetworkByteActivityCounters[i].detach();
8204                         mNetworkPacketActivityCounters[i].detach();
8205                     }
8206                 }
8207
8208                 if (mWifiControllerActivity != null) {
8209                     mWifiControllerActivity.detach();
8210                 }
8211
8212                 if (mBluetoothControllerActivity != null) {
8213                     mBluetoothControllerActivity.detach();
8214                 }
8215
8216                 if (mModemControllerActivity != null) {
8217                     mModemControllerActivity.detach();
8218                 }
8219
8220                 mPids.clear();
8221
8222                 mUserCpuTime.detach();
8223                 mSystemCpuTime.detach();
8224
8225                 if (mCpuClusterSpeedTimesUs != null) {
8226                     for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
8227                         if (cpuSpeeds != null) {
8228                             for (LongSamplingCounter c : cpuSpeeds) {
8229                                 if (c != null) {
8230                                     c.detach();
8231                                 }
8232                             }
8233                         }
8234                     }
8235                 }
8236
8237                 if (mCpuFreqTimeMs != null) {
8238                     mCpuFreqTimeMs.detach();
8239                 }
8240                 if (mScreenOffCpuFreqTimeMs != null) {
8241                     mScreenOffCpuFreqTimeMs.detach();
8242                 }
8243                 mCpuActiveTimeMs.detach();
8244                 mCpuClusterTimesMs.detach();
8245
8246                 if (mProcStateTimeMs != null) {
8247                     for (LongSamplingCounterArray counters : mProcStateTimeMs) {
8248                         if (counters != null) {
8249                             counters.detach();
8250                         }
8251                     }
8252                 }
8253                 if (mProcStateScreenOffTimeMs != null) {
8254                     for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
8255                         if (counters != null) {
8256                             counters.detach();
8257                         }
8258                     }
8259                 }
8260                 detachLongCounterIfNotNull(mMobileRadioApWakeupCount);
8261                 detachLongCounterIfNotNull(mWifiRadioApWakeupCount);
8262             }
8263
8264             return !active;
8265         }
8266
8267         void writeJobCompletionsToParcelLocked(Parcel out) {
8268             int NJC = mJobCompletions.size();
8269             out.writeInt(NJC);
8270             for (int ijc=0; ijc<NJC; ijc++) {
8271                 out.writeString(mJobCompletions.keyAt(ijc));
8272                 SparseIntArray types = mJobCompletions.valueAt(ijc);
8273                 int NT = types.size();
8274                 out.writeInt(NT);
8275                 for (int it=0; it<NT; it++) {
8276                     out.writeInt(types.keyAt(it));
8277                     out.writeInt(types.valueAt(it));
8278                 }
8279             }
8280         }
8281
8282         void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
8283             mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8284             mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8285
8286             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8287             int NW = wakeStats.size();
8288             out.writeInt(NW);
8289             for (int iw=0; iw<NW; iw++) {
8290                 out.writeString(wakeStats.keyAt(iw));
8291                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
8292                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
8293             }
8294
8295             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8296             int NS = syncStats.size();
8297             out.writeInt(NS);
8298             for (int is=0; is<NS; is++) {
8299                 out.writeString(syncStats.keyAt(is));
8300                 DualTimer timer = syncStats.valueAt(is);
8301                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8302             }
8303
8304             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8305             int NJ = jobStats.size();
8306             out.writeInt(NJ);
8307             for (int ij=0; ij<NJ; ij++) {
8308                 out.writeString(jobStats.keyAt(ij));
8309                 DualTimer timer = jobStats.valueAt(ij);
8310                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8311             }
8312
8313             writeJobCompletionsToParcelLocked(out);
8314
8315             mJobsDeferredEventCount.writeToParcel(out);
8316             mJobsDeferredCount.writeToParcel(out);
8317             mJobsFreshnessTimeMs.writeToParcel(out);
8318             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8319                 Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
8320             }
8321
8322             int NSE = mSensorStats.size();
8323             out.writeInt(NSE);
8324             for (int ise=0; ise<NSE; ise++) {
8325                 out.writeInt(mSensorStats.keyAt(ise));
8326                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
8327                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
8328             }
8329
8330             int NP = mProcessStats.size();
8331             out.writeInt(NP);
8332             for (int ip=0; ip<NP; ip++) {
8333                 out.writeString(mProcessStats.keyAt(ip));
8334                 Uid.Proc proc = mProcessStats.valueAt(ip);
8335                 proc.writeToParcelLocked(out);
8336             }
8337
8338             out.writeInt(mPackageStats.size());
8339             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
8340                 out.writeString(pkgEntry.getKey());
8341                 Uid.Pkg pkg = pkgEntry.getValue();
8342                 pkg.writeToParcelLocked(out);
8343             }
8344
8345             if (mWifiRunningTimer != null) {
8346                 out.writeInt(1);
8347                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
8348             } else {
8349                 out.writeInt(0);
8350             }
8351             if (mFullWifiLockTimer != null) {
8352                 out.writeInt(1);
8353                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
8354             } else {
8355                 out.writeInt(0);
8356             }
8357             if (mWifiScanTimer != null) {
8358                 out.writeInt(1);
8359                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
8360             } else {
8361                 out.writeInt(0);
8362             }
8363             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8364                 if (mWifiBatchedScanTimer[i] != null) {
8365                     out.writeInt(1);
8366                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
8367                 } else {
8368                     out.writeInt(0);
8369                 }
8370             }
8371             if (mWifiMulticastTimer != null) {
8372                 out.writeInt(1);
8373                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
8374             } else {
8375                 out.writeInt(0);
8376             }
8377
8378             if (mAudioTurnedOnTimer != null) {
8379                 out.writeInt(1);
8380                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8381             } else {
8382                 out.writeInt(0);
8383             }
8384             if (mVideoTurnedOnTimer != null) {
8385                 out.writeInt(1);
8386                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8387             } else {
8388                 out.writeInt(0);
8389             }
8390             if (mFlashlightTurnedOnTimer != null) {
8391                 out.writeInt(1);
8392                 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8393             } else {
8394                 out.writeInt(0);
8395             }
8396             if (mCameraTurnedOnTimer != null) {
8397                 out.writeInt(1);
8398                 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8399             } else {
8400                 out.writeInt(0);
8401             }
8402             if (mForegroundActivityTimer != null) {
8403                 out.writeInt(1);
8404                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
8405             } else {
8406                 out.writeInt(0);
8407             }
8408             if (mForegroundServiceTimer != null) {
8409                 out.writeInt(1);
8410                 mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
8411             } else {
8412                 out.writeInt(0);
8413             }
8414             if (mAggregatedPartialWakelockTimer != null) {
8415                 out.writeInt(1);
8416                 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
8417             } else {
8418                 out.writeInt(0);
8419             }
8420             if (mBluetoothScanTimer != null) {
8421                 out.writeInt(1);
8422                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
8423             } else {
8424                 out.writeInt(0);
8425             }
8426             if (mBluetoothUnoptimizedScanTimer != null) {
8427                 out.writeInt(1);
8428                 mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
8429             } else {
8430                 out.writeInt(0);
8431             }
8432             if (mBluetoothScanResultCounter != null) {
8433                 out.writeInt(1);
8434                 mBluetoothScanResultCounter.writeToParcel(out);
8435             } else {
8436                 out.writeInt(0);
8437             }
8438             if (mBluetoothScanResultBgCounter != null) {
8439                 out.writeInt(1);
8440                 mBluetoothScanResultBgCounter.writeToParcel(out);
8441             } else {
8442                 out.writeInt(0);
8443             }
8444             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8445                 if (mProcessStateTimer[i] != null) {
8446                     out.writeInt(1);
8447                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
8448                 } else {
8449                     out.writeInt(0);
8450                 }
8451             }
8452             if (mVibratorOnTimer != null) {
8453                 out.writeInt(1);
8454                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
8455             } else {
8456                 out.writeInt(0);
8457             }
8458             if (mUserActivityCounters != null) {
8459                 out.writeInt(1);
8460                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8461                     mUserActivityCounters[i].writeToParcel(out);
8462                 }
8463             } else {
8464                 out.writeInt(0);
8465             }
8466             if (mNetworkByteActivityCounters != null) {
8467                 out.writeInt(1);
8468                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8469                     mNetworkByteActivityCounters[i].writeToParcel(out);
8470                     mNetworkPacketActivityCounters[i].writeToParcel(out);
8471                 }
8472                 mMobileRadioActiveTime.writeToParcel(out);
8473                 mMobileRadioActiveCount.writeToParcel(out);
8474             } else {
8475                 out.writeInt(0);
8476             }
8477
8478             if (mWifiControllerActivity != null) {
8479                 out.writeInt(1);
8480                 mWifiControllerActivity.writeToParcel(out, 0);
8481             } else {
8482                 out.writeInt(0);
8483             }
8484
8485             if (mBluetoothControllerActivity != null) {
8486                 out.writeInt(1);
8487                 mBluetoothControllerActivity.writeToParcel(out, 0);
8488             } else {
8489                 out.writeInt(0);
8490             }
8491
8492             if (mModemControllerActivity != null) {
8493                 out.writeInt(1);
8494                 mModemControllerActivity.writeToParcel(out, 0);
8495             } else {
8496                 out.writeInt(0);
8497             }
8498
8499             mUserCpuTime.writeToParcel(out);
8500             mSystemCpuTime.writeToParcel(out);
8501
8502             if (mCpuClusterSpeedTimesUs != null) {
8503                 out.writeInt(1);
8504                 out.writeInt(mCpuClusterSpeedTimesUs.length);
8505                 for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
8506                     if (cpuSpeeds != null) {
8507                         out.writeInt(1);
8508                         out.writeInt(cpuSpeeds.length);
8509                         for (LongSamplingCounter c : cpuSpeeds) {
8510                             if (c != null) {
8511                                 out.writeInt(1);
8512                                 c.writeToParcel(out);
8513                             } else {
8514                                 out.writeInt(0);
8515                             }
8516                         }
8517                     } else {
8518                         out.writeInt(0);
8519                     }
8520                 }
8521             } else {
8522                 out.writeInt(0);
8523             }
8524
8525             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
8526             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
8527
8528             mCpuActiveTimeMs.writeToParcel(out);
8529             mCpuClusterTimesMs.writeToParcel(out);
8530
8531             if (mProcStateTimeMs != null) {
8532                 out.writeInt(mProcStateTimeMs.length);
8533                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
8534                     LongSamplingCounterArray.writeToParcel(out, counters);
8535                 }
8536             } else {
8537                 out.writeInt(0);
8538             }
8539             if (mProcStateScreenOffTimeMs != null) {
8540                 out.writeInt(mProcStateScreenOffTimeMs.length);
8541                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
8542                     LongSamplingCounterArray.writeToParcel(out, counters);
8543                 }
8544             } else {
8545                 out.writeInt(0);
8546             }
8547
8548             if (mMobileRadioApWakeupCount != null) {
8549                 out.writeInt(1);
8550                 mMobileRadioApWakeupCount.writeToParcel(out);
8551             } else {
8552                 out.writeInt(0);
8553             }
8554
8555             if (mWifiRadioApWakeupCount != null) {
8556                 out.writeInt(1);
8557                 mWifiRadioApWakeupCount.writeToParcel(out);
8558             } else {
8559                 out.writeInt(0);
8560             }
8561         }
8562
8563         void readJobCompletionsFromParcelLocked(Parcel in) {
8564             int numJobCompletions = in.readInt();
8565             mJobCompletions.clear();
8566             for (int j = 0; j < numJobCompletions; j++) {
8567                 String jobName = in.readString();
8568                 int numTypes = in.readInt();
8569                 if (numTypes > 0) {
8570                     SparseIntArray types = new SparseIntArray();
8571                     for (int k = 0; k < numTypes; k++) {
8572                         int type = in.readInt();
8573                         int count = in.readInt();
8574                         types.put(type, count);
8575                     }
8576                     mJobCompletions.put(jobName, types);
8577                 }
8578             }
8579         }
8580
8581         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
8582             mOnBatteryBackgroundTimeBase.readFromParcel(in);
8583             mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
8584
8585             int numWakelocks = in.readInt();
8586             mWakelockStats.clear();
8587             for (int j = 0; j < numWakelocks; j++) {
8588                 String wakelockName = in.readString();
8589                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
8590                 wakelock.readFromParcelLocked(
8591                         timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
8592                 mWakelockStats.add(wakelockName, wakelock);
8593             }
8594
8595             int numSyncs = in.readInt();
8596             mSyncStats.clear();
8597             for (int j = 0; j < numSyncs; j++) {
8598                 String syncName = in.readString();
8599                 if (in.readInt() != 0) {
8600                     mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
8601                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8602                 }
8603             }
8604
8605             int numJobs = in.readInt();
8606             mJobStats.clear();
8607             for (int j = 0; j < numJobs; j++) {
8608                 String jobName = in.readString();
8609                 if (in.readInt() != 0) {
8610                     mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
8611                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8612                 }
8613             }
8614
8615             readJobCompletionsFromParcelLocked(in);
8616
8617             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8618             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8619             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8620             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8621                 mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
8622                         in);
8623             }
8624
8625             int numSensors = in.readInt();
8626             mSensorStats.clear();
8627             for (int k = 0; k < numSensors; k++) {
8628                 int sensorNumber = in.readInt();
8629                 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
8630                 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8631                         in);
8632                 mSensorStats.put(sensorNumber, sensor);
8633             }
8634
8635             int numProcs = in.readInt();
8636             mProcessStats.clear();
8637             for (int k = 0; k < numProcs; k++) {
8638                 String processName = in.readString();
8639                 Uid.Proc proc = new Proc(mBsi, processName);
8640                 proc.readFromParcelLocked(in);
8641                 mProcessStats.put(processName, proc);
8642             }
8643
8644             int numPkgs = in.readInt();
8645             mPackageStats.clear();
8646             for (int l = 0; l < numPkgs; l++) {
8647                 String packageName = in.readString();
8648                 Uid.Pkg pkg = new Pkg(mBsi);
8649                 pkg.readFromParcelLocked(in);
8650                 mPackageStats.put(packageName, pkg);
8651             }
8652
8653             mWifiRunning = false;
8654             if (in.readInt() != 0) {
8655                 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
8656                         mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
8657             } else {
8658                 mWifiRunningTimer = null;
8659             }
8660             mFullWifiLockOut = false;
8661             if (in.readInt() != 0) {
8662                 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
8663                         mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
8664             } else {
8665                 mFullWifiLockTimer = null;
8666             }
8667             mWifiScanStarted = false;
8668             if (in.readInt() != 0) {
8669                 mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
8670                         mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8671                         in);
8672             } else {
8673                 mWifiScanTimer = null;
8674             }
8675             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8676             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8677                 if (in.readInt() != 0) {
8678                     makeWifiBatchedScanBin(i, in);
8679                 } else {
8680                     mWifiBatchedScanTimer[i] = null;
8681                 }
8682             }
8683             mWifiMulticastEnabled = false;
8684             if (in.readInt() != 0) {
8685                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
8686                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
8687             } else {
8688                 mWifiMulticastTimer = null;
8689             }
8690             if (in.readInt() != 0) {
8691                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
8692                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8693             } else {
8694                 mAudioTurnedOnTimer = null;
8695             }
8696             if (in.readInt() != 0) {
8697                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
8698                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8699             } else {
8700                 mVideoTurnedOnTimer = null;
8701             }
8702             if (in.readInt() != 0) {
8703                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8704                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8705             } else {
8706                 mFlashlightTurnedOnTimer = null;
8707             }
8708             if (in.readInt() != 0) {
8709                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
8710                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8711             } else {
8712                 mCameraTurnedOnTimer = null;
8713             }
8714             if (in.readInt() != 0) {
8715                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8716                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
8717             } else {
8718                 mForegroundActivityTimer = null;
8719             }
8720             if (in.readInt() != 0) {
8721                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8722                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
8723             } else {
8724                 mForegroundServiceTimer = null;
8725             }
8726             if (in.readInt() != 0) {
8727                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
8728                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
8729                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
8730                         in);
8731             } else {
8732                 mAggregatedPartialWakelockTimer = null;
8733             }
8734             if (in.readInt() != 0) {
8735                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
8736                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
8737                         mOnBatteryBackgroundTimeBase, in);
8738             } else {
8739                 mBluetoothScanTimer = null;
8740             }
8741             if (in.readInt() != 0) {
8742                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
8743                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
8744                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
8745             } else {
8746                 mBluetoothUnoptimizedScanTimer = null;
8747             }
8748             if (in.readInt() != 0) {
8749                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
8750             } else {
8751                 mBluetoothScanResultCounter = null;
8752             }
8753             if (in.readInt() != 0) {
8754                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
8755             } else {
8756                 mBluetoothScanResultBgCounter = null;
8757             }
8758             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
8759             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8760                 if (in.readInt() != 0) {
8761                     makeProcessState(i, in);
8762                 } else {
8763                     mProcessStateTimer[i] = null;
8764                 }
8765             }
8766             if (in.readInt() != 0) {
8767                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
8768                         mBsi.mOnBatteryTimeBase, in);
8769             } else {
8770                 mVibratorOnTimer = null;
8771             }
8772             if (in.readInt() != 0) {
8773                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
8774                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8775                     mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
8776                 }
8777             } else {
8778                 mUserActivityCounters = null;
8779             }
8780             if (in.readInt() != 0) {
8781                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8782                 mNetworkPacketActivityCounters
8783                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8784                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8785                     mNetworkByteActivityCounters[i]
8786                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8787                     mNetworkPacketActivityCounters[i]
8788                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8789                 }
8790                 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8791                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8792             } else {
8793                 mNetworkByteActivityCounters = null;
8794                 mNetworkPacketActivityCounters = null;
8795             }
8796
8797             if (in.readInt() != 0) {
8798                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8799                         NUM_WIFI_TX_LEVELS, in);
8800             } else {
8801                 mWifiControllerActivity = null;
8802             }
8803
8804             if (in.readInt() != 0) {
8805                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8806                         NUM_BT_TX_LEVELS, in);
8807             } else {
8808                 mBluetoothControllerActivity = null;
8809             }
8810
8811             if (in.readInt() != 0) {
8812                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8813                         ModemActivityInfo.TX_POWER_LEVELS, in);
8814             } else {
8815                 mModemControllerActivity = null;
8816             }
8817
8818             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8819             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8820
8821             if (in.readInt() != 0) {
8822                 int numCpuClusters = in.readInt();
8823                 if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
8824                     throw new ParcelFormatException("Incompatible number of cpu clusters");
8825                 }
8826
8827                 mCpuClusterSpeedTimesUs = new LongSamplingCounter[numCpuClusters][];
8828                 for (int cluster = 0; cluster < numCpuClusters; cluster++) {
8829                     if (in.readInt() != 0) {
8830                         int numSpeeds = in.readInt();
8831                         if (mBsi.mPowerProfile != null &&
8832                                 mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
8833                             throw new ParcelFormatException("Incompatible number of cpu speeds");
8834                         }
8835
8836                         final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
8837                         mCpuClusterSpeedTimesUs[cluster] = cpuSpeeds;
8838                         for (int speed = 0; speed < numSpeeds; speed++) {
8839                             if (in.readInt() != 0) {
8840                                 cpuSpeeds[speed] = new LongSamplingCounter(
8841                                         mBsi.mOnBatteryTimeBase, in);
8842                             }
8843                         }
8844                     } else {
8845                         mCpuClusterSpeedTimesUs[cluster] = null;
8846                     }
8847                 }
8848             } else {
8849                 mCpuClusterSpeedTimesUs = null;
8850             }
8851
8852             mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
8853             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
8854                     in, mBsi.mOnBatteryScreenOffTimeBase);
8855
8856             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8857             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
8858
8859             int length = in.readInt();
8860             if (length == NUM_PROCESS_STATE) {
8861                 mProcStateTimeMs = new LongSamplingCounterArray[length];
8862                 for (int procState = 0; procState < length; ++procState) {
8863                     mProcStateTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8864                             in, mBsi.mOnBatteryTimeBase);
8865                 }
8866             } else {
8867                 mProcStateTimeMs = null;
8868             }
8869             length = in.readInt();
8870             if (length == NUM_PROCESS_STATE) {
8871                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
8872                 for (int procState = 0; procState < length; ++procState) {
8873                     mProcStateScreenOffTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8874                             in, mBsi.mOnBatteryScreenOffTimeBase);
8875                 }
8876             } else {
8877                 mProcStateScreenOffTimeMs = null;
8878             }
8879
8880             if (in.readInt() != 0) {
8881                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8882             } else {
8883                 mMobileRadioApWakeupCount = null;
8884             }
8885
8886             if (in.readInt() != 0) {
8887                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8888             } else {
8889                 mWifiRadioApWakeupCount = null;
8890             }
8891         }
8892
8893         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
8894             mJobsDeferredEventCount.addAtomic(1);
8895             mJobsDeferredCount.addAtomic(numDeferred);
8896             if (sinceLast != 0) {
8897                 // Add the total time, which can be divided by the event count to get an average
8898                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
8899                 // Also keep track of how many times there were in these different buckets.
8900                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8901                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
8902                         if (mJobsFreshnessBuckets[i] == null) {
8903                             mJobsFreshnessBuckets[i] = new Counter(
8904                                     mBsi.mOnBatteryTimeBase);
8905                         }
8906                         mJobsFreshnessBuckets[i].addAtomic(1);
8907                         break;
8908                     }
8909                 }
8910             }
8911         }
8912
8913         /**
8914          * The statistics associated with a particular wake lock.
8915          */
8916         public static class Wakelock extends BatteryStats.Uid.Wakelock {
8917             /**
8918              * BatteryStatsImpl that we are associated with.
8919              */
8920             protected BatteryStatsImpl mBsi;
8921
8922             /**
8923              * BatteryStatsImpl that we are associated with.
8924              */
8925             protected Uid mUid;
8926
8927             /**
8928              * How long (in ms) this uid has been keeping the device partially awake.
8929              * Tracks both the total time and the time while the app was in the background.
8930              */
8931             DualTimer mTimerPartial;
8932
8933             /**
8934              * How long (in ms) this uid has been keeping the device fully awake.
8935              */
8936             StopwatchTimer mTimerFull;
8937
8938             /**
8939              * How long (in ms) this uid has had a window keeping the device awake.
8940              */
8941             StopwatchTimer mTimerWindow;
8942
8943             /**
8944              * How long (in ms) this uid has had a draw wake lock.
8945              */
8946             StopwatchTimer mTimerDraw;
8947
8948             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
8949                 mBsi = bsi;
8950                 mUid = uid;
8951             }
8952
8953             /**
8954              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8955              * proper timer pool from the given BatteryStatsImpl object.
8956              *
8957              * @param in the Parcel to be read from.
8958              * return a new Timer, or null.
8959              */
8960             private StopwatchTimer readStopwatchTimerFromParcel(int type,
8961                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
8962                 if (in.readInt() == 0) {
8963                     return null;
8964                 }
8965
8966                 return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
8967             }
8968
8969             /**
8970              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8971              * proper timer pool from the given BatteryStatsImpl object.
8972              *
8973              * @param in the Parcel to be read from.
8974              * return a new Timer, or null.
8975              */
8976             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
8977                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8978                 if (in.readInt() == 0) {
8979                     return null;
8980                 }
8981
8982                 return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
8983             }
8984
8985             boolean reset() {
8986                 boolean wlactive = false;
8987                 if (mTimerFull != null) {
8988                     wlactive |= !mTimerFull.reset(false);
8989                 }
8990                 if (mTimerPartial != null) {
8991                     wlactive |= !mTimerPartial.reset(false);
8992                 }
8993                 if (mTimerWindow != null) {
8994                     wlactive |= !mTimerWindow.reset(false);
8995                 }
8996                 if (mTimerDraw != null) {
8997                     wlactive |= !mTimerDraw.reset(false);
8998                 }
8999                 if (!wlactive) {
9000                     if (mTimerFull != null) {
9001                         mTimerFull.detach();
9002                         mTimerFull = null;
9003                     }
9004                     if (mTimerPartial != null) {
9005                         mTimerPartial.detach();
9006                         mTimerPartial = null;
9007                     }
9008                     if (mTimerWindow != null) {
9009                         mTimerWindow.detach();
9010                         mTimerWindow = null;
9011                     }
9012                     if (mTimerDraw != null) {
9013                         mTimerDraw.detach();
9014                         mTimerDraw = null;
9015                     }
9016                 }
9017                 return !wlactive;
9018             }
9019
9020             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
9021                     TimeBase screenOffBgTimeBase, Parcel in) {
9022                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
9023                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
9024                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
9025                         mBsi.mFullTimers, timeBase, in);
9026                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
9027                         mBsi.mWindowTimers, timeBase, in);
9028                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
9029                         mBsi.mDrawTimers, timeBase, in);
9030             }
9031
9032             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
9033                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
9034                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
9035                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
9036                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
9037             }
9038
9039             @Override
9040             public Timer getWakeTime(int type) {
9041                 switch (type) {
9042                 case WAKE_TYPE_FULL: return mTimerFull;
9043                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
9044                 case WAKE_TYPE_WINDOW: return mTimerWindow;
9045                 case WAKE_TYPE_DRAW: return mTimerDraw;
9046                 default: throw new IllegalArgumentException("type = " + type);
9047                 }
9048             }
9049         }
9050
9051         public static class Sensor extends BatteryStats.Uid.Sensor {
9052             /**
9053              * BatteryStatsImpl that we are associated with.
9054              */
9055             protected BatteryStatsImpl mBsi;
9056
9057             /**
9058              * Uid that we are associated with.
9059              */
9060             protected Uid mUid;
9061
9062             final int mHandle;
9063             DualTimer mTimer;
9064
9065             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
9066                 mBsi = bsi;
9067                 mUid = uid;
9068                 mHandle = handle;
9069             }
9070
9071             private DualTimer readTimersFromParcel(
9072                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9073                 if (in.readInt() == 0) {
9074                     return null;
9075                 }
9076
9077                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
9078                 if (pool == null) {
9079                     pool = new ArrayList<StopwatchTimer>();
9080                     mBsi.mSensorTimers.put(mHandle, pool);
9081                 }
9082                 return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
9083             }
9084
9085             boolean reset() {
9086                 if (mTimer.reset(true)) {
9087                     mTimer = null;
9088                     return true;
9089                 }
9090                 return false;
9091             }
9092
9093             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9094                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
9095             }
9096
9097             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
9098                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
9099             }
9100
9101             @Override
9102             public Timer getSensorTime() {
9103                 return mTimer;
9104             }
9105
9106             @Override
9107             public Timer getSensorBackgroundTime() {
9108                 if (mTimer == null) {
9109                     return null;
9110                 }
9111                 return mTimer.getSubTimer();
9112             }
9113
9114             @Override
9115             public int getHandle() {
9116                 return mHandle;
9117             }
9118         }
9119
9120         /**
9121          * The statistics associated with a particular process.
9122          */
9123         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
9124             /**
9125              * BatteryStatsImpl that we are associated with.
9126              */
9127             protected BatteryStatsImpl mBsi;
9128
9129             /**
9130              * The name of this process.
9131              */
9132             final String mName;
9133
9134             /**
9135              * Remains true until removed from the stats.
9136              */
9137             boolean mActive = true;
9138
9139             /**
9140              * Total time (in ms) spent executing in user code.
9141              */
9142             long mUserTime;
9143
9144             /**
9145              * Total time (in ms) spent executing in kernel code.
9146              */
9147             long mSystemTime;
9148
9149             /**
9150              * Amount of time (in ms) the process was running in the foreground.
9151              */
9152             long mForegroundTime;
9153
9154             /**
9155              * Number of times the process has been started.
9156              */
9157             int mStarts;
9158
9159             /**
9160              * Number of times the process has crashed.
9161              */
9162             int mNumCrashes;
9163
9164             /**
9165              * Number of times the process has had an ANR.
9166              */
9167             int mNumAnrs;
9168
9169             /**
9170              * The amount of user time loaded from a previous save.
9171              */
9172             long mLoadedUserTime;
9173
9174             /**
9175              * The amount of system time loaded from a previous save.
9176              */
9177             long mLoadedSystemTime;
9178
9179             /**
9180              * The amount of foreground time loaded from a previous save.
9181              */
9182             long mLoadedForegroundTime;
9183
9184             /**
9185              * The number of times the process has started from a previous save.
9186              */
9187             int mLoadedStarts;
9188
9189             /**
9190              * Number of times the process has crashed from a previous save.
9191              */
9192             int mLoadedNumCrashes;
9193
9194             /**
9195              * Number of times the process has had an ANR from a previous save.
9196              */
9197             int mLoadedNumAnrs;
9198
9199             /**
9200              * The amount of user time when last unplugged.
9201              */
9202             long mUnpluggedUserTime;
9203
9204             /**
9205              * The amount of system time when last unplugged.
9206              */
9207             long mUnpluggedSystemTime;
9208
9209             /**
9210              * The amount of foreground time since unplugged.
9211              */
9212             long mUnpluggedForegroundTime;
9213
9214             /**
9215              * The number of times the process has started before unplugged.
9216              */
9217             int mUnpluggedStarts;
9218
9219             /**
9220              * Number of times the process has crashed before unplugged.
9221              */
9222             int mUnpluggedNumCrashes;
9223
9224             /**
9225              * Number of times the process has had an ANR before unplugged.
9226              */
9227             int mUnpluggedNumAnrs;
9228
9229             ArrayList<ExcessivePower> mExcessivePower;
9230
9231             public Proc(BatteryStatsImpl bsi, String name) {
9232                 mBsi = bsi;
9233                 mName = name;
9234                 mBsi.mOnBatteryTimeBase.add(this);
9235             }
9236
9237             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
9238                 mUnpluggedUserTime = mUserTime;
9239                 mUnpluggedSystemTime = mSystemTime;
9240                 mUnpluggedForegroundTime = mForegroundTime;
9241                 mUnpluggedStarts = mStarts;
9242                 mUnpluggedNumCrashes = mNumCrashes;
9243                 mUnpluggedNumAnrs = mNumAnrs;
9244             }
9245
9246             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
9247             }
9248
9249             void detach() {
9250                 mActive = false;
9251                 mBsi.mOnBatteryTimeBase.remove(this);
9252             }
9253
9254             public int countExcessivePowers() {
9255                 return mExcessivePower != null ? mExcessivePower.size() : 0;
9256             }
9257
9258             public ExcessivePower getExcessivePower(int i) {
9259                 if (mExcessivePower != null) {
9260                     return mExcessivePower.get(i);
9261                 }
9262                 return null;
9263             }
9264
9265             public void addExcessiveCpu(long overTime, long usedTime) {
9266                 if (mExcessivePower == null) {
9267                     mExcessivePower = new ArrayList<ExcessivePower>();
9268                 }
9269                 ExcessivePower ew = new ExcessivePower();
9270                 ew.type = ExcessivePower.TYPE_CPU;
9271                 ew.overTime = overTime;
9272                 ew.usedTime = usedTime;
9273                 mExcessivePower.add(ew);
9274             }
9275
9276             void writeExcessivePowerToParcelLocked(Parcel out) {
9277                 if (mExcessivePower == null) {
9278                     out.writeInt(0);
9279                     return;
9280                 }
9281
9282                 final int N = mExcessivePower.size();
9283                 out.writeInt(N);
9284                 for (int i=0; i<N; i++) {
9285                     ExcessivePower ew = mExcessivePower.get(i);
9286                     out.writeInt(ew.type);
9287                     out.writeLong(ew.overTime);
9288                     out.writeLong(ew.usedTime);
9289                 }
9290             }
9291
9292             void readExcessivePowerFromParcelLocked(Parcel in) {
9293                 final int N = in.readInt();
9294                 if (N == 0) {
9295                     mExcessivePower = null;
9296                     return;
9297                 }
9298
9299                 if (N > 10000) {
9300                     throw new ParcelFormatException(
9301                             "File corrupt: too many excessive power entries " + N);
9302                 }
9303
9304                 mExcessivePower = new ArrayList<>();
9305                 for (int i=0; i<N; i++) {
9306                     ExcessivePower ew = new ExcessivePower();
9307                     ew.type = in.readInt();
9308                     ew.overTime = in.readLong();
9309                     ew.usedTime = in.readLong();
9310                     mExcessivePower.add(ew);
9311                 }
9312             }
9313
9314             void writeToParcelLocked(Parcel out) {
9315                 out.writeLong(mUserTime);
9316                 out.writeLong(mSystemTime);
9317                 out.writeLong(mForegroundTime);
9318                 out.writeInt(mStarts);
9319                 out.writeInt(mNumCrashes);
9320                 out.writeInt(mNumAnrs);
9321                 out.writeLong(mLoadedUserTime);
9322                 out.writeLong(mLoadedSystemTime);
9323                 out.writeLong(mLoadedForegroundTime);
9324                 out.writeInt(mLoadedStarts);
9325                 out.writeInt(mLoadedNumCrashes);
9326                 out.writeInt(mLoadedNumAnrs);
9327                 out.writeLong(mUnpluggedUserTime);
9328                 out.writeLong(mUnpluggedSystemTime);
9329                 out.writeLong(mUnpluggedForegroundTime);
9330                 out.writeInt(mUnpluggedStarts);
9331                 out.writeInt(mUnpluggedNumCrashes);
9332                 out.writeInt(mUnpluggedNumAnrs);
9333                 writeExcessivePowerToParcelLocked(out);
9334             }
9335
9336             void readFromParcelLocked(Parcel in) {
9337                 mUserTime = in.readLong();
9338                 mSystemTime = in.readLong();
9339                 mForegroundTime = in.readLong();
9340                 mStarts = in.readInt();
9341                 mNumCrashes = in.readInt();
9342                 mNumAnrs = in.readInt();
9343                 mLoadedUserTime = in.readLong();
9344                 mLoadedSystemTime = in.readLong();
9345                 mLoadedForegroundTime = in.readLong();
9346                 mLoadedStarts = in.readInt();
9347                 mLoadedNumCrashes = in.readInt();
9348                 mLoadedNumAnrs = in.readInt();
9349                 mUnpluggedUserTime = in.readLong();
9350                 mUnpluggedSystemTime = in.readLong();
9351                 mUnpluggedForegroundTime = in.readLong();
9352                 mUnpluggedStarts = in.readInt();
9353                 mUnpluggedNumCrashes = in.readInt();
9354                 mUnpluggedNumAnrs = in.readInt();
9355                 readExcessivePowerFromParcelLocked(in);
9356             }
9357
9358             public void addCpuTimeLocked(int utime, int stime) {
9359                 addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
9360             }
9361
9362             public void addCpuTimeLocked(int utime, int stime, boolean isRunning) {
9363                 if (isRunning) {
9364                     mUserTime += utime;
9365                     mSystemTime += stime;
9366                 }
9367             }
9368
9369             public void addForegroundTimeLocked(long ttime) {
9370                 mForegroundTime += ttime;
9371             }
9372
9373             public void incStartsLocked() {
9374                 mStarts++;
9375             }
9376
9377             public void incNumCrashesLocked() {
9378                 mNumCrashes++;
9379             }
9380
9381             public void incNumAnrsLocked() {
9382                 mNumAnrs++;
9383             }
9384
9385             @Override
9386             public boolean isActive() {
9387                 return mActive;
9388             }
9389
9390             @Override
9391             public long getUserTime(int which) {
9392                 long val = mUserTime;
9393                 if (which == STATS_CURRENT) {
9394                     val -= mLoadedUserTime;
9395                 } else if (which == STATS_SINCE_UNPLUGGED) {
9396                     val -= mUnpluggedUserTime;
9397                 }
9398                 return val;
9399             }
9400
9401             @Override
9402             public long getSystemTime(int which) {
9403                 long val = mSystemTime;
9404                 if (which == STATS_CURRENT) {
9405                     val -= mLoadedSystemTime;
9406                 } else if (which == STATS_SINCE_UNPLUGGED) {
9407                     val -= mUnpluggedSystemTime;
9408                 }
9409                 return val;
9410             }
9411
9412             @Override
9413             public long getForegroundTime(int which) {
9414                 long val = mForegroundTime;
9415                 if (which == STATS_CURRENT) {
9416                     val -= mLoadedForegroundTime;
9417                 } else if (which == STATS_SINCE_UNPLUGGED) {
9418                     val -= mUnpluggedForegroundTime;
9419                 }
9420                 return val;
9421             }
9422
9423             @Override
9424             public int getStarts(int which) {
9425                 int val = mStarts;
9426                 if (which == STATS_CURRENT) {
9427                     val -= mLoadedStarts;
9428                 } else if (which == STATS_SINCE_UNPLUGGED) {
9429                     val -= mUnpluggedStarts;
9430                 }
9431                 return val;
9432             }
9433
9434             @Override
9435             public int getNumCrashes(int which) {
9436                 int val = mNumCrashes;
9437                 if (which == STATS_CURRENT) {
9438                     val -= mLoadedNumCrashes;
9439                 } else if (which == STATS_SINCE_UNPLUGGED) {
9440                     val -= mUnpluggedNumCrashes;
9441                 }
9442                 return val;
9443             }
9444
9445             @Override
9446             public int getNumAnrs(int which) {
9447                 int val = mNumAnrs;
9448                 if (which == STATS_CURRENT) {
9449                     val -= mLoadedNumAnrs;
9450                 } else if (which == STATS_SINCE_UNPLUGGED) {
9451                     val -= mUnpluggedNumAnrs;
9452                 }
9453                 return val;
9454             }
9455         }
9456
9457         /**
9458          * The statistics associated with a particular package.
9459          */
9460         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
9461             /**
9462              * BatteryStatsImpl that we are associated with.
9463              */
9464             protected BatteryStatsImpl mBsi;
9465
9466             /**
9467              * Number of times wakeup alarms have occurred for this app.
9468              * On screen-off timebase starting in report v25.
9469              */
9470             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
9471
9472             /**
9473              * The statics we have collected for this package's services.
9474              */
9475             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
9476
9477             public Pkg(BatteryStatsImpl bsi) {
9478                 mBsi = bsi;
9479                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
9480             }
9481
9482             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
9483             }
9484
9485             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
9486             }
9487
9488             void detach() {
9489                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
9490             }
9491
9492             void readFromParcelLocked(Parcel in) {
9493                 int numWA = in.readInt();
9494                 mWakeupAlarms.clear();
9495                 for (int i=0; i<numWA; i++) {
9496                     String tag = in.readString();
9497                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
9498                 }
9499
9500                 int numServs = in.readInt();
9501                 mServiceStats.clear();
9502                 for (int m = 0; m < numServs; m++) {
9503                     String serviceName = in.readString();
9504                     Uid.Pkg.Serv serv = new Serv(mBsi);
9505                     mServiceStats.put(serviceName, serv);
9506
9507                     serv.readFromParcelLocked(in);
9508                 }
9509             }
9510
9511             void writeToParcelLocked(Parcel out) {
9512                 int numWA = mWakeupAlarms.size();
9513                 out.writeInt(numWA);
9514                 for (int i=0; i<numWA; i++) {
9515                     out.writeString(mWakeupAlarms.keyAt(i));
9516                     mWakeupAlarms.valueAt(i).writeToParcel(out);
9517                 }
9518
9519                 final int NS = mServiceStats.size();
9520                 out.writeInt(NS);
9521                 for (int i=0; i<NS; i++) {
9522                     out.writeString(mServiceStats.keyAt(i));
9523                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
9524                     serv.writeToParcelLocked(out);
9525                 }
9526             }
9527
9528             @Override
9529             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
9530                 return mWakeupAlarms;
9531             }
9532
9533             public void noteWakeupAlarmLocked(String tag) {
9534                 Counter c = mWakeupAlarms.get(tag);
9535                 if (c == null) {
9536                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
9537                     mWakeupAlarms.put(tag, c);
9538                 }
9539                 c.stepAtomic();
9540             }
9541
9542             @Override
9543             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
9544                 return mServiceStats;
9545             }
9546
9547             /**
9548              * The statistics associated with a particular service.
9549              */
9550             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
9551                 /**
9552                  * BatteryStatsImpl that we are associated with.
9553                  */
9554                 protected BatteryStatsImpl mBsi;
9555
9556                 /**
9557                  * The android package in which this service resides.
9558                  */
9559                 protected Pkg mPkg;
9560
9561                 /**
9562                  * Total time (ms in battery uptime) the service has been left started.
9563                  */
9564                 protected long mStartTime;
9565
9566                 /**
9567                  * If service has been started and not yet stopped, this is
9568                  * when it was started.
9569                  */
9570                 protected long mRunningSince;
9571
9572                 /**
9573                  * True if we are currently running.
9574                  */
9575                 protected boolean mRunning;
9576
9577                 /**
9578                  * Total number of times startService() has been called.
9579                  */
9580                 protected int mStarts;
9581
9582                 /**
9583                  * Total time (ms in battery uptime) the service has been left launched.
9584                  */
9585                 protected long mLaunchedTime;
9586
9587                 /**
9588                  * If service has been launched and not yet exited, this is
9589                  * when it was launched (ms in battery uptime).
9590                  */
9591                 protected long mLaunchedSince;
9592
9593                 /**
9594                  * True if we are currently launched.
9595                  */
9596                 protected boolean mLaunched;
9597
9598                 /**
9599                  * Total number times the service has been launched.
9600                  */
9601                 protected int mLaunches;
9602
9603                 /**
9604                  * The amount of time spent started loaded from a previous save
9605                  * (ms in battery uptime).
9606                  */
9607                 protected long mLoadedStartTime;
9608
9609                 /**
9610                  * The number of starts loaded from a previous save.
9611                  */
9612                 protected int mLoadedStarts;
9613
9614                 /**
9615                  * The number of launches loaded from a previous save.
9616                  */
9617                 protected int mLoadedLaunches;
9618
9619                 /**
9620                  * The amount of time spent started as of the last run (ms
9621                  * in battery uptime).
9622                  */
9623                 protected long mLastStartTime;
9624
9625                 /**
9626                  * The number of starts as of the last run.
9627                  */
9628                 protected int mLastStarts;
9629
9630                 /**
9631                  * The number of launches as of the last run.
9632                  */
9633                 protected int mLastLaunches;
9634
9635                 /**
9636                  * The amount of time spent started when last unplugged (ms
9637                  * in battery uptime).
9638                  */
9639                 protected long mUnpluggedStartTime;
9640
9641                 /**
9642                  * The number of starts when last unplugged.
9643                  */
9644                 protected int mUnpluggedStarts;
9645
9646                 /**
9647                  * The number of launches when last unplugged.
9648                  */
9649                 protected int mUnpluggedLaunches;
9650
9651                 /**
9652                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
9653                  */
9654                 public Serv(BatteryStatsImpl bsi) {
9655                     mBsi = bsi;
9656                     mBsi.mOnBatteryTimeBase.add(this);
9657                 }
9658
9659                 public void onTimeStarted(long elapsedRealtime, long baseUptime,
9660                         long baseRealtime) {
9661                     mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
9662                     mUnpluggedStarts = mStarts;
9663                     mUnpluggedLaunches = mLaunches;
9664                 }
9665
9666                 public void onTimeStopped(long elapsedRealtime, long baseUptime,
9667                         long baseRealtime) {
9668                 }
9669
9670                 /**
9671                  * Remove this Serv as a listener from the time base.
9672                  */
9673                 public void detach() {
9674                     mBsi.mOnBatteryTimeBase.remove(this);
9675                 }
9676
9677                 public void readFromParcelLocked(Parcel in) {
9678                     mStartTime = in.readLong();
9679                     mRunningSince = in.readLong();
9680                     mRunning = in.readInt() != 0;
9681                     mStarts = in.readInt();
9682                     mLaunchedTime = in.readLong();
9683                     mLaunchedSince = in.readLong();
9684                     mLaunched = in.readInt() != 0;
9685                     mLaunches = in.readInt();
9686                     mLoadedStartTime = in.readLong();
9687                     mLoadedStarts = in.readInt();
9688                     mLoadedLaunches = in.readInt();
9689                     mLastStartTime = 0;
9690                     mLastStarts = 0;
9691                     mLastLaunches = 0;
9692                     mUnpluggedStartTime = in.readLong();
9693                     mUnpluggedStarts = in.readInt();
9694                     mUnpluggedLaunches = in.readInt();
9695                 }
9696
9697                 public void writeToParcelLocked(Parcel out) {
9698                     out.writeLong(mStartTime);
9699                     out.writeLong(mRunningSince);
9700                     out.writeInt(mRunning ? 1 : 0);
9701                     out.writeInt(mStarts);
9702                     out.writeLong(mLaunchedTime);
9703                     out.writeLong(mLaunchedSince);
9704                     out.writeInt(mLaunched ? 1 : 0);
9705                     out.writeInt(mLaunches);
9706                     out.writeLong(mLoadedStartTime);
9707                     out.writeInt(mLoadedStarts);
9708                     out.writeInt(mLoadedLaunches);
9709                     out.writeLong(mUnpluggedStartTime);
9710                     out.writeInt(mUnpluggedStarts);
9711                     out.writeInt(mUnpluggedLaunches);
9712                 }
9713
9714                 public long getLaunchTimeToNowLocked(long batteryUptime) {
9715                     if (!mLaunched) return mLaunchedTime;
9716                     return mLaunchedTime + batteryUptime - mLaunchedSince;
9717                 }
9718
9719                 public long getStartTimeToNowLocked(long batteryUptime) {
9720                     if (!mRunning) return mStartTime;
9721                     return mStartTime + batteryUptime - mRunningSince;
9722                 }
9723
9724                 public void startLaunchedLocked() {
9725                     if (!mLaunched) {
9726                         mLaunches++;
9727                         mLaunchedSince = mBsi.getBatteryUptimeLocked();
9728                         mLaunched = true;
9729                     }
9730                 }
9731
9732                 public void stopLaunchedLocked() {
9733                     if (mLaunched) {
9734                         long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
9735                         if (time > 0) {
9736                             mLaunchedTime += time;
9737                         } else {
9738                             mLaunches--;
9739                         }
9740                         mLaunched = false;
9741                     }
9742                 }
9743
9744                 public void startRunningLocked() {
9745                     if (!mRunning) {
9746                         mStarts++;
9747                         mRunningSince = mBsi.getBatteryUptimeLocked();
9748                         mRunning = true;
9749                     }
9750                 }
9751
9752                 public void stopRunningLocked() {
9753                     if (mRunning) {
9754                         long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
9755                         if (time > 0) {
9756                             mStartTime += time;
9757                         } else {
9758                             mStarts--;
9759                         }
9760                         mRunning = false;
9761                     }
9762                 }
9763
9764                 public BatteryStatsImpl getBatteryStats() {
9765                     return mBsi;
9766                 }
9767
9768                 @Override
9769                 public int getLaunches(int which) {
9770                     int val = mLaunches;
9771                     if (which == STATS_CURRENT) {
9772                         val -= mLoadedLaunches;
9773                     } else if (which == STATS_SINCE_UNPLUGGED) {
9774                         val -= mUnpluggedLaunches;
9775                     }
9776                     return val;
9777                 }
9778
9779                 @Override
9780                 public long getStartTime(long now, int which) {
9781                     long val = getStartTimeToNowLocked(now);
9782                     if (which == STATS_CURRENT) {
9783                         val -= mLoadedStartTime;
9784                     } else if (which == STATS_SINCE_UNPLUGGED) {
9785                         val -= mUnpluggedStartTime;
9786                     }
9787                     return val;
9788                 }
9789
9790                 @Override
9791                 public int getStarts(int which) {
9792                     int val = mStarts;
9793                     if (which == STATS_CURRENT) {
9794                         val -= mLoadedStarts;
9795                     } else if (which == STATS_SINCE_UNPLUGGED) {
9796                         val -= mUnpluggedStarts;
9797                     }
9798
9799                     return val;
9800                 }
9801             }
9802
9803             final Serv newServiceStatsLocked() {
9804                 return new Serv(mBsi);
9805             }
9806         }
9807
9808         /**
9809          * Retrieve the statistics object for a particular process, creating
9810          * if needed.
9811          */
9812         public Proc getProcessStatsLocked(String name) {
9813             Proc ps = mProcessStats.get(name);
9814             if (ps == null) {
9815                 ps = new Proc(mBsi, name);
9816                 mProcessStats.put(name, ps);
9817             }
9818
9819             return ps;
9820         }
9821
9822         @GuardedBy("mBsi")
9823         public void updateUidProcessStateLocked(int procState) {
9824             int uidRunningState;
9825             // Make special note of Foreground Services
9826             final boolean userAwareService =
9827                     (procState == ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
9828             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
9829
9830             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
9831                 return;
9832             }
9833
9834             final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
9835             if (mProcessState != uidRunningState) {
9836                 final long uptimeMs = mBsi.mClocks.uptimeMillis();
9837
9838                 if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9839                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
9840
9841                     if (mBsi.trackPerProcStateCpuTimes()) {
9842                         if (mBsi.mPendingUids.size() == 0) {
9843                             mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
9844                                     mBsi.mOnBatteryTimeBase.isRunning(),
9845                                     mBsi.mOnBatteryScreenOffTimeBase.isRunning(),
9846                                     mBsi.mConstants.PROC_STATE_CPU_TIMES_READ_DELAY_MS);
9847                             mBsi.mNumCpuTimeReads++;
9848                         } else {
9849                             mBsi.mNumBatchedCpuTimeReads++;
9850                         }
9851                         if (mBsi.mPendingUids.indexOfKey(mUid) < 0
9852                                 || ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
9853                             mBsi.mPendingUids.put(mUid, mProcessState);
9854                         }
9855                     } else {
9856                         mBsi.mPendingUids.clear();
9857                     }
9858                 }
9859                 mProcessState = uidRunningState;
9860                 if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9861                     if (mProcessStateTimer[uidRunningState] == null) {
9862                         makeProcessState(uidRunningState, null);
9863                     }
9864                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
9865                 }
9866
9867                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9868                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9869             }
9870
9871             if (userAwareService != mInForegroundService) {
9872                 if (userAwareService) {
9873                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
9874                 } else {
9875                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
9876                 }
9877                 mInForegroundService = userAwareService;
9878             }
9879         }
9880
9881         /** Whether to consider Uid to be in the background for background timebase purposes. */
9882         public boolean isInBackground() {
9883             // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
9884             // also considered to be 'background' for our purposes, because it's not foreground.
9885             return mProcessState >= PROCESS_STATE_BACKGROUND;
9886         }
9887
9888         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
9889             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
9890             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9891         }
9892
9893         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
9894             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
9895             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9896         }
9897
9898         public SparseArray<? extends Pid> getPidStats() {
9899             return mPids;
9900         }
9901
9902         public Pid getPidStatsLocked(int pid) {
9903             Pid p = mPids.get(pid);
9904             if (p == null) {
9905                 p = new Pid();
9906                 mPids.put(pid, p);
9907             }
9908             return p;
9909         }
9910
9911         /**
9912          * Retrieve the statistics object for a particular service, creating
9913          * if needed.
9914          */
9915         public Pkg getPackageStatsLocked(String name) {
9916             Pkg ps = mPackageStats.get(name);
9917             if (ps == null) {
9918                 ps = new Pkg(mBsi);
9919                 mPackageStats.put(name, ps);
9920             }
9921
9922             return ps;
9923         }
9924
9925         /**
9926          * Retrieve the statistics object for a particular service, creating
9927          * if needed.
9928          */
9929         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
9930             Pkg ps = getPackageStatsLocked(pkg);
9931             Pkg.Serv ss = ps.mServiceStats.get(serv);
9932             if (ss == null) {
9933                 ss = ps.newServiceStatsLocked();
9934                 ps.mServiceStats.put(serv, ss);
9935             }
9936
9937             return ss;
9938         }
9939
9940         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
9941             DualTimer timer = mSyncStats.instantiateObject();
9942             timer.readSummaryFromParcelLocked(in);
9943             mSyncStats.add(name, timer);
9944         }
9945
9946         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
9947             DualTimer timer = mJobStats.instantiateObject();
9948             timer.readSummaryFromParcelLocked(in);
9949             mJobStats.add(name, timer);
9950         }
9951
9952         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
9953             Wakelock wl = new Wakelock(mBsi, this);
9954             mWakelockStats.add(wlName, wl);
9955             if (in.readInt() != 0) {
9956                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
9957             }
9958             if (in.readInt() != 0) {
9959                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
9960             }
9961             if (in.readInt() != 0) {
9962                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
9963             }
9964             if (in.readInt() != 0) {
9965                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
9966             }
9967         }
9968
9969         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
9970             Sensor se = mSensorStats.get(sensor);
9971             if (se == null) {
9972                 if (!create) {
9973                     return null;
9974                 }
9975                 se = new Sensor(mBsi, this, sensor);
9976                 mSensorStats.put(sensor, se);
9977             }
9978             DualTimer t = se.mTimer;
9979             if (t != null) {
9980                 return t;
9981             }
9982             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
9983             if (timers == null) {
9984                 timers = new ArrayList<StopwatchTimer>();
9985                 mBsi.mSensorTimers.put(sensor, timers);
9986             }
9987             t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
9988                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
9989             se.mTimer = t;
9990             return t;
9991         }
9992
9993         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
9994             DualTimer t = mSyncStats.startObject(name);
9995             if (t != null) {
9996                 t.startRunningLocked(elapsedRealtimeMs);
9997                 StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, getUid(), null, name,
9998                         StatsLog.SYNC_STATE_CHANGED__STATE__ON);
9999             }
10000         }
10001
10002         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
10003             DualTimer t = mSyncStats.stopObject(name);
10004             if (t != null) {
10005                 t.stopRunningLocked(elapsedRealtimeMs);
10006                 if (!t.isRunningLocked()) { // only tell statsd if truly stopped
10007                     StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, getUid(), null, name,
10008                             StatsLog.SYNC_STATE_CHANGED__STATE__OFF);
10009                 }
10010             }
10011         }
10012
10013         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
10014             DualTimer t = mJobStats.startObject(name);
10015             if (t != null) {
10016                 t.startRunningLocked(elapsedRealtimeMs);
10017                 StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), null,
10018                         name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__STARTED);
10019             }
10020         }
10021
10022         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
10023             DualTimer t = mJobStats.stopObject(name);
10024             if (t != null) {
10025                 t.stopRunningLocked(elapsedRealtimeMs);
10026                 if (!t.isRunningLocked()) { // only tell statsd if truly stopped
10027                     StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), null,
10028                             name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__FINISHED);
10029                 }
10030             }
10031             if (mBsi.mOnBatteryTimeBase.isRunning()) {
10032                 SparseIntArray types = mJobCompletions.get(name);
10033                 if (types == null) {
10034                     types = new SparseIntArray();
10035                     mJobCompletions.put(name, types);
10036                 }
10037                 int last = types.get(stopReason, 0);
10038                 types.put(stopReason, last + 1);
10039             }
10040         }
10041
10042         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
10043             if (wl == null) {
10044                 return null;
10045             }
10046             switch (type) {
10047                 case WAKE_TYPE_PARTIAL: {
10048                     DualTimer t = wl.mTimerPartial;
10049                     if (t == null) {
10050                         t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
10051                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
10052                                 mOnBatteryScreenOffBackgroundTimeBase);
10053                         wl.mTimerPartial = t;
10054                     }
10055                     return t;
10056                 }
10057                 case WAKE_TYPE_FULL: {
10058                     StopwatchTimer t = wl.mTimerFull;
10059                     if (t == null) {
10060                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
10061                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
10062                         wl.mTimerFull = t;
10063                     }
10064                     return t;
10065                 }
10066                 case WAKE_TYPE_WINDOW: {
10067                     StopwatchTimer t = wl.mTimerWindow;
10068                     if (t == null) {
10069                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
10070                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
10071                         wl.mTimerWindow = t;
10072                     }
10073                     return t;
10074                 }
10075                 case WAKE_TYPE_DRAW: {
10076                     StopwatchTimer t = wl.mTimerDraw;
10077                     if (t == null) {
10078                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
10079                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
10080                         wl.mTimerDraw = t;
10081                     }
10082                     return t;
10083                 }
10084                 default:
10085                     throw new IllegalArgumentException("type=" + type);
10086             }
10087         }
10088
10089         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10090             Wakelock wl = mWakelockStats.startObject(name);
10091             if (wl != null) {
10092                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
10093             }
10094             if (type == WAKE_TYPE_PARTIAL) {
10095                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
10096                 if (pid >= 0) {
10097                     Pid p = getPidStatsLocked(pid);
10098                     if (p.mWakeNesting++ == 0) {
10099                         p.mWakeStartMs = elapsedRealtimeMs;
10100                     }
10101                 }
10102             }
10103         }
10104
10105         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10106             Wakelock wl = mWakelockStats.stopObject(name);
10107             if (wl != null) {
10108                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
10109                 wlt.stopRunningLocked(elapsedRealtimeMs);
10110             }
10111             if (type == WAKE_TYPE_PARTIAL) {
10112                 if (mAggregatedPartialWakelockTimer != null) {
10113                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
10114                 }
10115                 if (pid >= 0) {
10116                     Pid p = mPids.get(pid);
10117                     if (p != null && p.mWakeNesting > 0) {
10118                         if (p.mWakeNesting-- == 1) {
10119                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
10120                             p.mWakeStartMs = 0;
10121                         }
10122                     }
10123                 }
10124             }
10125         }
10126
10127         public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
10128             Proc p = getProcessStatsLocked(proc);
10129             if (p != null) {
10130                 p.addExcessiveCpu(overTime, usedTime);
10131             }
10132         }
10133
10134         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
10135             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
10136             t.startRunningLocked(elapsedRealtimeMs);
10137             if (sensor != Sensor.GPS) {
10138                 StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null, sensor,
10139                         StatsLog.SENSOR_STATE_CHANGED__STATE__ON);
10140             }
10141         }
10142
10143         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
10144             // Don't create a timer if one doesn't already exist
10145             DualTimer t = getSensorTimerLocked(sensor, false);
10146             if (t != null) {
10147                 t.stopRunningLocked(elapsedRealtimeMs);
10148                 if (sensor != Sensor.GPS) {
10149                     StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null,
10150                              sensor, StatsLog.SENSOR_STATE_CHANGED__STATE__OFF);
10151                 }
10152             }
10153         }
10154
10155         public void noteStartGps(long elapsedRealtimeMs) {
10156             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
10157         }
10158
10159         public void noteStopGps(long elapsedRealtimeMs) {
10160             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
10161         }
10162
10163         public BatteryStatsImpl getBatteryStats() {
10164             return mBsi;
10165         }
10166     }
10167
10168     public long[] getCpuFreqs() {
10169         return mCpuFreqs;
10170     }
10171
10172     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
10173             UserInfoProvider userInfoProvider) {
10174         this(new SystemClocks(), systemDir, handler, cb, userInfoProvider);
10175     }
10176
10177     private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
10178             PlatformIdleStateCallback cb,
10179             UserInfoProvider userInfoProvider) {
10180         init(clocks);
10181
10182         if (systemDir != null) {
10183             mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
10184                     new File(systemDir, "batterystats.bin.tmp"));
10185         } else {
10186             mFile = null;
10187         }
10188         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
10189         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
10190         mHandler = new MyHandler(handler.getLooper());
10191         mConstants = new Constants(mHandler);
10192         mStartCount++;
10193         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
10194         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
10195         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10196             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
10197                     mOnBatteryTimeBase);
10198         }
10199         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
10200         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
10201                 mOnBatteryTimeBase);
10202         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
10203                 mOnBatteryTimeBase);
10204         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
10205         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
10206         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
10207         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
10208         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10209             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
10210                     mOnBatteryTimeBase);
10211         }
10212         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
10213                 mOnBatteryTimeBase);
10214         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10215             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
10216                     mOnBatteryTimeBase);
10217         }
10218         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10219             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
10220             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
10221         }
10222         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
10223         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10224                 NUM_BT_TX_LEVELS);
10225         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10226                 ModemActivityInfo.TX_POWER_LEVELS);
10227         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
10228         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
10229                 mOnBatteryTimeBase);
10230         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
10231         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
10232         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
10233         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null,
10234                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
10235         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
10236         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
10237         for (int i=0; i<NUM_WIFI_STATES; i++) {
10238             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
10239                     mOnBatteryTimeBase);
10240         }
10241         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10242             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
10243                     mOnBatteryTimeBase);
10244         }
10245         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10246             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
10247                     mOnBatteryTimeBase);
10248         }
10249         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
10250         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
10251             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
10252                 mOnBatteryTimeBase);
10253         }
10254         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
10255         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
10256         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
10257         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
10258         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
10259         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
10260         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10261         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10262         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10263         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10264         mOnBattery = mOnBatteryInternal = false;
10265         long uptime = mClocks.uptimeMillis() * 1000;
10266         long realtime = mClocks.elapsedRealtime() * 1000;
10267         initTimes(uptime, realtime);
10268         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
10269         mDischargeStartLevel = 0;
10270         mDischargeUnplugLevel = 0;
10271         mDischargePlugLevel = -1;
10272         mDischargeCurrentLevel = 0;
10273         mCurrentBatteryLevel = 0;
10274         initDischarge();
10275         clearHistoryLocked();
10276         updateDailyDeadlineLocked();
10277         mPlatformIdleStateCallback = cb;
10278         mUserInfoProvider = userInfoProvider;
10279     }
10280
10281     public BatteryStatsImpl(Parcel p) {
10282         this(new SystemClocks(), p);
10283     }
10284
10285     public BatteryStatsImpl(Clocks clocks, Parcel p) {
10286         init(clocks);
10287         mFile = null;
10288         mCheckinFile = null;
10289         mDailyFile = null;
10290         mHandler = null;
10291         mExternalSync = null;
10292         mConstants = new Constants(mHandler);
10293         clearHistoryLocked();
10294         readFromParcel(p);
10295         mPlatformIdleStateCallback = null;
10296     }
10297
10298     public void setPowerProfileLocked(PowerProfile profile) {
10299         mPowerProfile = profile;
10300
10301         // We need to initialize the KernelCpuSpeedReaders to read from
10302         // the first cpu of each core. Once we have the PowerProfile, we have access to this
10303         // information.
10304         final int numClusters = mPowerProfile.getNumCpuClusters();
10305         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
10306         int firstCpuOfCluster = 0;
10307         for (int i = 0; i < numClusters; i++) {
10308             final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
10309             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
10310                     numSpeedSteps);
10311             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
10312         }
10313
10314         if (mEstimatedBatteryCapacity == -1) {
10315             // Initialize the estimated battery capacity to a known preset one.
10316             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
10317         }
10318     }
10319
10320     public void setCallback(BatteryCallback cb) {
10321         mCallback = cb;
10322     }
10323
10324     public void setRadioScanningTimeoutLocked(long timeout) {
10325         if (mPhoneSignalScanningTimer != null) {
10326             mPhoneSignalScanningTimer.setTimeout(timeout);
10327         }
10328     }
10329
10330     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
10331         mExternalSync = sync;
10332     }
10333
10334     public void updateDailyDeadlineLocked() {
10335         // Get the current time.
10336         long currentTime = mDailyStartTime = System.currentTimeMillis();
10337         Calendar calDeadline = Calendar.getInstance();
10338         calDeadline.setTimeInMillis(currentTime);
10339
10340         // Move time up to the next day, ranging from 1am to 3pm.
10341         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
10342         calDeadline.set(Calendar.MILLISECOND, 0);
10343         calDeadline.set(Calendar.SECOND, 0);
10344         calDeadline.set(Calendar.MINUTE, 0);
10345         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
10346         mNextMinDailyDeadline = calDeadline.getTimeInMillis();
10347         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
10348         mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
10349     }
10350
10351     public void recordDailyStatsIfNeededLocked(boolean settled) {
10352         long currentTime = System.currentTimeMillis();
10353         if (currentTime >= mNextMaxDailyDeadline) {
10354             recordDailyStatsLocked();
10355         } else if (settled && currentTime >= mNextMinDailyDeadline) {
10356             recordDailyStatsLocked();
10357         } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
10358             recordDailyStatsLocked();
10359         }
10360     }
10361
10362     public void recordDailyStatsLocked() {
10363         DailyItem item = new DailyItem();
10364         item.mStartTime = mDailyStartTime;
10365         item.mEndTime = System.currentTimeMillis();
10366         boolean hasData = false;
10367         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
10368             hasData = true;
10369             item.mDischargeSteps = new LevelStepTracker(
10370                     mDailyDischargeStepTracker.mNumStepDurations,
10371                     mDailyDischargeStepTracker.mStepDurations);
10372         }
10373         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
10374             hasData = true;
10375             item.mChargeSteps = new LevelStepTracker(
10376                     mDailyChargeStepTracker.mNumStepDurations,
10377                     mDailyChargeStepTracker.mStepDurations);
10378         }
10379         if (mDailyPackageChanges != null) {
10380             hasData = true;
10381             item.mPackageChanges = mDailyPackageChanges;
10382             mDailyPackageChanges = null;
10383         }
10384         mDailyDischargeStepTracker.init();
10385         mDailyChargeStepTracker.init();
10386         updateDailyDeadlineLocked();
10387
10388         if (hasData) {
10389             final long startTime = SystemClock.uptimeMillis();
10390             mDailyItems.add(item);
10391             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
10392                 mDailyItems.remove(0);
10393             }
10394             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
10395             try {
10396                 XmlSerializer out = new FastXmlSerializer();
10397                 out.setOutput(memStream, StandardCharsets.UTF_8.name());
10398                 writeDailyItemsLocked(out);
10399                 final long initialTime = SystemClock.uptimeMillis() - startTime;
10400                 BackgroundThread.getHandler().post(new Runnable() {
10401                     @Override
10402                     public void run() {
10403                         synchronized (mCheckinFile) {
10404                             final long startTime2 = SystemClock.uptimeMillis();
10405                             FileOutputStream stream = null;
10406                             try {
10407                                 stream = mDailyFile.startWrite();
10408                                 memStream.writeTo(stream);
10409                                 stream.flush();
10410                                 FileUtils.sync(stream);
10411                                 stream.close();
10412                                 mDailyFile.finishWrite(stream);
10413                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
10414                                         "batterystats-daily",
10415                                         initialTime + SystemClock.uptimeMillis() - startTime2);
10416                             } catch (IOException e) {
10417                                 Slog.w("BatteryStats",
10418                                         "Error writing battery daily items", e);
10419                                 mDailyFile.failWrite(stream);
10420                             }
10421                         }
10422                     }
10423                 });
10424             } catch (IOException e) {
10425             }
10426         }
10427     }
10428
10429     private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
10430         StringBuilder sb = new StringBuilder(64);
10431         out.startDocument(null, true);
10432         out.startTag(null, "daily-items");
10433         for (int i=0; i<mDailyItems.size(); i++) {
10434             final DailyItem dit = mDailyItems.get(i);
10435             out.startTag(null, "item");
10436             out.attribute(null, "start", Long.toString(dit.mStartTime));
10437             out.attribute(null, "end", Long.toString(dit.mEndTime));
10438             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
10439             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
10440             if (dit.mPackageChanges != null) {
10441                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
10442                     PackageChange pc = dit.mPackageChanges.get(j);
10443                     if (pc.mUpdate) {
10444                         out.startTag(null, "upd");
10445                         out.attribute(null, "pkg", pc.mPackageName);
10446                         out.attribute(null, "ver", Long.toString(pc.mVersionCode));
10447                         out.endTag(null, "upd");
10448                     } else {
10449                         out.startTag(null, "rem");
10450                         out.attribute(null, "pkg", pc.mPackageName);
10451                         out.endTag(null, "rem");
10452                     }
10453                 }
10454             }
10455             out.endTag(null, "item");
10456         }
10457         out.endTag(null, "daily-items");
10458         out.endDocument();
10459     }
10460
10461     private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
10462             StringBuilder tmpBuilder) throws IOException {
10463         if (steps != null) {
10464             out.startTag(null, tag);
10465             out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
10466             for (int i=0; i<steps.mNumStepDurations; i++) {
10467                 out.startTag(null, "s");
10468                 tmpBuilder.setLength(0);
10469                 steps.encodeEntryAt(i, tmpBuilder);
10470                 out.attribute(null, "v", tmpBuilder.toString());
10471                 out.endTag(null, "s");
10472             }
10473             out.endTag(null, tag);
10474         }
10475     }
10476
10477     public void readDailyStatsLocked() {
10478         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
10479         mDailyItems.clear();
10480         FileInputStream stream;
10481         try {
10482             stream = mDailyFile.openRead();
10483         } catch (FileNotFoundException e) {
10484             return;
10485         }
10486         try {
10487             XmlPullParser parser = Xml.newPullParser();
10488             parser.setInput(stream, StandardCharsets.UTF_8.name());
10489             readDailyItemsLocked(parser);
10490         } catch (XmlPullParserException e) {
10491         } finally {
10492             try {
10493                 stream.close();
10494             } catch (IOException e) {
10495             }
10496         }
10497     }
10498
10499     private void readDailyItemsLocked(XmlPullParser parser) {
10500         try {
10501             int type;
10502             while ((type = parser.next()) != XmlPullParser.START_TAG
10503                     && type != XmlPullParser.END_DOCUMENT) {
10504                 ;
10505             }
10506
10507             if (type != XmlPullParser.START_TAG) {
10508                 throw new IllegalStateException("no start tag found");
10509             }
10510
10511             int outerDepth = parser.getDepth();
10512             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10513                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10514                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10515                     continue;
10516                 }
10517
10518                 String tagName = parser.getName();
10519                 if (tagName.equals("item")) {
10520                     readDailyItemTagLocked(parser);
10521                 } else {
10522                     Slog.w(TAG, "Unknown element under <daily-items>: "
10523                             + parser.getName());
10524                     XmlUtils.skipCurrentTag(parser);
10525                 }
10526             }
10527
10528         } catch (IllegalStateException e) {
10529             Slog.w(TAG, "Failed parsing daily " + e);
10530         } catch (NullPointerException e) {
10531             Slog.w(TAG, "Failed parsing daily " + e);
10532         } catch (NumberFormatException e) {
10533             Slog.w(TAG, "Failed parsing daily " + e);
10534         } catch (XmlPullParserException e) {
10535             Slog.w(TAG, "Failed parsing daily " + e);
10536         } catch (IOException e) {
10537             Slog.w(TAG, "Failed parsing daily " + e);
10538         } catch (IndexOutOfBoundsException e) {
10539             Slog.w(TAG, "Failed parsing daily " + e);
10540         }
10541     }
10542
10543     void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
10544             XmlPullParserException, IOException {
10545         DailyItem dit = new DailyItem();
10546         String attr = parser.getAttributeValue(null, "start");
10547         if (attr != null) {
10548             dit.mStartTime = Long.parseLong(attr);
10549         }
10550         attr = parser.getAttributeValue(null, "end");
10551         if (attr != null) {
10552             dit.mEndTime = Long.parseLong(attr);
10553         }
10554         int outerDepth = parser.getDepth();
10555         int type;
10556         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10557                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10558             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10559                 continue;
10560             }
10561
10562             String tagName = parser.getName();
10563             if (tagName.equals("dis")) {
10564                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
10565             } else if (tagName.equals("chg")) {
10566                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
10567             } else if (tagName.equals("upd")) {
10568                 if (dit.mPackageChanges == null) {
10569                     dit.mPackageChanges = new ArrayList<>();
10570                 }
10571                 PackageChange pc = new PackageChange();
10572                 pc.mUpdate = true;
10573                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
10574                 String verStr = parser.getAttributeValue(null, "ver");
10575                 pc.mVersionCode = verStr != null ? Long.parseLong(verStr) : 0;
10576                 dit.mPackageChanges.add(pc);
10577                 XmlUtils.skipCurrentTag(parser);
10578             } else if (tagName.equals("rem")) {
10579                 if (dit.mPackageChanges == null) {
10580                     dit.mPackageChanges = new ArrayList<>();
10581                 }
10582                 PackageChange pc = new PackageChange();
10583                 pc.mUpdate = false;
10584                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
10585                 dit.mPackageChanges.add(pc);
10586                 XmlUtils.skipCurrentTag(parser);
10587             } else {
10588                 Slog.w(TAG, "Unknown element under <item>: "
10589                         + parser.getName());
10590                 XmlUtils.skipCurrentTag(parser);
10591             }
10592         }
10593         mDailyItems.add(dit);
10594     }
10595
10596     void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
10597             String tag)
10598             throws NumberFormatException, XmlPullParserException, IOException {
10599         final String numAttr = parser.getAttributeValue(null, "n");
10600         if (numAttr == null) {
10601             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
10602             XmlUtils.skipCurrentTag(parser);
10603             return;
10604         }
10605         final int num = Integer.parseInt(numAttr);
10606         LevelStepTracker steps = new LevelStepTracker(num);
10607         if (isCharge) {
10608             dit.mChargeSteps = steps;
10609         } else {
10610             dit.mDischargeSteps = steps;
10611         }
10612         int i = 0;
10613         int outerDepth = parser.getDepth();
10614         int type;
10615         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10616                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10617             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10618                 continue;
10619             }
10620
10621             String tagName = parser.getName();
10622             if ("s".equals(tagName)) {
10623                 if (i < num) {
10624                     String valueAttr = parser.getAttributeValue(null, "v");
10625                     if (valueAttr != null) {
10626                         steps.decodeEntryAt(i, valueAttr);
10627                         i++;
10628                     }
10629                 }
10630             } else {
10631                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
10632                         + parser.getName());
10633                 XmlUtils.skipCurrentTag(parser);
10634             }
10635         }
10636         steps.mNumStepDurations = i;
10637     }
10638
10639     @Override
10640     public DailyItem getDailyItemLocked(int daysAgo) {
10641         int index = mDailyItems.size()-1-daysAgo;
10642         return index >= 0 ? mDailyItems.get(index) : null;
10643     }
10644
10645     @Override
10646     public long getCurrentDailyStartTime() {
10647         return mDailyStartTime;
10648     }
10649
10650     @Override
10651     public long getNextMinDailyDeadline() {
10652         return mNextMinDailyDeadline;
10653     }
10654
10655     @Override
10656     public long getNextMaxDailyDeadline() {
10657         return mNextMaxDailyDeadline;
10658     }
10659
10660     @Override
10661     public boolean startIteratingOldHistoryLocked() {
10662         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
10663                 + " pos=" + mHistoryBuffer.dataPosition());
10664         if ((mHistoryIterator = mHistory) == null) {
10665             return false;
10666         }
10667         mHistoryBuffer.setDataPosition(0);
10668         mHistoryReadTmp.clear();
10669         mReadOverflow = false;
10670         mIteratingHistory = true;
10671         return true;
10672     }
10673
10674     @Override
10675     public boolean getNextOldHistoryLocked(HistoryItem out) {
10676         boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
10677         if (!end) {
10678             readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
10679             mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
10680         }
10681         HistoryItem cur = mHistoryIterator;
10682         if (cur == null) {
10683             if (!mReadOverflow && !end) {
10684                 Slog.w(TAG, "Old history ends before new history!");
10685             }
10686             return false;
10687         }
10688         out.setTo(cur);
10689         mHistoryIterator = cur.next;
10690         if (!mReadOverflow) {
10691             if (end) {
10692                 Slog.w(TAG, "New history ends before old history!");
10693             } else if (!out.same(mHistoryReadTmp)) {
10694                 PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
10695                 pw.println("Histories differ!");
10696                 pw.println("Old history:");
10697                 (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
10698                 pw.println("New history:");
10699                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
10700                         true);
10701                 pw.flush();
10702             }
10703         }
10704         return true;
10705     }
10706
10707     @Override
10708     public void finishIteratingOldHistoryLocked() {
10709         mIteratingHistory = false;
10710         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
10711         mHistoryIterator = null;
10712     }
10713
10714     public int getHistoryTotalSize() {
10715         return MAX_HISTORY_BUFFER;
10716     }
10717
10718     public int getHistoryUsedSize() {
10719         return mHistoryBuffer.dataSize();
10720     }
10721
10722     @Override
10723     public boolean startIteratingHistoryLocked() {
10724         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
10725                 + " pos=" + mHistoryBuffer.dataPosition());
10726         if (mHistoryBuffer.dataSize() <= 0) {
10727             return false;
10728         }
10729         mHistoryBuffer.setDataPosition(0);
10730         mReadOverflow = false;
10731         mIteratingHistory = true;
10732         mReadHistoryStrings = new String[mHistoryTagPool.size()];
10733         mReadHistoryUids = new int[mHistoryTagPool.size()];
10734         mReadHistoryChars = 0;
10735         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
10736             final HistoryTag tag = ent.getKey();
10737             final int idx = ent.getValue();
10738             mReadHistoryStrings[idx] = tag.string;
10739             mReadHistoryUids[idx] = tag.uid;
10740             mReadHistoryChars += tag.string.length() + 1;
10741         }
10742         return true;
10743     }
10744
10745     @Override
10746     public int getHistoryStringPoolSize() {
10747         return mReadHistoryStrings.length;
10748     }
10749
10750     @Override
10751     public int getHistoryStringPoolBytes() {
10752         // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
10753         // Each string character is 2 bytes.
10754         return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
10755     }
10756
10757     @Override
10758     public String getHistoryTagPoolString(int index) {
10759         return mReadHistoryStrings[index];
10760     }
10761
10762     @Override
10763     public int getHistoryTagPoolUid(int index) {
10764         return mReadHistoryUids[index];
10765     }
10766
10767     @Override
10768     public boolean getNextHistoryLocked(HistoryItem out) {
10769         final int pos = mHistoryBuffer.dataPosition();
10770         if (pos == 0) {
10771             out.clear();
10772         }
10773         boolean end = pos >= mHistoryBuffer.dataSize();
10774         if (end) {
10775             return false;
10776         }
10777
10778         final long lastRealtime = out.time;
10779         final long lastWalltime = out.currentTime;
10780         readHistoryDelta(mHistoryBuffer, out);
10781         if (out.cmd != HistoryItem.CMD_CURRENT_TIME
10782                 && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
10783             out.currentTime = lastWalltime + (out.time - lastRealtime);
10784         }
10785         return true;
10786     }
10787
10788     @Override
10789     public void finishIteratingHistoryLocked() {
10790         mIteratingHistory = false;
10791         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
10792         mReadHistoryStrings = null;
10793     }
10794
10795     @Override
10796     public long getHistoryBaseTime() {
10797         return mHistoryBaseTime;
10798     }
10799
10800     @Override
10801     public int getStartCount() {
10802         return mStartCount;
10803     }
10804
10805     public boolean isOnBattery() {
10806         return mOnBattery;
10807     }
10808
10809     public boolean isCharging() {
10810         return mCharging;
10811     }
10812
10813     public boolean isScreenOn(int state) {
10814         return state == Display.STATE_ON || state == Display.STATE_VR
10815             || state == Display.STATE_ON_SUSPEND;
10816     }
10817
10818     public boolean isScreenOff(int state) {
10819         return state == Display.STATE_OFF;
10820     }
10821
10822     public boolean isScreenDoze(int state) {
10823         return state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND;
10824     }
10825
10826     void initTimes(long uptime, long realtime) {
10827         mStartClockTime = System.currentTimeMillis();
10828         mOnBatteryTimeBase.init(uptime, realtime);
10829         mOnBatteryScreenOffTimeBase.init(uptime, realtime);
10830         mRealtime = 0;
10831         mUptime = 0;
10832         mRealtimeStart = realtime;
10833         mUptimeStart = uptime;
10834     }
10835
10836     void initDischarge() {
10837         mLowDischargeAmountSinceCharge = 0;
10838         mHighDischargeAmountSinceCharge = 0;
10839         mDischargeAmountScreenOn = 0;
10840         mDischargeAmountScreenOnSinceCharge = 0;
10841         mDischargeAmountScreenOff = 0;
10842         mDischargeAmountScreenOffSinceCharge = 0;
10843         mDischargeAmountScreenDoze = 0;
10844         mDischargeAmountScreenDozeSinceCharge = 0;
10845         mDischargeStepTracker.init();
10846         mChargeStepTracker.init();
10847         mDischargeScreenOffCounter.reset(false);
10848         mDischargeScreenDozeCounter.reset(false);
10849         mDischargeLightDozeCounter.reset(false);
10850         mDischargeDeepDozeCounter.reset(false);
10851         mDischargeCounter.reset(false);
10852     }
10853
10854     public void resetAllStatsCmdLocked() {
10855         resetAllStatsLocked();
10856         final long mSecUptime = mClocks.uptimeMillis();
10857         long uptime = mSecUptime * 1000;
10858         long mSecRealtime = mClocks.elapsedRealtime();
10859         long realtime = mSecRealtime * 1000;
10860         mDischargeStartLevel = mHistoryCur.batteryLevel;
10861         pullPendingStateUpdatesLocked();
10862         addHistoryRecordLocked(mSecRealtime, mSecUptime);
10863         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
10864                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
10865         mOnBatteryTimeBase.reset(uptime, realtime);
10866         mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
10867         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
10868             if (isScreenOn(mScreenState)) {
10869                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
10870                 mDischargeScreenDozeUnplugLevel = 0;
10871                 mDischargeScreenOffUnplugLevel = 0;
10872             } else if (isScreenDoze(mScreenState)) {
10873                 mDischargeScreenOnUnplugLevel = 0;
10874                 mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
10875                 mDischargeScreenOffUnplugLevel = 0;
10876             } else {
10877                 mDischargeScreenOnUnplugLevel = 0;
10878                 mDischargeScreenDozeUnplugLevel = 0;
10879                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
10880             }
10881             mDischargeAmountScreenOn = 0;
10882             mDischargeAmountScreenOff = 0;
10883             mDischargeAmountScreenDoze = 0;
10884         }
10885         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
10886     }
10887
10888     private void resetAllStatsLocked() {
10889         final long uptimeMillis = mClocks.uptimeMillis();
10890         final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
10891         mStartCount = 0;
10892         initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
10893         mScreenOnTimer.reset(false);
10894         mScreenDozeTimer.reset(false);
10895         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10896             mScreenBrightnessTimer[i].reset(false);
10897         }
10898
10899         if (mPowerProfile != null) {
10900             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
10901         } else {
10902             mEstimatedBatteryCapacity = -1;
10903         }
10904         mMinLearnedBatteryCapacity = -1;
10905         mMaxLearnedBatteryCapacity = -1;
10906         mInteractiveTimer.reset(false);
10907         mPowerSaveModeEnabledTimer.reset(false);
10908         mLastIdleTimeStart = elapsedRealtimeMillis;
10909         mLongestLightIdleTime = 0;
10910         mLongestFullIdleTime = 0;
10911         mDeviceIdleModeLightTimer.reset(false);
10912         mDeviceIdleModeFullTimer.reset(false);
10913         mDeviceLightIdlingTimer.reset(false);
10914         mDeviceIdlingTimer.reset(false);
10915         mPhoneOnTimer.reset(false);
10916         mAudioOnTimer.reset(false);
10917         mVideoOnTimer.reset(false);
10918         mFlashlightOnTimer.reset(false);
10919         mCameraOnTimer.reset(false);
10920         mBluetoothScanTimer.reset(false);
10921         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10922             mPhoneSignalStrengthsTimer[i].reset(false);
10923         }
10924         mPhoneSignalScanningTimer.reset(false);
10925         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10926             mPhoneDataConnectionsTimer[i].reset(false);
10927         }
10928         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10929             mNetworkByteActivityCounters[i].reset(false);
10930             mNetworkPacketActivityCounters[i].reset(false);
10931         }
10932         mMobileRadioActiveTimer.reset(false);
10933         mMobileRadioActivePerAppTimer.reset(false);
10934         mMobileRadioActiveAdjustedTime.reset(false);
10935         mMobileRadioActiveUnknownTime.reset(false);
10936         mMobileRadioActiveUnknownCount.reset(false);
10937         mWifiOnTimer.reset(false);
10938         mGlobalWifiRunningTimer.reset(false);
10939         for (int i=0; i<NUM_WIFI_STATES; i++) {
10940             mWifiStateTimer[i].reset(false);
10941         }
10942         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10943             mWifiSupplStateTimer[i].reset(false);
10944         }
10945         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10946             mWifiSignalStrengthsTimer[i].reset(false);
10947         }
10948         mWifiMulticastWakelockTimer.reset(false);
10949         mWifiActiveTimer.reset(false);
10950         mWifiActivity.reset(false);
10951         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
10952             mGpsSignalQualityTimer[i].reset(false);
10953         }
10954         mBluetoothActivity.reset(false);
10955         mModemActivity.reset(false);
10956         mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
10957
10958         for (int i=0; i<mUidStats.size(); i++) {
10959             if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
10960                 mUidStats.remove(mUidStats.keyAt(i));
10961                 i--;
10962             }
10963         }
10964
10965         if (mRpmStats.size() > 0) {
10966             for (SamplingTimer timer : mRpmStats.values()) {
10967                 mOnBatteryTimeBase.remove(timer);
10968             }
10969             mRpmStats.clear();
10970         }
10971         if (mScreenOffRpmStats.size() > 0) {
10972             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
10973                 mOnBatteryScreenOffTimeBase.remove(timer);
10974             }
10975             mScreenOffRpmStats.clear();
10976         }
10977
10978         if (mKernelWakelockStats.size() > 0) {
10979             for (SamplingTimer timer : mKernelWakelockStats.values()) {
10980                 mOnBatteryScreenOffTimeBase.remove(timer);
10981             }
10982             mKernelWakelockStats.clear();
10983         }
10984
10985         if (mKernelMemoryStats.size() > 0) {
10986             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
10987                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
10988             }
10989             mKernelMemoryStats.clear();
10990         }
10991
10992         if (mWakeupReasonStats.size() > 0) {
10993             for (SamplingTimer timer : mWakeupReasonStats.values()) {
10994                 mOnBatteryTimeBase.remove(timer);
10995             }
10996             mWakeupReasonStats.clear();
10997         }
10998
10999         mLastHistoryStepDetails = null;
11000         mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
11001         mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
11002         mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
11003         mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
11004         mLastStepStatUserTime = mCurStepStatUserTime = 0;
11005         mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
11006         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
11007         mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
11008         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
11009         mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
11010
11011         initDischarge();
11012
11013         clearHistoryLocked();
11014     }
11015
11016     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
11017         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
11018             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
11019                 // Not recording process starts/stops.
11020                 continue;
11021             }
11022             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
11023             if (active == null) {
11024                 continue;
11025             }
11026             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
11027                 SparseIntArray uids = ent.getValue();
11028                 for (int j=0; j<uids.size(); j++) {
11029                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
11030                             uids.keyAt(j));
11031                 }
11032             }
11033         }
11034     }
11035
11036     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
11037         updateOldDischargeScreenLevelLocked(oldState);
11038         updateNewDischargeScreenLevelLocked(newState);
11039     }
11040
11041     private void updateOldDischargeScreenLevelLocked(int state) {
11042         if (isScreenOn(state)) {
11043             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
11044             if (diff > 0) {
11045                 mDischargeAmountScreenOn += diff;
11046                 mDischargeAmountScreenOnSinceCharge += diff;
11047             }
11048         } else if (isScreenDoze(state)) {
11049             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
11050             if (diff > 0) {
11051                 mDischargeAmountScreenDoze += diff;
11052                 mDischargeAmountScreenDozeSinceCharge += diff;
11053             }
11054         } else if (isScreenOff(state)){
11055             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
11056             if (diff > 0) {
11057                 mDischargeAmountScreenOff += diff;
11058                 mDischargeAmountScreenOffSinceCharge += diff;
11059             }
11060         }
11061     }
11062
11063     private void updateNewDischargeScreenLevelLocked(int state) {
11064         if (isScreenOn(state)) {
11065             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
11066             mDischargeScreenOffUnplugLevel = 0;
11067             mDischargeScreenDozeUnplugLevel = 0;
11068         } else if (isScreenDoze(state)){
11069             mDischargeScreenOnUnplugLevel = 0;
11070             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
11071             mDischargeScreenOffUnplugLevel = 0;
11072         } else if (isScreenOff(state)) {
11073             mDischargeScreenOnUnplugLevel = 0;
11074             mDischargeScreenDozeUnplugLevel = 0;
11075             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
11076         }
11077     }
11078
11079     public void pullPendingStateUpdatesLocked() {
11080         if (mOnBatteryInternal) {
11081             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
11082         }
11083     }
11084
11085     private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
11086     private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
11087
11088     private final Object mWifiNetworkLock = new Object();
11089
11090     @GuardedBy("mWifiNetworkLock")
11091     private String[] mWifiIfaces = EmptyArray.STRING;
11092
11093     @GuardedBy("mWifiNetworkLock")
11094     private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
11095
11096     private final Object mModemNetworkLock = new Object();
11097
11098     @GuardedBy("mModemNetworkLock")
11099     private String[] mModemIfaces = EmptyArray.STRING;
11100
11101     @GuardedBy("mModemNetworkLock")
11102     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
11103
11104     private NetworkStats readNetworkStatsLocked(String[] ifaces) {
11105         try {
11106             if (!ArrayUtils.isEmpty(ifaces)) {
11107                 return mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
11108                         NetworkStats.TAG_NONE, mNetworkStatsPool.acquire());
11109             }
11110         } catch (IOException e) {
11111             Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces));
11112         }
11113         return null;
11114     }
11115
11116    /**
11117      * Distribute WiFi energy info and network traffic to apps.
11118      * @param info The energy information from the WiFi controller.
11119      */
11120     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
11121         if (DEBUG_ENERGY) {
11122             Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
11123         }
11124
11125         // Grab a separate lock to acquire the network stats, which may do I/O.
11126         NetworkStats delta = null;
11127         synchronized (mWifiNetworkLock) {
11128             final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
11129             if (latestStats != null) {
11130                 delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
11131                         mNetworkStatsPool.acquire());
11132                 mNetworkStatsPool.release(mLastWifiNetworkStats);
11133                 mLastWifiNetworkStats = latestStats;
11134             }
11135         }
11136
11137         synchronized (this) {
11138             if (!mOnBatteryInternal) {
11139                 if (delta != null) {
11140                     mNetworkStatsPool.release(delta);
11141                 }
11142                 return;
11143             }
11144
11145             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11146             SparseLongArray rxPackets = new SparseLongArray();
11147             SparseLongArray txPackets = new SparseLongArray();
11148             long totalTxPackets = 0;
11149             long totalRxPackets = 0;
11150             if (delta != null) {
11151                 NetworkStats.Entry entry = new NetworkStats.Entry();
11152                 final int size = delta.size();
11153                 for (int i = 0; i < size; i++) {
11154                     entry = delta.getValues(i, entry);
11155
11156                     if (DEBUG_ENERGY) {
11157                         Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
11158                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11159                                 + " txPackets=" + entry.txPackets);
11160                     }
11161
11162                     if (entry.rxBytes == 0 && entry.txBytes == 0) {
11163                         // Skip the lookup below since there is no work to do.
11164                         continue;
11165                     }
11166
11167                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
11168                     if (entry.rxBytes != 0) {
11169                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
11170                                 entry.rxPackets);
11171                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11172                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
11173                                     entry.rxPackets);
11174                         }
11175                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11176                                 entry.rxBytes);
11177                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11178                                 entry.rxPackets);
11179
11180                         rxPackets.put(u.getUid(), entry.rxPackets);
11181
11182                         // Sum the total number of packets so that the Rx Power can
11183                         // be evenly distributed amongst the apps.
11184                         totalRxPackets += entry.rxPackets;
11185                     }
11186
11187                     if (entry.txBytes != 0) {
11188                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
11189                                 entry.txPackets);
11190                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11191                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
11192                                     entry.txPackets);
11193                         }
11194                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11195                                 entry.txBytes);
11196                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11197                                 entry.txPackets);
11198
11199                         txPackets.put(u.getUid(), entry.txPackets);
11200
11201                         // Sum the total number of packets so that the Tx Power can
11202                         // be evenly distributed amongst the apps.
11203                         totalTxPackets += entry.txPackets;
11204                     }
11205                 }
11206                 mNetworkStatsPool.release(delta);
11207                 delta = null;
11208             }
11209
11210             if (info != null) {
11211                 mHasWifiReporting = true;
11212
11213                 // Measured in mAms
11214                 final long txTimeMs = info.getControllerTxTimeMillis();
11215                 final long rxTimeMs = info.getControllerRxTimeMillis();
11216                 final long scanTimeMs = info.getControllerScanTimeMillis();
11217                 final long idleTimeMs = info.getControllerIdleTimeMillis();
11218                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
11219
11220                 long leftOverRxTimeMs = rxTimeMs;
11221                 long leftOverTxTimeMs = txTimeMs;
11222
11223                 if (DEBUG_ENERGY) {
11224                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
11225                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11226                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11227                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11228                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
11229                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
11230                 }
11231
11232                 long totalWifiLockTimeMs = 0;
11233                 long totalScanTimeMs = 0;
11234
11235                 // On the first pass, collect some totals so that we can normalize power
11236                 // calculations if we need to.
11237                 final int uidStatsSize = mUidStats.size();
11238                 for (int i = 0; i < uidStatsSize; i++) {
11239                     final Uid uid = mUidStats.valueAt(i);
11240
11241                     // Sum the total scan power for all apps.
11242                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
11243                             elapsedRealtimeMs * 1000) / 1000;
11244
11245                     // Sum the total time holding wifi lock for all apps.
11246                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
11247                             elapsedRealtimeMs * 1000) / 1000;
11248                 }
11249
11250                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
11251                     Slog.d(TAG,
11252                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
11253                                     + rxTimeMs + " ms). Normalizing scan time.");
11254                 }
11255                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
11256                     Slog.d(TAG,
11257                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
11258                                     + txTimeMs + " ms). Normalizing scan time.");
11259                 }
11260
11261                 // Actually assign and distribute power usage to apps.
11262                 for (int i = 0; i < uidStatsSize; i++) {
11263                     final Uid uid = mUidStats.valueAt(i);
11264
11265                     long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
11266                             elapsedRealtimeMs * 1000) / 1000;
11267                     if (scanTimeSinceMarkMs > 0) {
11268                         // Set the new mark so that next time we get new data since this point.
11269                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
11270
11271                         long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
11272                         long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
11273
11274                         // Our total scan time is more than the reported Tx/Rx time.
11275                         // This is possible because the cost of a scan is approximate.
11276                         // Let's normalize the result so that we evenly blame each app
11277                         // scanning.
11278                         //
11279                         // This means that we may have apps that transmitted/received packets not be
11280                         // blamed for this, but this is fine as scans are relatively more expensive.
11281                         if (totalScanTimeMs > rxTimeMs) {
11282                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
11283                                     totalScanTimeMs;
11284                         }
11285                         if (totalScanTimeMs > txTimeMs) {
11286                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
11287                                     totalScanTimeMs;
11288                         }
11289
11290                         if (DEBUG_ENERGY) {
11291                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
11292                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
11293                                     + scanTxTimeSinceMarkMs + " ms)");
11294                         }
11295
11296                         ControllerActivityCounterImpl activityCounter =
11297                                 uid.getOrCreateWifiControllerActivityLocked();
11298                         activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
11299                         activityCounter.getTxTimeCounters()[0].addCountLocked(
11300                                 scanTxTimeSinceMarkMs);
11301                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
11302                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
11303                     }
11304
11305                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
11306                     // lock.
11307                     final long wifiLockTimeSinceMarkMs =
11308                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
11309                                     elapsedRealtimeMs * 1000) / 1000;
11310                     if (wifiLockTimeSinceMarkMs > 0) {
11311                         // Set the new mark so that next time we get new data since this point.
11312                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
11313
11314                         final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
11315                                 / totalWifiLockTimeMs;
11316                         if (DEBUG_ENERGY) {
11317                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
11318                                     + myIdleTimeMs + " ms");
11319                         }
11320                         uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
11321                                 .addCountLocked(myIdleTimeMs);
11322                     }
11323                 }
11324
11325                 if (DEBUG_ENERGY) {
11326                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
11327                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
11328                 }
11329
11330                 // Distribute the remaining Tx power appropriately between all apps that transmitted
11331                 // packets.
11332                 for (int i = 0; i < txPackets.size(); i++) {
11333                     final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
11334                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
11335                             / totalTxPackets;
11336                     if (DEBUG_ENERGY) {
11337                         Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
11338                     }
11339                     uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
11340                             .addCountLocked(myTxTimeMs);
11341                 }
11342
11343                 // Distribute the remaining Rx power appropriately between all apps that received
11344                 // packets.
11345                 for (int i = 0; i < rxPackets.size(); i++) {
11346                     final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
11347                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
11348                             / totalRxPackets;
11349                     if (DEBUG_ENERGY) {
11350                         Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
11351                     }
11352                     uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
11353                             .addCountLocked(myRxTimeMs);
11354                 }
11355
11356                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
11357
11358
11359                 // Update WiFi controller stats.
11360                 mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
11361                 mWifiActivity.getTxTimeCounters()[0].addCountLocked(
11362                         info.getControllerTxTimeMillis());
11363                 mWifiActivity.getScanTimeCounter().addCountLocked(
11364                     info.getControllerScanTimeMillis());
11365                 mWifiActivity.getIdleTimeCounter().addCountLocked(
11366                         info.getControllerIdleTimeMillis());
11367
11368                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11369                 final double opVolt = mPowerProfile.getAveragePower(
11370                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11371                 if (opVolt != 0) {
11372                     // We store the power drain as mAms.
11373                     mWifiActivity.getPowerCounter().addCountLocked(
11374                             (long) (info.getControllerEnergyUsed() / opVolt));
11375                 }
11376             }
11377         }
11378     }
11379
11380     private ModemActivityInfo mLastModemActivityInfo =
11381             new ModemActivityInfo(0, 0, 0, new int[0], 0, 0);
11382
11383     private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
11384         if (activityInfo == null) {
11385             return null;
11386         }
11387         int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
11388         for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
11389             txTimeMs[i] = activityInfo.getTxTimeMillis()[i]
11390                     - mLastModemActivityInfo.getTxTimeMillis()[i];
11391         }
11392         ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
11393                 activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
11394                 activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
11395                 txTimeMs,
11396                 activityInfo.getRxTimeMillis() - mLastModemActivityInfo.getRxTimeMillis(),
11397                 activityInfo.getEnergyUsed() - mLastModemActivityInfo.getEnergyUsed());
11398         mLastModemActivityInfo = activityInfo;
11399         return deltaInfo;
11400     }
11401
11402     /**
11403      * Distribute Cell radio energy info and network traffic to apps.
11404      */
11405     public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
11406         if (DEBUG_ENERGY) {
11407             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
11408         }
11409         ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
11410
11411         // Add modem tx power to history.
11412         addModemTxPowerToHistory(deltaInfo);
11413
11414         // Grab a separate lock to acquire the network stats, which may do I/O.
11415         NetworkStats delta = null;
11416         synchronized (mModemNetworkLock) {
11417             final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
11418             if (latestStats != null) {
11419                 delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
11420                         mNetworkStatsPool.acquire());
11421                 mNetworkStatsPool.release(mLastModemNetworkStats);
11422                 mLastModemNetworkStats = latestStats;
11423             }
11424         }
11425
11426         synchronized (this) {
11427             if (!mOnBatteryInternal) {
11428                 if (delta != null) {
11429                     mNetworkStatsPool.release(delta);
11430                 }
11431                 return;
11432             }
11433
11434             if (deltaInfo != null) {
11435                 mHasModemReporting = true;
11436                 mModemActivity.getIdleTimeCounter().addCountLocked(
11437                         deltaInfo.getIdleTimeMillis());
11438                 mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getRxTimeMillis());
11439                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11440                     mModemActivity.getTxTimeCounters()[lvl]
11441                         .addCountLocked(deltaInfo.getTxTimeMillis()[lvl]);
11442                 }
11443
11444                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11445                 final double opVolt = mPowerProfile.getAveragePower(
11446                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11447                 if (opVolt != 0) {
11448                     double energyUsed =
11449                             deltaInfo.getSleepTimeMillis() *
11450                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
11451                             + deltaInfo.getIdleTimeMillis() *
11452                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
11453                             + deltaInfo.getRxTimeMillis() *
11454                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
11455                     int[] txTimeMs = deltaInfo.getTxTimeMillis();
11456                     for (int i = 0; i < Math.min(txTimeMs.length,
11457                             SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
11458                         energyUsed += txTimeMs[i] * mPowerProfile.getAveragePower(
11459                                 PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
11460                     }
11461
11462                     // We store the power drain as mAms.
11463                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
11464                 }
11465             }
11466
11467             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11468             long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
11469                     elapsedRealtimeMs * 1000);
11470             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
11471
11472             long totalRxPackets = 0;
11473             long totalTxPackets = 0;
11474             if (delta != null) {
11475                 NetworkStats.Entry entry = new NetworkStats.Entry();
11476                 final int size = delta.size();
11477                 for (int i = 0; i < size; i++) {
11478                     entry = delta.getValues(i, entry);
11479                     if (entry.rxPackets == 0 && entry.txPackets == 0) {
11480                         continue;
11481                     }
11482
11483                     if (DEBUG_ENERGY) {
11484                         Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
11485                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11486                                 + " txPackets=" + entry.txPackets);
11487                     }
11488
11489                     totalRxPackets += entry.rxPackets;
11490                     totalTxPackets += entry.txPackets;
11491
11492                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
11493                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
11494                             entry.rxPackets);
11495                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
11496                             entry.txPackets);
11497                     if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11498                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
11499                                 entry.rxBytes, entry.rxPackets);
11500                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
11501                                 entry.txBytes, entry.txPackets);
11502                     }
11503
11504                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11505                             entry.rxBytes);
11506                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11507                             entry.txBytes);
11508                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11509                             entry.rxPackets);
11510                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11511                             entry.txPackets);
11512                 }
11513
11514                 // Now distribute proportional blame to the apps that did networking.
11515                 long totalPackets = totalRxPackets + totalTxPackets;
11516                 if (totalPackets > 0) {
11517                     for (int i = 0; i < size; i++) {
11518                         entry = delta.getValues(i, entry);
11519                         if (entry.rxPackets == 0 && entry.txPackets == 0) {
11520                             continue;
11521                         }
11522
11523                         final Uid u = getUidStatsLocked(mapUid(entry.uid));
11524
11525                         // Distribute total radio active time in to this app.
11526                         final long appPackets = entry.rxPackets + entry.txPackets;
11527                         final long appRadioTime = (radioTime * appPackets) / totalPackets;
11528                         u.noteMobileRadioActiveTimeLocked(appRadioTime);
11529
11530                         // Remove this app from the totals, so that we don't lose any time
11531                         // due to rounding.
11532                         radioTime -= appRadioTime;
11533                         totalPackets -= appPackets;
11534
11535                         if (deltaInfo != null) {
11536                             ControllerActivityCounterImpl activityCounter =
11537                                     u.getOrCreateModemControllerActivityLocked();
11538                             if (totalRxPackets > 0 && entry.rxPackets > 0) {
11539                                 final long rxMs = (entry.rxPackets * deltaInfo.getRxTimeMillis())
11540                                         / totalRxPackets;
11541                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
11542                             }
11543
11544                             if (totalTxPackets > 0 && entry.txPackets > 0) {
11545                                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11546                                     long txMs =
11547                                             entry.txPackets * deltaInfo.getTxTimeMillis()[lvl];
11548                                     txMs /= totalTxPackets;
11549                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
11550                                 }
11551                             }
11552                         }
11553                     }
11554                 }
11555
11556                 if (radioTime > 0) {
11557                     // Whoops, there is some radio time we can't blame on an app!
11558                     mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
11559                     mMobileRadioActiveUnknownCount.addCountLocked(1);
11560                 }
11561
11562                 mNetworkStatsPool.release(delta);
11563                 delta = null;
11564             }
11565         }
11566     }
11567
11568     // Cache last value for comparison.
11569     private BluetoothActivityEnergyInfo mLastBluetoothActivityEnergyInfo =
11570             new BluetoothActivityEnergyInfo(0, 0, 0, 0, 0, 0);
11571
11572     /**
11573      * Add modem tx power to history
11574      * Device is said to be in high cellular transmit power when it has spent most of the transmit
11575      * time at the highest power level.
11576      * @param activityInfo
11577      */
11578     private void addModemTxPowerToHistory(final ModemActivityInfo activityInfo) {
11579         if (activityInfo == null) {
11580             return;
11581         }
11582         int[] txTimeMs = activityInfo.getTxTimeMillis();
11583         if (txTimeMs == null || txTimeMs.length != ModemActivityInfo.TX_POWER_LEVELS) {
11584             return;
11585         }
11586         final long elapsedRealtime = mClocks.elapsedRealtime();
11587         final long uptime = mClocks.uptimeMillis();
11588         int levelMaxTimeSpent = 0;
11589         for (int i = 1; i < txTimeMs.length; i++) {
11590             if (txTimeMs[i] > txTimeMs[levelMaxTimeSpent]) {
11591                 levelMaxTimeSpent = i;
11592             }
11593         }
11594         if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
11595             if (!mIsCellularTxPowerHigh) {
11596                 mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
11597                 addHistoryRecordLocked(elapsedRealtime, uptime);
11598                 mIsCellularTxPowerHigh = true;
11599             }
11600             return;
11601         }
11602         if (mIsCellularTxPowerHigh) {
11603             mHistoryCur.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
11604             addHistoryRecordLocked(elapsedRealtime, uptime);
11605             mIsCellularTxPowerHigh = false;
11606         }
11607         return;
11608     }
11609
11610     /**
11611      * Distribute Bluetooth energy info and network traffic to apps.
11612      * @param info The energy information from the bluetooth controller.
11613      */
11614     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
11615         if (DEBUG_ENERGY) {
11616             Slog.d(TAG, "Updating bluetooth stats: " + info);
11617         }
11618
11619         if (info == null || !mOnBatteryInternal) {
11620             return;
11621         }
11622
11623         mHasBluetoothReporting = true;
11624
11625         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11626         final long rxTimeMs = info.getControllerRxTimeMillis() -
11627                 mLastBluetoothActivityEnergyInfo.getControllerRxTimeMillis();
11628         final long txTimeMs = info.getControllerTxTimeMillis() -
11629                 mLastBluetoothActivityEnergyInfo.getControllerTxTimeMillis();
11630         final long idleTimeMs = info.getControllerIdleTimeMillis() -
11631                 mLastBluetoothActivityEnergyInfo.getControllerIdleTimeMillis();
11632         if (DEBUG_ENERGY) {
11633             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
11634             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11635             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11636             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11637         }
11638
11639         long totalScanTimeMs = 0;
11640
11641         final int uidCount = mUidStats.size();
11642         for (int i = 0; i < uidCount; i++) {
11643             final Uid u = mUidStats.valueAt(i);
11644             if (u.mBluetoothScanTimer == null) {
11645                 continue;
11646             }
11647
11648             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11649                     elapsedRealtimeMs * 1000) / 1000;
11650         }
11651
11652         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
11653         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
11654
11655         if (DEBUG_ENERGY) {
11656             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
11657                     + " TX=" + normalizeScanTxTime);
11658         }
11659
11660         long leftOverRxTimeMs = rxTimeMs;
11661         long leftOverTxTimeMs = txTimeMs;
11662
11663         for (int i = 0; i < uidCount; i++) {
11664             final Uid u = mUidStats.valueAt(i);
11665             if (u.mBluetoothScanTimer == null) {
11666                 continue;
11667             }
11668
11669             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11670                     elapsedRealtimeMs * 1000) / 1000;
11671             if (scanTimeSinceMarkMs > 0) {
11672                 // Set the new mark so that next time we get new data since this point.
11673                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
11674
11675                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
11676                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
11677
11678                 if (normalizeScanRxTime) {
11679                     // Scan time is longer than the total rx time in the controller,
11680                     // so distribute the scan time proportionately. This means regular traffic
11681                     // will not blamed, but scans are more expensive anyways.
11682                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
11683                 }
11684
11685                 if (normalizeScanTxTime) {
11686                     // Scan time is longer than the total tx time in the controller,
11687                     // so distribute the scan time proportionately. This means regular traffic
11688                     // will not blamed, but scans are more expensive anyways.
11689                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
11690                 }
11691
11692                 final ControllerActivityCounterImpl counter =
11693                         u.getOrCreateBluetoothControllerActivityLocked();
11694                 counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
11695                 counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
11696
11697                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
11698                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
11699             }
11700         }
11701
11702         if (DEBUG_ENERGY) {
11703             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs
11704                     + " TX=" + leftOverTxTimeMs);
11705         }
11706
11707         //
11708         // Now distribute blame to apps that did bluetooth traffic.
11709         //
11710
11711         long totalTxBytes = 0;
11712         long totalRxBytes = 0;
11713
11714         final UidTraffic[] uidTraffic = info.getUidTraffic();
11715         final UidTraffic[] lastUidTraffic = mLastBluetoothActivityEnergyInfo.getUidTraffic();
11716         final ArrayList<UidTraffic> deltaTraffic = new ArrayList<>();
11717         int m = 0, n = 0;
11718         for (; m < uidTraffic.length && n < lastUidTraffic.length; m++) {
11719             final UidTraffic traffic = uidTraffic[m];
11720             final UidTraffic lastTraffic = lastUidTraffic[n];
11721             if (traffic.getUid() == lastTraffic.getUid()) {
11722                 deltaTraffic.add(new UidTraffic(traffic.getUid(),
11723                         traffic.getRxBytes() - lastTraffic.getRxBytes(),
11724                         traffic.getTxBytes() - lastTraffic.getTxBytes()));
11725                 n++;
11726             }
11727         }
11728         for (; m < uidTraffic.length; m ++) {
11729             deltaTraffic.add(uidTraffic[m]);
11730         }
11731
11732         for (int i = 0, j = 0; i < deltaTraffic.size(); i++) {
11733             final UidTraffic traffic = deltaTraffic.get(i);
11734
11735             // Add to the global counters.
11736             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(
11737                     traffic.getRxBytes());
11738             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(
11739                     traffic.getTxBytes());
11740
11741             // Add to the UID counters.
11742             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
11743             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, traffic.getRxBytes(), 0);
11744             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, traffic.getTxBytes(), 0);
11745
11746             // Calculate the total traffic.
11747             totalTxBytes += traffic.getTxBytes();
11748             totalRxBytes += traffic.getRxBytes();
11749         }
11750
11751         if ((totalTxBytes != 0 || totalRxBytes != 0) &&
11752                 (leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) {
11753             for (int i = 0; i < deltaTraffic.size(); i++) {
11754                 final UidTraffic traffic = deltaTraffic.get(i);
11755
11756                 final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
11757                 final ControllerActivityCounterImpl counter =
11758                         u.getOrCreateBluetoothControllerActivityLocked();
11759
11760                 if (totalRxBytes > 0 && traffic.getRxBytes() > 0) {
11761                     final long timeRxMs = (leftOverRxTimeMs * traffic.getRxBytes()) / totalRxBytes;
11762
11763                     if (DEBUG_ENERGY) {
11764                         Slog.d(TAG, "UID=" + traffic.getUid() + " rx_bytes=" + traffic.getRxBytes()
11765                                 + " rx_time=" + timeRxMs);
11766                     }
11767                     counter.getRxTimeCounter().addCountLocked(timeRxMs);
11768                     leftOverRxTimeMs -= timeRxMs;
11769                 }
11770
11771                 if (totalTxBytes > 0 && traffic.getTxBytes() > 0) {
11772                     final long timeTxMs = (leftOverTxTimeMs * traffic.getTxBytes()) / totalTxBytes;
11773
11774                     if (DEBUG_ENERGY) {
11775                         Slog.d(TAG, "UID=" + traffic.getUid() + " tx_bytes=" + traffic.getTxBytes()
11776                                 + " tx_time=" + timeTxMs);
11777                     }
11778
11779                     counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
11780                     leftOverTxTimeMs -= timeTxMs;
11781                 }
11782             }
11783         }
11784
11785         mBluetoothActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
11786         mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(txTimeMs);
11787         mBluetoothActivity.getIdleTimeCounter().addCountLocked(idleTimeMs);
11788
11789         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11790         final double opVolt = mPowerProfile.getAveragePower(
11791                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11792         if (opVolt != 0) {
11793             // We store the power drain as mAms.
11794             mBluetoothActivity.getPowerCounter().addCountLocked(
11795                     (long) ((info.getControllerEnergyUsed() -
11796                             mLastBluetoothActivityEnergyInfo.getControllerEnergyUsed() )/ opVolt));
11797         }
11798         mLastBluetoothActivityEnergyInfo = info;
11799     }
11800
11801     /**
11802      * Read and record Resource Power Manager (RPM) state and voter times.
11803      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
11804      * instead of fetching it anew.
11805      */
11806     public void updateRpmStatsLocked() {
11807         if (mPlatformIdleStateCallback == null) return;
11808         long now = SystemClock.elapsedRealtime();
11809         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
11810             mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats);
11811             mLastRpmStatsUpdateTimeMs = now;
11812         }
11813
11814         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
11815                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
11816
11817             // Update values for this platform state.
11818             final String pName = pstate.getKey();
11819             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
11820             final int pCount = pstate.getValue().mCount;
11821             getRpmTimerLocked(pName).update(pTimeUs, pCount);
11822             if (SCREEN_OFF_RPM_STATS_ENABLED) {
11823                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount);
11824             }
11825
11826             // Update values for each voter of this platform state.
11827             for (Map.Entry<String, RpmStats.PowerStateElement> voter
11828                     : pstate.getValue().mVoters.entrySet()) {
11829                 final String vName = pName + "." + voter.getKey();
11830                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
11831                 final int vCount = voter.getValue().mCount;
11832                 getRpmTimerLocked(vName).update(vTimeUs, vCount);
11833                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
11834                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount);
11835                 }
11836             }
11837         }
11838
11839         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
11840                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
11841
11842             final String subsysName = subsys.getKey();
11843             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
11844                     : subsys.getValue().mStates.entrySet()) {
11845                 final String name = subsysName + "." + sstate.getKey();
11846                 final long timeUs = sstate.getValue().mTimeMs * 1000;
11847                 final int count = sstate.getValue().mCount;
11848                 getRpmTimerLocked(name).update(timeUs, count);
11849                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
11850                     getScreenOffRpmTimerLocked(name).update(timeUs, count);
11851                 }
11852             }
11853         }
11854     }
11855
11856     /**
11857      * Read and distribute kernel wake lock use across apps.
11858      */
11859     public void updateKernelWakelocksLocked() {
11860         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
11861                 mTmpWakelockStats);
11862         if (wakelockStats == null) {
11863             // Not crashing might make board bringup easier.
11864             Slog.w(TAG, "Couldn't get kernel wake lock stats");
11865             return;
11866         }
11867
11868         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
11869             String name = ent.getKey();
11870             KernelWakelockStats.Entry kws = ent.getValue();
11871
11872             SamplingTimer kwlt = mKernelWakelockStats.get(name);
11873             if (kwlt == null) {
11874                 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
11875                 mKernelWakelockStats.put(name, kwlt);
11876             }
11877
11878             kwlt.update(kws.mTotalTime, kws.mCount);
11879             kwlt.setUpdateVersion(kws.mVersion);
11880         }
11881
11882         int numWakelocksSetStale = 0;
11883         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
11884         // this time.
11885         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11886             SamplingTimer st = ent.getValue();
11887             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
11888                 st.endSample();
11889                 numWakelocksSetStale++;
11890             }
11891         }
11892
11893         // Record whether we've seen a non-zero time (for debugging b/22716723).
11894         if (wakelockStats.isEmpty()) {
11895             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
11896         }
11897
11898         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
11899             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
11900                     wakelockStats.kernelWakelockVersion);
11901         }
11902     }
11903
11904     // We use an anonymous class to access these variables,
11905     // so they can't live on the stack or they'd have to be
11906     // final MutableLong objects (more allocations).
11907     // Used in updateCpuTimeLocked().
11908     long mTempTotalCpuUserTimeUs;
11909     long mTempTotalCpuSystemTimeUs;
11910     long[][] mWakeLockAllocationsUs;
11911
11912     /**
11913      * Reads the newest memory stats from the kernel.
11914      */
11915     public void updateKernelMemoryBandwidthLocked() {
11916         mKernelMemoryBandwidthStats.updateStats();
11917         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
11918         final int bandwidthEntryCount = bandwidthEntries.size();
11919         int index;
11920         for (int i = 0; i < bandwidthEntryCount; i++) {
11921             SamplingTimer timer;
11922             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
11923                 timer = mKernelMemoryStats.valueAt(index);
11924             } else {
11925                 timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
11926                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
11927             }
11928             timer.update(bandwidthEntries.valueAt(i), 1);
11929             if (DEBUG_MEMORY) {
11930                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
11931                         + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i),
11932                         mKernelMemoryStats.get(
11933                                 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime,
11934                         mKernelMemoryStats.size()));
11935             }
11936         }
11937     }
11938
11939     public boolean isOnBatteryLocked() {
11940         return mOnBatteryTimeBase.isRunning();
11941     }
11942
11943     public boolean isOnBatteryScreenOffLocked() {
11944         return mOnBatteryScreenOffTimeBase.isRunning();
11945     }
11946
11947     /**
11948      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
11949      * and we are on battery with screen off, we give more of the cpu time to those apps holding
11950      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
11951      * It's possible this will be invoked after the internal battery/screen states are updated, so
11952      * passing the appropriate battery/screen states to try attribute the cpu times to correct
11953      * buckets.
11954      */
11955     @GuardedBy("this")
11956     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) {
11957         if (mPowerProfile == null) {
11958             return;
11959         }
11960
11961         if (DEBUG_ENERGY_CPU) {
11962             Slog.d(TAG, "!Cpu updating!");
11963         }
11964
11965         if (mCpuFreqs == null) {
11966             mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
11967         }
11968
11969         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
11970         // usually holding the wakelock on behalf of an app.
11971         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
11972         ArrayList<StopwatchTimer> partialTimersToConsider = null;
11973         if (onBatteryScreenOff) {
11974             partialTimersToConsider = new ArrayList<>();
11975             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11976                 final StopwatchTimer timer = mPartialTimers.get(i);
11977                 // Since the collection and blaming of wakelocks can be scheduled to run after
11978                 // some delay, the mPartialTimers list may have new entries. We can't blame
11979                 // the newly added timer for past cpu time, so we only consider timers that
11980                 // were present for one round of collection. Once a timer has gone through
11981                 // a round of collection, its mInList field is set to true.
11982                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
11983                     partialTimersToConsider.add(timer);
11984                 }
11985             }
11986         }
11987         markPartialTimersAsEligible();
11988
11989         // When the battery is not on, we don't attribute the cpu times to any timers but we still
11990         // need to take the snapshots.
11991         if (!onBattery) {
11992             mKernelUidCpuTimeReader.readDelta(null);
11993             mKernelUidCpuFreqTimeReader.readDelta(null);
11994             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11995                 mKernelUidCpuActiveTimeReader.readDelta(null);
11996                 mKernelUidCpuClusterTimeReader.readDelta(null);
11997             }
11998             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
11999                 mKernelCpuSpeedReaders[cluster].readDelta();
12000             }
12001             return;
12002         }
12003
12004         mUserInfoProvider.refreshUserIds();
12005         final SparseLongArray updatedUids = mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()
12006                 ? null : new SparseLongArray();
12007         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
12008         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
12009         // freqs, so no need to approximate these values.
12010         if (updatedUids != null) {
12011             updateClusterSpeedTimes(updatedUids, onBattery);
12012         }
12013         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff);
12014         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
12015             readKernelUidCpuActiveTimesLocked(onBattery);
12016             readKernelUidCpuClusterTimesLocked(onBattery);
12017         }
12018     }
12019
12020     /**
12021      * Mark the current partial timers as gone through a collection so that they will be
12022      * considered in the next cpu times distribution to wakelock holders.
12023      */
12024     @VisibleForTesting
12025     public void markPartialTimersAsEligible() {
12026         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
12027             // No difference, so each timer is now considered for the next collection.
12028             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
12029                 mPartialTimers.get(i).mInList = true;
12030             }
12031         } else {
12032             // The lists are different, meaning we added (or removed a timer) since the last
12033             // collection.
12034             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
12035                 mLastPartialTimers.get(i).mInList = false;
12036             }
12037             mLastPartialTimers.clear();
12038
12039             // Mark the current timers as gone through a collection.
12040             final int numPartialTimers = mPartialTimers.size();
12041             for (int i = 0; i < numPartialTimers; ++i) {
12042                 final StopwatchTimer timer = mPartialTimers.get(i);
12043                 timer.mInList = true;
12044                 mLastPartialTimers.add(timer);
12045             }
12046         }
12047     }
12048
12049     /**
12050      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
12051      * calculate cpu times spent by each uid at different frequencies.
12052      *
12053      * @param updatedUids The uids for which times spent at different frequencies are calculated.
12054      */
12055     @VisibleForTesting
12056     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) {
12057         long totalCpuClustersTimeMs = 0;
12058         // Read the time spent for each cluster at various cpu frequencies.
12059         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
12060         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
12061             clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
12062             if (clusterSpeedTimesMs[cluster] != null) {
12063                 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
12064                     totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
12065                 }
12066             }
12067         }
12068         if (totalCpuClustersTimeMs != 0) {
12069             // We have cpu times per freq aggregated over all uids but we need the times per uid.
12070             // So, we distribute total time spent by an uid to different cpu freqs based on the
12071             // amount of time cpu was running at that freq.
12072             final int updatedUidsCount = updatedUids.size();
12073             for (int i = 0; i < updatedUidsCount; ++i) {
12074                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
12075                 final long appCpuTimeUs = updatedUids.valueAt(i);
12076                 // Add the cpu speeds to this UID.
12077                 final int numClusters = mPowerProfile.getNumCpuClusters();
12078                 if (u.mCpuClusterSpeedTimesUs == null ||
12079                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
12080                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
12081                 }
12082
12083                 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
12084                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
12085                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
12086                             u.mCpuClusterSpeedTimesUs[cluster].length) {
12087                         u.mCpuClusterSpeedTimesUs[cluster]
12088                                 = new LongSamplingCounter[speedsInCluster];
12089                     }
12090
12091                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
12092                     for (int speed = 0; speed < speedsInCluster; speed++) {
12093                         if (cpuSpeeds[speed] == null) {
12094                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
12095                         }
12096                         cpuSpeeds[speed].addCountLocked(appCpuTimeUs
12097                                 * clusterSpeedTimesMs[cluster][speed]
12098                                 / totalCpuClustersTimeMs, onBattery);
12099                     }
12100                 }
12101             }
12102         }
12103     }
12104
12105     /**
12106      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
12107      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
12108      * wakelock holders.
12109      *
12110      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
12111      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
12112      */
12113     @VisibleForTesting
12114     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
12115             @Nullable SparseLongArray updatedUids, boolean onBattery) {
12116         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
12117         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
12118         final long startTimeMs = mClocks.uptimeMillis();
12119
12120         mKernelUidCpuTimeReader.readDelta((uid, userTimeUs, systemTimeUs) -> {
12121             uid = mapUid(uid);
12122             if (Process.isIsolated(uid)) {
12123                 // This could happen if the isolated uid mapping was removed before that process
12124                 // was actually killed.
12125                 mKernelUidCpuTimeReader.removeUid(uid);
12126                 Slog.d(TAG, "Got readings for an isolated uid with no mapping: " + uid);
12127                 return;
12128             }
12129             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12130                 Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
12131                 mKernelUidCpuTimeReader.removeUid(uid);
12132                 return;
12133             }
12134             final Uid u = getUidStatsLocked(uid);
12135
12136             // Accumulate the total system and user time.
12137             mTempTotalCpuUserTimeUs += userTimeUs;
12138             mTempTotalCpuSystemTimeUs += systemTimeUs;
12139
12140             StringBuilder sb = null;
12141             if (DEBUG_ENERGY_CPU) {
12142                 sb = new StringBuilder();
12143                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
12144                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
12145                 sb.append(" s=");
12146                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
12147                 sb.append("\n");
12148             }
12149
12150             if (numWakelocks > 0) {
12151                 // We have wakelocks being held, so only give a portion of the
12152                 // time to the process. The rest will be distributed among wakelock
12153                 // holders.
12154                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
12155                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
12156             }
12157
12158             if (sb != null) {
12159                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
12160                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
12161                 sb.append(" s=");
12162                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
12163                 Slog.d(TAG, sb.toString());
12164             }
12165
12166             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
12167             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
12168             if (updatedUids != null) {
12169                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
12170             }
12171         });
12172
12173         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12174         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12175             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
12176         }
12177
12178         if (numWakelocks > 0) {
12179             // Distribute a portion of the total cpu time to wakelock holders.
12180             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
12181             mTempTotalCpuSystemTimeUs =
12182                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
12183
12184             for (int i = 0; i < numWakelocks; ++i) {
12185                 final StopwatchTimer timer = partialTimers.get(i);
12186                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
12187                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
12188
12189                 if (DEBUG_ENERGY_CPU) {
12190                     final StringBuilder sb = new StringBuilder();
12191                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
12192                             .append(": u=");
12193                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
12194                     sb.append(" s=");
12195                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
12196                     Slog.d(TAG, sb.toString());
12197                 }
12198
12199                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
12200                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
12201                 if (updatedUids != null) {
12202                     final int uid = timer.mUid.getUid();
12203                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
12204                 }
12205
12206                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
12207                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
12208
12209                 mTempTotalCpuUserTimeUs -= userTimeUs;
12210                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
12211             }
12212         }
12213     }
12214
12215     /**
12216      * Take a snapshot of the cpu times spent by each uid in each freq and update the
12217      * corresponding counters.
12218      *
12219      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
12220      */
12221     @VisibleForTesting
12222     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
12223             boolean onBattery, boolean onBatteryScreenOff) {
12224         final boolean perClusterTimesAvailable =
12225                 mKernelUidCpuFreqTimeReader.perClusterTimesAvailable();
12226         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
12227         final int numClusters = mPowerProfile.getNumCpuClusters();
12228         mWakeLockAllocationsUs = null;
12229         final long startTimeMs = mClocks.uptimeMillis();
12230         mKernelUidCpuFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
12231             uid = mapUid(uid);
12232             if (Process.isIsolated(uid)) {
12233                 mKernelUidCpuFreqTimeReader.removeUid(uid);
12234                 Slog.d(TAG, "Got freq readings for an isolated uid with no mapping: " + uid);
12235                 return;
12236             }
12237             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12238                 Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
12239                 mKernelUidCpuFreqTimeReader.removeUid(uid);
12240                 return;
12241             }
12242             final Uid u = getUidStatsLocked(uid);
12243             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
12244                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
12245             }
12246             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
12247             if (u.mScreenOffCpuFreqTimeMs == null ||
12248                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
12249                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
12250                         mOnBatteryScreenOffTimeBase);
12251             }
12252             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
12253
12254             if (perClusterTimesAvailable) {
12255                 if (u.mCpuClusterSpeedTimesUs == null ||
12256                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
12257                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
12258                 }
12259                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
12260                     mWakeLockAllocationsUs = new long[numClusters][];
12261                 }
12262
12263                 int freqIndex = 0;
12264                 for (int cluster = 0; cluster < numClusters; ++cluster) {
12265                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
12266                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
12267                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
12268                         u.mCpuClusterSpeedTimesUs[cluster]
12269                                 = new LongSamplingCounter[speedsInCluster];
12270                     }
12271                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
12272                         mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
12273                     }
12274                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
12275                     for (int speed = 0; speed < speedsInCluster; ++speed) {
12276                         if (cpuTimesUs[speed] == null) {
12277                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
12278                         }
12279                         final long appAllocationUs;
12280                         if (mWakeLockAllocationsUs != null) {
12281                             appAllocationUs =
12282                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
12283                             mWakeLockAllocationsUs[cluster][speed] +=
12284                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
12285                         } else {
12286                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
12287                         }
12288                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
12289                         freqIndex++;
12290                     }
12291                 }
12292             }
12293         });
12294
12295         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12296         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12297             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
12298         }
12299
12300         if (mWakeLockAllocationsUs != null) {
12301             for (int i = 0; i < numWakelocks; ++i) {
12302                 final Uid u = partialTimers.get(i).mUid;
12303                 if (u.mCpuClusterSpeedTimesUs == null ||
12304                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
12305                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
12306                 }
12307
12308                 for (int cluster = 0; cluster < numClusters; ++cluster) {
12309                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
12310                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
12311                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
12312                         u.mCpuClusterSpeedTimesUs[cluster]
12313                                 = new LongSamplingCounter[speedsInCluster];
12314                     }
12315                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
12316                     for (int speed = 0; speed < speedsInCluster; ++speed) {
12317                         if (cpuTimeUs[speed] == null) {
12318                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
12319                         }
12320                         final long allocationUs =
12321                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
12322                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
12323                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
12324                     }
12325                 }
12326             }
12327         }
12328     }
12329
12330     /**
12331      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
12332      * counters.
12333      */
12334     @VisibleForTesting
12335     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
12336         final long startTimeMs = mClocks.uptimeMillis();
12337         mKernelUidCpuActiveTimeReader.readDelta((uid, cpuActiveTimesUs) -> {
12338             uid = mapUid(uid);
12339             if (Process.isIsolated(uid)) {
12340                 mKernelUidCpuActiveTimeReader.removeUid(uid);
12341                 Slog.w(TAG, "Got active times for an isolated uid with no mapping: " + uid);
12342                 return;
12343             }
12344             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12345                 Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
12346                 mKernelUidCpuActiveTimeReader.removeUid(uid);
12347                 return;
12348             }
12349             final Uid u = getUidStatsLocked(uid);
12350             u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesUs, onBattery);
12351         });
12352
12353         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12354         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12355             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
12356         }
12357     }
12358
12359     /**
12360      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
12361      * counters.
12362      */
12363     @VisibleForTesting
12364     public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
12365         final long startTimeMs = mClocks.uptimeMillis();
12366         mKernelUidCpuClusterTimeReader.readDelta((uid, cpuClusterTimesUs) -> {
12367             uid = mapUid(uid);
12368             if (Process.isIsolated(uid)) {
12369                 mKernelUidCpuClusterTimeReader.removeUid(uid);
12370                 Slog.w(TAG, "Got cluster times for an isolated uid with no mapping: " + uid);
12371                 return;
12372             }
12373             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12374                 Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
12375                 mKernelUidCpuClusterTimeReader.removeUid(uid);
12376                 return;
12377             }
12378             final Uid u = getUidStatsLocked(uid);
12379             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesUs, onBattery);
12380         });
12381
12382         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12383         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12384             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
12385         }
12386     }
12387
12388     boolean setChargingLocked(boolean charging) {
12389         if (mCharging != charging) {
12390             mCharging = charging;
12391             if (charging) {
12392                 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12393             } else {
12394                 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
12395             }
12396             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
12397             return true;
12398         }
12399         return false;
12400     }
12401
12402     @GuardedBy("this")
12403     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
12404             final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
12405         boolean doWrite = false;
12406         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
12407         m.arg1 = onBattery ? 1 : 0;
12408         mHandler.sendMessage(m);
12409
12410         final long uptime = mSecUptime * 1000;
12411         final long realtime = mSecRealtime * 1000;
12412         final int screenState = mScreenState;
12413         if (onBattery) {
12414             // We will reset our status if we are unplugging after the
12415             // battery was last full, or the level is at 100, or
12416             // we have gone through a significant charge (from a very low
12417             // level to a now very high level).
12418             boolean reset = false;
12419             if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
12420                     || level >= 90
12421                     || (mDischargeCurrentLevel < 20 && level >= 80)
12422                     || (getHighDischargeAmountSinceCharge() >= 200
12423                             && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
12424                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
12425                         + " dischargeLevel=" + mDischargeCurrentLevel
12426                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
12427                         + " highAmount=" + getHighDischargeAmountSinceCharge());
12428                 // Before we write, collect a snapshot of the final aggregated
12429                 // stats to be reported in the next checkin.  Only do this if we have
12430                 // a sufficient amount of data to make it interesting.
12431                 if (getLowDischargeAmountSinceCharge() >= 20) {
12432                     final long startTime = SystemClock.uptimeMillis();
12433                     final Parcel parcel = Parcel.obtain();
12434                     writeSummaryToParcel(parcel, true);
12435                     final long initialTime = SystemClock.uptimeMillis() - startTime;
12436                     BackgroundThread.getHandler().post(new Runnable() {
12437                         @Override public void run() {
12438                             synchronized (mCheckinFile) {
12439                                 final long startTime2 = SystemClock.uptimeMillis();
12440                                 FileOutputStream stream = null;
12441                                 try {
12442                                     stream = mCheckinFile.startWrite();
12443                                     stream.write(parcel.marshall());
12444                                     stream.flush();
12445                                     FileUtils.sync(stream);
12446                                     stream.close();
12447                                     mCheckinFile.finishWrite(stream);
12448                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
12449                                             "batterystats-checkin",
12450                                             initialTime + SystemClock.uptimeMillis() - startTime2);
12451                                 } catch (IOException e) {
12452                                     Slog.w("BatteryStats",
12453                                             "Error writing checkin battery statistics", e);
12454                                     mCheckinFile.failWrite(stream);
12455                                 } finally {
12456                                     parcel.recycle();
12457                                 }
12458                             }
12459                         }
12460                     });
12461                 }
12462                 doWrite = true;
12463                 resetAllStatsLocked();
12464                 if (chargeUAh > 0 && level > 0) {
12465                     // Only use the reported coulomb charge value if it is supported and reported.
12466                     mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
12467                 }
12468                 mDischargeStartLevel = level;
12469                 reset = true;
12470                 mDischargeStepTracker.init();
12471             }
12472             if (mCharging) {
12473                 setChargingLocked(false);
12474             }
12475             mLastChargingStateLevel = level;
12476             mOnBattery = mOnBatteryInternal = true;
12477             mLastDischargeStepLevel = level;
12478             mMinDischargeStepLevel = level;
12479             mDischargeStepTracker.clearTime();
12480             mDailyDischargeStepTracker.clearTime();
12481             mInitStepMode = mCurStepMode;
12482             mModStepMode = 0;
12483             pullPendingStateUpdatesLocked();
12484             mHistoryCur.batteryLevel = (byte)level;
12485             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12486             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
12487                     + Integer.toHexString(mHistoryCur.states));
12488             if (reset) {
12489                 mRecordingHistory = true;
12490                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
12491             }
12492             addHistoryRecordLocked(mSecRealtime, mSecUptime);
12493             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
12494             if (isScreenOn(screenState)) {
12495                 mDischargeScreenOnUnplugLevel = level;
12496                 mDischargeScreenDozeUnplugLevel = 0;
12497                 mDischargeScreenOffUnplugLevel = 0;
12498             } else if (isScreenDoze(screenState)) {
12499                 mDischargeScreenOnUnplugLevel = 0;
12500                 mDischargeScreenDozeUnplugLevel = level;
12501                 mDischargeScreenOffUnplugLevel = 0;
12502             } else {
12503                 mDischargeScreenOnUnplugLevel = 0;
12504                 mDischargeScreenDozeUnplugLevel = 0;
12505                 mDischargeScreenOffUnplugLevel = level;
12506             }
12507             mDischargeAmountScreenOn = 0;
12508             mDischargeAmountScreenDoze = 0;
12509             mDischargeAmountScreenOff = 0;
12510             updateTimeBasesLocked(true, screenState, uptime, realtime);
12511         } else {
12512             mLastChargingStateLevel = level;
12513             mOnBattery = mOnBatteryInternal = false;
12514             pullPendingStateUpdatesLocked();
12515             mHistoryCur.batteryLevel = (byte)level;
12516             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12517             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
12518                     + Integer.toHexString(mHistoryCur.states));
12519             addHistoryRecordLocked(mSecRealtime, mSecUptime);
12520             mDischargeCurrentLevel = mDischargePlugLevel = level;
12521             if (level < mDischargeUnplugLevel) {
12522                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
12523                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
12524             }
12525             updateDischargeScreenLevelsLocked(screenState, screenState);
12526             updateTimeBasesLocked(false, screenState, uptime, realtime);
12527             mChargeStepTracker.init();
12528             mLastChargeStepLevel = level;
12529             mMaxChargeStepLevel = level;
12530             mInitStepMode = mCurStepMode;
12531             mModStepMode = 0;
12532         }
12533         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
12534             if (mFile != null) {
12535                 writeAsyncLocked();
12536             }
12537         }
12538     }
12539
12540     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
12541             boolean reset) {
12542         mRecordingHistory = true;
12543         mHistoryCur.currentTime = System.currentTimeMillis();
12544         addHistoryBufferLocked(elapsedRealtimeMs,
12545                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
12546                 mHistoryCur);
12547         mHistoryCur.currentTime = 0;
12548         if (reset) {
12549             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
12550         }
12551     }
12552
12553     private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
12554             final long uptimeMs) {
12555         if (mRecordingHistory) {
12556             mHistoryCur.currentTime = currentTime;
12557             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
12558             mHistoryCur.currentTime = 0;
12559         }
12560     }
12561
12562     private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
12563         if (mRecordingHistory) {
12564             mHistoryCur.currentTime = System.currentTimeMillis();
12565             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
12566             mHistoryCur.currentTime = 0;
12567         }
12568     }
12569
12570     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
12571         if (mExternalSync != null) {
12572             mExternalSync.scheduleSync(reason, updateFlags);
12573         }
12574     }
12575
12576     // This should probably be exposed in the API, though it's not critical
12577     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
12578
12579     @GuardedBy("this")
12580     public void setBatteryStateLocked(final int status, final int health, final int plugType,
12581             final int level, /* not final */ int temp, final int volt, final int chargeUAh,
12582             final int chargeFullUAh) {
12583         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
12584         temp = Math.max(0, temp);
12585
12586         reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
12587                 status, plugType, level, temp);
12588
12589         final boolean onBattery = isOnBattery(plugType, status);
12590         final long uptime = mClocks.uptimeMillis();
12591         final long elapsedRealtime = mClocks.elapsedRealtime();
12592         if (!mHaveBatteryLevel) {
12593             mHaveBatteryLevel = true;
12594             // We start out assuming that the device is plugged in (not
12595             // on battery).  If our first report is now that we are indeed
12596             // plugged in, then twiddle our state to correctly reflect that
12597             // since we won't be going through the full setOnBattery().
12598             if (onBattery == mOnBattery) {
12599                 if (onBattery) {
12600                     mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12601                 } else {
12602                     mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12603                 }
12604             }
12605             // Always start out assuming charging, that will be updated later.
12606             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12607             mHistoryCur.batteryStatus = (byte)status;
12608             mHistoryCur.batteryLevel = (byte)level;
12609             mHistoryCur.batteryChargeUAh = chargeUAh;
12610             mMaxChargeStepLevel = mMinDischargeStepLevel =
12611                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
12612             mLastChargingStateLevel = level;
12613         } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
12614             recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
12615         }
12616         int oldStatus = mHistoryCur.batteryStatus;
12617         if (onBattery) {
12618             mDischargeCurrentLevel = level;
12619             if (!mRecordingHistory) {
12620                 mRecordingHistory = true;
12621                 startRecordingHistory(elapsedRealtime, uptime, true);
12622             }
12623         } else if (level < 96 &&
12624             status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
12625             if (!mRecordingHistory) {
12626                 mRecordingHistory = true;
12627                 startRecordingHistory(elapsedRealtime, uptime, true);
12628             }
12629         }
12630         mCurrentBatteryLevel = level;
12631         if (mDischargePlugLevel < 0) {
12632             mDischargePlugLevel = level;
12633         }
12634
12635         if (onBattery != mOnBattery) {
12636             mHistoryCur.batteryLevel = (byte)level;
12637             mHistoryCur.batteryStatus = (byte)status;
12638             mHistoryCur.batteryHealth = (byte)health;
12639             mHistoryCur.batteryPlugType = (byte)plugType;
12640             mHistoryCur.batteryTemperature = (short)temp;
12641             mHistoryCur.batteryVoltage = (char)volt;
12642             if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12643                 // Only record discharges
12644                 final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12645                 mDischargeCounter.addCountLocked(chargeDiff);
12646                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12647                 if (isScreenDoze(mScreenState)) {
12648                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12649                 }
12650                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12651                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12652                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12653                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12654                 }
12655             }
12656             mHistoryCur.batteryChargeUAh = chargeUAh;
12657             setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
12658         } else {
12659             boolean changed = false;
12660             if (mHistoryCur.batteryLevel != level) {
12661                 mHistoryCur.batteryLevel = (byte)level;
12662                 changed = true;
12663
12664                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
12665                 // which will pull external stats.
12666                 scheduleSyncExternalStatsLocked("battery-level", ExternalStatsSync.UPDATE_ALL);
12667             }
12668             if (mHistoryCur.batteryStatus != status) {
12669                 mHistoryCur.batteryStatus = (byte)status;
12670                 changed = true;
12671             }
12672             if (mHistoryCur.batteryHealth != health) {
12673                 mHistoryCur.batteryHealth = (byte)health;
12674                 changed = true;
12675             }
12676             if (mHistoryCur.batteryPlugType != plugType) {
12677                 mHistoryCur.batteryPlugType = (byte)plugType;
12678                 changed = true;
12679             }
12680             if (temp >= (mHistoryCur.batteryTemperature+10)
12681                     || temp <= (mHistoryCur.batteryTemperature-10)) {
12682                 mHistoryCur.batteryTemperature = (short)temp;
12683                 changed = true;
12684             }
12685             if (volt > (mHistoryCur.batteryVoltage+20)
12686                     || volt < (mHistoryCur.batteryVoltage-20)) {
12687                 mHistoryCur.batteryVoltage = (char)volt;
12688                 changed = true;
12689             }
12690             if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
12691                     || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
12692                 if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12693                     // Only record discharges
12694                     final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12695                     mDischargeCounter.addCountLocked(chargeDiff);
12696                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12697                     if (isScreenDoze(mScreenState)) {
12698                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12699                     }
12700                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12701                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12702                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12703                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12704                     }
12705                 }
12706                 mHistoryCur.batteryChargeUAh = chargeUAh;
12707                 changed = true;
12708             }
12709             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
12710                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
12711                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
12712             if (onBattery) {
12713                 changed |= setChargingLocked(false);
12714                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
12715                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12716                             modeBits, elapsedRealtime);
12717                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12718                             modeBits, elapsedRealtime);
12719                     mLastDischargeStepLevel = level;
12720                     mMinDischargeStepLevel = level;
12721                     mInitStepMode = mCurStepMode;
12722                     mModStepMode = 0;
12723                 }
12724             } else {
12725                 if (level >= 90) {
12726                     // If the battery level is at least 90%, always consider the device to be
12727                     // charging even if it happens to go down a level.
12728                     changed |= setChargingLocked(true);
12729                     mLastChargeStepLevel = level;
12730                 } if (!mCharging) {
12731                     if (mLastChargeStepLevel < level) {
12732                         // We have not reporting that we are charging, but the level has now
12733                         // gone up, so consider the state to be charging.
12734                         changed |= setChargingLocked(true);
12735                         mLastChargeStepLevel = level;
12736                     }
12737                 } else {
12738                     if (mLastChargeStepLevel > level) {
12739                         // We had reported that the device was charging, but here we are with
12740                         // power connected and the level going down.  Looks like the current
12741                         // power supplied isn't enough, so consider the device to now be
12742                         // discharging.
12743                         changed |= setChargingLocked(false);
12744                         mLastChargeStepLevel = level;
12745                     }
12746                 }
12747                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
12748                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12749                             modeBits, elapsedRealtime);
12750                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12751                             modeBits, elapsedRealtime);
12752                     mLastChargeStepLevel = level;
12753                     mMaxChargeStepLevel = level;
12754                     mInitStepMode = mCurStepMode;
12755                     mModStepMode = 0;
12756                 }
12757             }
12758             if (changed) {
12759                 addHistoryRecordLocked(elapsedRealtime, uptime);
12760             }
12761         }
12762         if (!onBattery &&
12763             (status == BatteryManager.BATTERY_STATUS_FULL ||
12764              status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
12765             // We don't record history while we are plugged in and fully charged
12766             // (or when battery is not present).  The next time we are
12767             // unplugged, history will be cleared.
12768             mRecordingHistory = DEBUG;
12769         }
12770
12771         if (mMinLearnedBatteryCapacity == -1) {
12772             mMinLearnedBatteryCapacity = chargeFullUAh;
12773         } else {
12774             Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
12775         }
12776         mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
12777     }
12778
12779     public static boolean isOnBattery(int plugType, int status) {
12780         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
12781     }
12782
12783     // Inform StatsLog of setBatteryState changes.
12784     // If this is the first reporting, pass in recentPast == null.
12785     private void reportChangesToStatsLog(HistoryItem recentPast,
12786             final int status, final int plugType, final int level, final int temp) {
12787
12788         if (recentPast == null || recentPast.batteryStatus != status) {
12789             StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, status);
12790         }
12791         if (recentPast == null || recentPast.batteryPlugType != plugType) {
12792             StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, plugType);
12793         }
12794         if (recentPast == null || recentPast.batteryLevel != level) {
12795             StatsLog.write(StatsLog.BATTERY_LEVEL_CHANGED, level);
12796         }
12797         // Let's just always print the temperature, regardless of whether it changed.
12798         StatsLog.write(StatsLog.DEVICE_TEMPERATURE_REPORTED, temp);
12799     }
12800
12801     public long getAwakeTimeBattery() {
12802         return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
12803     }
12804
12805     public long getAwakeTimePlugged() {
12806         return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
12807     }
12808
12809     @Override
12810     public long computeUptime(long curTime, int which) {
12811         switch (which) {
12812             case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
12813             case STATS_CURRENT: return (curTime-mUptimeStart);
12814             case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
12815         }
12816         return 0;
12817     }
12818
12819     @Override
12820     public long computeRealtime(long curTime, int which) {
12821         switch (which) {
12822             case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
12823             case STATS_CURRENT: return (curTime-mRealtimeStart);
12824             case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
12825         }
12826         return 0;
12827     }
12828
12829     @Override
12830     public long computeBatteryUptime(long curTime, int which) {
12831         return mOnBatteryTimeBase.computeUptime(curTime, which);
12832     }
12833
12834     @Override
12835     public long computeBatteryRealtime(long curTime, int which) {
12836         return mOnBatteryTimeBase.computeRealtime(curTime, which);
12837     }
12838
12839     @Override
12840     public long computeBatteryScreenOffUptime(long curTime, int which) {
12841         return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
12842     }
12843
12844     @Override
12845     public long computeBatteryScreenOffRealtime(long curTime, int which) {
12846         return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
12847     }
12848
12849     private long computeTimePerLevel(long[] steps, int numSteps) {
12850         // For now we'll do a simple average across all steps.
12851         if (numSteps <= 0) {
12852             return -1;
12853         }
12854         long total = 0;
12855         for (int i=0; i<numSteps; i++) {
12856             total += steps[i] & STEP_LEVEL_TIME_MASK;
12857         }
12858         return total / numSteps;
12859         /*
12860         long[] buckets = new long[numSteps];
12861         int numBuckets = 0;
12862         int numToAverage = 4;
12863         int i = 0;
12864         while (i < numSteps) {
12865             long totalTime = 0;
12866             int num = 0;
12867             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
12868                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
12869                 num++;
12870             }
12871             buckets[numBuckets] = totalTime / num;
12872             numBuckets++;
12873             numToAverage *= 2;
12874             i += num;
12875         }
12876         if (numBuckets < 1) {
12877             return -1;
12878         }
12879         long averageTime = buckets[numBuckets-1];
12880         for (i=numBuckets-2; i>=0; i--) {
12881             averageTime = (averageTime + buckets[i]) / 2;
12882         }
12883         return averageTime;
12884         */
12885     }
12886
12887     @Override
12888     public long computeBatteryTimeRemaining(long curTime) {
12889         if (!mOnBattery) {
12890             return -1;
12891         }
12892         /* Simple implementation just looks at the average discharge per level across the
12893            entire sample period.
12894         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
12895         if (discharge < 2) {
12896             return -1;
12897         }
12898         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
12899         if (duration < 1000*1000) {
12900             return -1;
12901         }
12902         long usPerLevel = duration/discharge;
12903         return usPerLevel * mCurrentBatteryLevel;
12904         */
12905         if (mDischargeStepTracker.mNumStepDurations < 1) {
12906             return -1;
12907         }
12908         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
12909         if (msPerLevel <= 0) {
12910             return -1;
12911         }
12912         return (msPerLevel * mCurrentBatteryLevel) * 1000;
12913     }
12914
12915     @Override
12916     public LevelStepTracker getDischargeLevelStepTracker() {
12917         return mDischargeStepTracker;
12918     }
12919
12920     @Override
12921     public LevelStepTracker getDailyDischargeLevelStepTracker() {
12922         return mDailyDischargeStepTracker;
12923     }
12924
12925     @Override
12926     public long computeChargeTimeRemaining(long curTime) {
12927         if (mOnBattery) {
12928             // Not yet working.
12929             return -1;
12930         }
12931         /* Broken
12932         int curLevel = mCurrentBatteryLevel;
12933         int plugLevel = mDischargePlugLevel;
12934         if (plugLevel < 0 || curLevel < (plugLevel+1)) {
12935             return -1;
12936         }
12937         long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
12938         if (duration < 1000*1000) {
12939             return -1;
12940         }
12941         long usPerLevel = duration/(curLevel-plugLevel);
12942         return usPerLevel * (100-curLevel);
12943         */
12944         if (mChargeStepTracker.mNumStepDurations < 1) {
12945             return -1;
12946         }
12947         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
12948         if (msPerLevel <= 0) {
12949             return -1;
12950         }
12951         return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
12952     }
12953
12954     /*@hide */
12955     public CellularBatteryStats getCellularBatteryStats() {
12956         CellularBatteryStats s = new CellularBatteryStats();
12957         final int which = STATS_SINCE_CHARGED;
12958         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12959         final ControllerActivityCounter counter = getModemControllerActivity();
12960         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12961         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12962         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12963         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
12964         for (int i = 0; i < timeInRatMs.length; i++) {
12965            timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
12966         }
12967         long[] timeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
12968         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
12969            timeInRxSignalStrengthLevelMs[i]
12970                = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
12971         }
12972         long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
12973             counter.getTxTimeCounters().length)];
12974         long totalTxTimeMs = 0;
12975         for (int i = 0; i < txTimeMs.length; i++) {
12976             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
12977             totalTxTimeMs += txTimeMs[i];
12978         }
12979         final long totalControllerActivityTimeMs
12980             = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
12981         final long sleepTimeMs
12982             = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + totalTxTimeMs);
12983         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12984         s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
12985         s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
12986         s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
12987         s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
12988         s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
12989         s.setSleepTimeMs(sleepTimeMs);
12990         s.setIdleTimeMs(idleTimeMs);
12991         s.setRxTimeMs(rxTimeMs);
12992         s.setEnergyConsumedMaMs(energyConsumedMaMs);
12993         s.setTimeInRatMs(timeInRatMs);
12994         s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
12995         s.setTxTimeMs(txTimeMs);
12996         return s;
12997     }
12998
12999      /*@hide */
13000      public WifiBatteryStats getWifiBatteryStats() {
13001          WifiBatteryStats s = new WifiBatteryStats();
13002          final int which = STATS_SINCE_CHARGED;
13003          final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
13004          final ControllerActivityCounter counter = getWifiControllerActivity();
13005          final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
13006          final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
13007          final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
13008          final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
13009          final long totalControllerActivityTimeMs
13010              = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
13011          final long sleepTimeMs
13012              = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
13013          final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
13014          long numAppScanRequest = 0;
13015          for (int i = 0; i < mUidStats.size(); i++) {
13016              numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
13017          }
13018          long[] timeInStateMs = new long[NUM_WIFI_STATES];
13019          for (int i=0; i<NUM_WIFI_STATES; i++) {
13020             timeInStateMs[i] = getWifiStateTime(i, rawRealTime, which) / 1000;
13021          }
13022          long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
13023          for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
13024              timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000;
13025          }
13026          long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
13027          for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
13028              timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000;
13029          }
13030          s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
13031          s.setKernelActiveTimeMs(getWifiActiveTime(rawRealTime, which) / 1000);
13032          s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
13033          s.setNumBytesTx(getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
13034          s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
13035          s.setNumBytesRx(getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
13036          s.setSleepTimeMs(sleepTimeMs);
13037          s.setIdleTimeMs(idleTimeMs);
13038          s.setRxTimeMs(rxTimeMs);
13039          s.setTxTimeMs(txTimeMs);
13040          s.setScanTimeMs(scanTimeMs);
13041          s.setEnergyConsumedMaMs(energyConsumedMaMs);
13042          s.setNumAppScanRequest(numAppScanRequest);
13043          s.setTimeInStateMs(timeInStateMs);
13044          s.setTimeInSupplicantStateMs(timeInSupplStateMs);
13045          s.setTimeInRxSignalStrengthLevelMs(timeSignalStrengthTimeMs);
13046          return s;
13047      }
13048
13049     /*@hide */
13050     public GpsBatteryStats getGpsBatteryStats() {
13051         GpsBatteryStats s = new GpsBatteryStats();
13052         final int which = STATS_SINCE_CHARGED;
13053         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
13054         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
13055         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
13056         long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
13057         for (int i=0; i<time.length; i++) {
13058             time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
13059         }
13060         s.setTimeInGpsSignalQualityLevel(time);
13061         return s;
13062     }
13063
13064     @Override
13065     public LevelStepTracker getChargeLevelStepTracker() {
13066         return mChargeStepTracker;
13067     }
13068
13069     @Override
13070     public LevelStepTracker getDailyChargeLevelStepTracker() {
13071         return mDailyChargeStepTracker;
13072     }
13073
13074     @Override
13075     public ArrayList<PackageChange> getDailyPackageChanges() {
13076         return mDailyPackageChanges;
13077     }
13078
13079     protected long getBatteryUptimeLocked() {
13080         return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
13081     }
13082
13083     @Override
13084     public long getBatteryUptime(long curTime) {
13085         return mOnBatteryTimeBase.getUptime(curTime);
13086     }
13087
13088     @Override
13089     public long getBatteryRealtime(long curTime) {
13090         return mOnBatteryTimeBase.getRealtime(curTime);
13091     }
13092
13093     @Override
13094     public int getDischargeStartLevel() {
13095         synchronized(this) {
13096             return getDischargeStartLevelLocked();
13097         }
13098     }
13099
13100     public int getDischargeStartLevelLocked() {
13101             return mDischargeUnplugLevel;
13102     }
13103
13104     @Override
13105     public int getDischargeCurrentLevel() {
13106         synchronized(this) {
13107             return getDischargeCurrentLevelLocked();
13108         }
13109     }
13110
13111     public int getDischargeCurrentLevelLocked() {
13112         return mDischargeCurrentLevel;
13113     }
13114
13115     @Override
13116     public int getLowDischargeAmountSinceCharge() {
13117         synchronized(this) {
13118             int val = mLowDischargeAmountSinceCharge;
13119             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
13120                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
13121             }
13122             return val;
13123         }
13124     }
13125
13126     @Override
13127     public int getHighDischargeAmountSinceCharge() {
13128         synchronized(this) {
13129             int val = mHighDischargeAmountSinceCharge;
13130             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
13131                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
13132             }
13133             return val;
13134         }
13135     }
13136
13137     @Override
13138     public int getDischargeAmount(int which) {
13139         int dischargeAmount = which == STATS_SINCE_CHARGED
13140                 ? getHighDischargeAmountSinceCharge()
13141                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
13142         if (dischargeAmount < 0) {
13143             dischargeAmount = 0;
13144         }
13145         return dischargeAmount;
13146     }
13147
13148     @Override
13149     public int getDischargeAmountScreenOn() {
13150         synchronized(this) {
13151             int val = mDischargeAmountScreenOn;
13152             if (mOnBattery && isScreenOn(mScreenState)
13153                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
13154                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
13155             }
13156             return val;
13157         }
13158     }
13159
13160     @Override
13161     public int getDischargeAmountScreenOnSinceCharge() {
13162         synchronized(this) {
13163             int val = mDischargeAmountScreenOnSinceCharge;
13164             if (mOnBattery && isScreenOn(mScreenState)
13165                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
13166                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
13167             }
13168             return val;
13169         }
13170     }
13171
13172     @Override
13173     public int getDischargeAmountScreenOff() {
13174         synchronized(this) {
13175             int val = mDischargeAmountScreenOff;
13176             if (mOnBattery && isScreenOff(mScreenState)
13177                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
13178                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
13179             }
13180             // For backward compatibility, doze discharge is counted into screen off.
13181             return val + getDischargeAmountScreenDoze();
13182         }
13183     }
13184
13185     @Override
13186     public int getDischargeAmountScreenOffSinceCharge() {
13187         synchronized(this) {
13188             int val = mDischargeAmountScreenOffSinceCharge;
13189             if (mOnBattery && isScreenOff(mScreenState)
13190                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
13191                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
13192             }
13193             // For backward compatibility, doze discharge is counted into screen off.
13194             return val + getDischargeAmountScreenDozeSinceCharge();
13195         }
13196     }
13197
13198     @Override
13199     public int getDischargeAmountScreenDoze() {
13200         synchronized(this) {
13201             int val = mDischargeAmountScreenDoze;
13202             if (mOnBattery && isScreenDoze(mScreenState)
13203                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
13204                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
13205             }
13206             return val;
13207         }
13208     }
13209
13210     @Override
13211     public int getDischargeAmountScreenDozeSinceCharge() {
13212         synchronized(this) {
13213             int val = mDischargeAmountScreenDozeSinceCharge;
13214             if (mOnBattery && isScreenDoze(mScreenState)
13215                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
13216                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
13217             }
13218             return val;
13219         }
13220     }
13221
13222     /**
13223      * Retrieve the statistics object for a particular uid, creating if needed.
13224      */
13225     public Uid getUidStatsLocked(int uid) {
13226         Uid u = mUidStats.get(uid);
13227         if (u == null) {
13228             u = new Uid(this, uid);
13229             mUidStats.put(uid, u);
13230         }
13231         return u;
13232     }
13233
13234     /**
13235      * Retrieve the statistics object for a particular uid. Returns null if the object is not
13236      * available.
13237      */
13238     public Uid getAvailableUidStatsLocked(int uid) {
13239         Uid u = mUidStats.get(uid);
13240         return u;
13241     }
13242
13243     public void onCleanupUserLocked(int userId) {
13244         final int firstUidForUser = UserHandle.getUid(userId, 0);
13245         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
13246         mKernelUidCpuFreqTimeReader.removeUidsInRange(firstUidForUser, lastUidForUser);
13247         mKernelUidCpuTimeReader.removeUidsInRange(firstUidForUser, lastUidForUser);
13248         if (mKernelSingleUidTimeReader != null) {
13249             mKernelSingleUidTimeReader.removeUidsInRange(firstUidForUser, lastUidForUser);
13250         }
13251     }
13252
13253     public void onUserRemovedLocked(int userId) {
13254         final int firstUidForUser = UserHandle.getUid(userId, 0);
13255         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
13256         mUidStats.put(firstUidForUser, null);
13257         mUidStats.put(lastUidForUser, null);
13258         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
13259         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
13260         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
13261     }
13262
13263     /**
13264      * Remove the statistics object for a particular uid.
13265      */
13266     public void removeUidStatsLocked(int uid) {
13267         mKernelUidCpuTimeReader.removeUid(uid);
13268         mKernelUidCpuFreqTimeReader.removeUid(uid);
13269         if (mKernelSingleUidTimeReader != null) {
13270             mKernelSingleUidTimeReader.removeUid(uid);
13271         }
13272         mUidStats.remove(uid);
13273     }
13274
13275     /**
13276      * Retrieve the statistics object for a particular process, creating
13277      * if needed.
13278      */
13279     public Uid.Proc getProcessStatsLocked(int uid, String name) {
13280         uid = mapUid(uid);
13281         Uid u = getUidStatsLocked(uid);
13282         return u.getProcessStatsLocked(name);
13283     }
13284
13285     /**
13286      * Retrieve the statistics object for a particular process, creating
13287      * if needed.
13288      */
13289     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
13290         uid = mapUid(uid);
13291         Uid u = getUidStatsLocked(uid);
13292         return u.getPackageStatsLocked(pkg);
13293     }
13294
13295     /**
13296      * Retrieve the statistics object for a particular service, creating
13297      * if needed.
13298      */
13299     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
13300         uid = mapUid(uid);
13301         Uid u = getUidStatsLocked(uid);
13302         return u.getServiceStatsLocked(pkg, name);
13303     }
13304
13305     public void shutdownLocked() {
13306         recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
13307         writeSyncLocked();
13308         mShuttingDown = true;
13309     }
13310
13311     public boolean trackPerProcStateCpuTimes() {
13312         return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
13313     }
13314
13315     public void systemServicesReady(Context context) {
13316         mConstants.startObserving(context.getContentResolver());
13317     }
13318
13319     @VisibleForTesting
13320     public final class Constants extends ContentObserver {
13321         public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE
13322                 = "track_cpu_times_by_proc_state";
13323         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
13324                 = "track_cpu_active_cluster_time";
13325         public static final String KEY_READ_BINARY_CPU_TIME
13326                 = "read_binary_cpu_time";
13327         public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
13328                 = "proc_state_cpu_times_read_delay_ms";
13329
13330         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = true;
13331         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
13332         private static final boolean DEFAULT_READ_BINARY_CPU_TIME = false;
13333         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
13334
13335         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
13336         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
13337         // Not used right now.
13338         public boolean READ_BINARY_CPU_TIME = DEFAULT_READ_BINARY_CPU_TIME;
13339         public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
13340
13341         private ContentResolver mResolver;
13342         private final KeyValueListParser mParser = new KeyValueListParser(',');
13343
13344         public Constants(Handler handler) {
13345             super(handler);
13346         }
13347
13348         public void startObserving(ContentResolver resolver) {
13349             mResolver = resolver;
13350             mResolver.registerContentObserver(
13351                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
13352                     false /* notifyForDescendants */, this);
13353             updateConstants();
13354         }
13355
13356         @Override
13357         public void onChange(boolean selfChange, Uri uri) {
13358             updateConstants();
13359         }
13360
13361         private void updateConstants() {
13362             synchronized (BatteryStatsImpl.this) {
13363                 try {
13364                     mParser.setString(Settings.Global.getString(mResolver,
13365                             Settings.Global.BATTERY_STATS_CONSTANTS));
13366                 } catch (IllegalArgumentException e) {
13367                     // Failed to parse the settings string, log this and move on
13368                     // with defaults.
13369                     Slog.e(TAG, "Bad batterystats settings", e);
13370                 }
13371
13372                 updateTrackCpuTimesByProcStateLocked(TRACK_CPU_TIMES_BY_PROC_STATE,
13373                         mParser.getBoolean(KEY_TRACK_CPU_TIMES_BY_PROC_STATE,
13374                                 DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE));
13375                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
13376                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
13377                 READ_BINARY_CPU_TIME = mParser.getBoolean(
13378                         KEY_READ_BINARY_CPU_TIME, DEFAULT_READ_BINARY_CPU_TIME);
13379                 updateProcStateCpuTimesReadDelayMs(PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13380                         mParser.getLong(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13381                         DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS));
13382             }
13383         }
13384
13385         private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
13386             TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
13387             if (isEnabled && !wasEnabled) {
13388                 mKernelSingleUidTimeReader.markDataAsStale(true);
13389                 mExternalSync.scheduleCpuSyncDueToSettingChange();
13390
13391                 mNumCpuTimeReads = 0;
13392                 mNumBatchedCpuTimeReads = 0;
13393                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13394             }
13395         }
13396
13397         private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
13398             PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
13399             if (oldDelayMillis != newDelayMillis) {
13400                 mNumCpuTimeReads = 0;
13401                 mNumBatchedCpuTimeReads = 0;
13402                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13403             }
13404         }
13405
13406         public void dumpLocked(PrintWriter pw) {
13407             pw.print(KEY_TRACK_CPU_TIMES_BY_PROC_STATE); pw.print("=");
13408             pw.println(TRACK_CPU_TIMES_BY_PROC_STATE);
13409             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
13410             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
13411             pw.print(KEY_READ_BINARY_CPU_TIME); pw.print("=");
13412             pw.println(READ_BINARY_CPU_TIME);
13413             pw.print(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS); pw.print("=");
13414             pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
13415         }
13416     }
13417
13418     @GuardedBy("this")
13419     public void dumpConstantsLocked(PrintWriter pw) {
13420         mConstants.dumpLocked(pw);
13421     }
13422
13423     Parcel mPendingWrite = null;
13424     final ReentrantLock mWriteLock = new ReentrantLock();
13425
13426     public void writeAsyncLocked() {
13427         writeLocked(false);
13428     }
13429
13430     public void writeSyncLocked() {
13431         writeLocked(true);
13432     }
13433
13434     void writeLocked(boolean sync) {
13435         if (mFile == null) {
13436             Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
13437             return;
13438         }
13439
13440         if (mShuttingDown) {
13441             return;
13442         }
13443
13444         Parcel out = Parcel.obtain();
13445         writeSummaryToParcel(out, true);
13446         mLastWriteTime = mClocks.elapsedRealtime();
13447
13448         if (mPendingWrite != null) {
13449             mPendingWrite.recycle();
13450         }
13451         mPendingWrite = out;
13452
13453         if (sync) {
13454             commitPendingDataToDisk();
13455         } else {
13456             BackgroundThread.getHandler().post(new Runnable() {
13457                 @Override public void run() {
13458                     commitPendingDataToDisk();
13459                 }
13460             });
13461         }
13462     }
13463
13464     public void commitPendingDataToDisk() {
13465         final Parcel next;
13466         synchronized (this) {
13467             next = mPendingWrite;
13468             mPendingWrite = null;
13469             if (next == null) {
13470                 return;
13471             }
13472         }
13473
13474         mWriteLock.lock();
13475         try {
13476             final long startTime = SystemClock.uptimeMillis();
13477             FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
13478             stream.write(next.marshall());
13479             stream.flush();
13480             FileUtils.sync(stream);
13481             stream.close();
13482             mFile.commit();
13483             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
13484                     "batterystats", SystemClock.uptimeMillis() - startTime);
13485         } catch (IOException e) {
13486             Slog.w("BatteryStats", "Error writing battery statistics", e);
13487             mFile.rollback();
13488         } finally {
13489             next.recycle();
13490             mWriteLock.unlock();
13491         }
13492     }
13493
13494     public void readLocked() {
13495         if (mDailyFile != null) {
13496             readDailyStatsLocked();
13497         }
13498
13499         if (mFile == null) {
13500             Slog.w("BatteryStats", "readLocked: no file associated with this instance");
13501             return;
13502         }
13503
13504         mUidStats.clear();
13505
13506         try {
13507             File file = mFile.chooseForRead();
13508             if (!file.exists()) {
13509                 return;
13510             }
13511             FileInputStream stream = new FileInputStream(file);
13512
13513             byte[] raw = BatteryStatsHelper.readFully(stream);
13514             Parcel in = Parcel.obtain();
13515             in.unmarshall(raw, 0, raw.length);
13516             in.setDataPosition(0);
13517             stream.close();
13518
13519             readSummaryFromParcel(in);
13520         } catch(Exception e) {
13521             Slog.e("BatteryStats", "Error reading battery statistics", e);
13522             resetAllStatsLocked();
13523         }
13524
13525         mEndPlatformVersion = Build.ID;
13526
13527         if (mHistoryBuffer.dataPosition() > 0) {
13528             mRecordingHistory = true;
13529             final long elapsedRealtime = mClocks.elapsedRealtime();
13530             final long uptime = mClocks.uptimeMillis();
13531             if (USE_OLD_HISTORY) {
13532                 addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
13533             }
13534             addHistoryBufferLocked(elapsedRealtime, HistoryItem.CMD_START, mHistoryCur);
13535             startRecordingHistory(elapsedRealtime, uptime, false);
13536         }
13537
13538         recordDailyStatsIfNeededLocked(false);
13539     }
13540
13541     public int describeContents() {
13542         return 0;
13543     }
13544
13545     void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
13546         final long historyBaseTime = in.readLong();
13547
13548         mHistoryBuffer.setDataSize(0);
13549         mHistoryBuffer.setDataPosition(0);
13550         mHistoryTagPool.clear();
13551         mNextHistoryTagIdx = 0;
13552         mNumHistoryTagChars = 0;
13553
13554         int numTags = in.readInt();
13555         for (int i=0; i<numTags; i++) {
13556             int idx = in.readInt();
13557             String str = in.readString();
13558             if (str == null) {
13559                 throw new ParcelFormatException("null history tag string");
13560             }
13561             int uid = in.readInt();
13562             HistoryTag tag = new HistoryTag();
13563             tag.string = str;
13564             tag.uid = uid;
13565             tag.poolIdx = idx;
13566             mHistoryTagPool.put(tag, idx);
13567             if (idx >= mNextHistoryTagIdx) {
13568                 mNextHistoryTagIdx = idx+1;
13569             }
13570             mNumHistoryTagChars += tag.string.length() + 1;
13571         }
13572
13573         int bufSize = in.readInt();
13574         int curPos = in.dataPosition();
13575         if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
13576             throw new ParcelFormatException("File corrupt: history data buffer too large " +
13577                     bufSize);
13578         } else if ((bufSize&~3) != bufSize) {
13579             throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
13580                     bufSize);
13581         } else {
13582             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
13583                     + " bytes at " + curPos);
13584             mHistoryBuffer.appendFrom(in, curPos, bufSize);
13585             in.setDataPosition(curPos + bufSize);
13586         }
13587
13588         if (andOldHistory) {
13589             readOldHistory(in);
13590         }
13591
13592         if (DEBUG_HISTORY) {
13593             StringBuilder sb = new StringBuilder(128);
13594             sb.append("****************** OLD mHistoryBaseTime: ");
13595             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13596             Slog.i(TAG, sb.toString());
13597         }
13598         mHistoryBaseTime = historyBaseTime;
13599         if (DEBUG_HISTORY) {
13600             StringBuilder sb = new StringBuilder(128);
13601             sb.append("****************** NEW mHistoryBaseTime: ");
13602             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13603             Slog.i(TAG, sb.toString());
13604         }
13605
13606         // We are just arbitrarily going to insert 1 minute from the sample of
13607         // the last run until samples in this run.
13608         if (mHistoryBaseTime > 0) {
13609             long oldnow = mClocks.elapsedRealtime();
13610             mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
13611             if (DEBUG_HISTORY) {
13612                 StringBuilder sb = new StringBuilder(128);
13613                 sb.append("****************** ADJUSTED mHistoryBaseTime: ");
13614                 TimeUtils.formatDuration(mHistoryBaseTime, sb);
13615                 Slog.i(TAG, sb.toString());
13616             }
13617         }
13618     }
13619
13620     void readOldHistory(Parcel in) {
13621         if (!USE_OLD_HISTORY) {
13622             return;
13623         }
13624         mHistory = mHistoryEnd = mHistoryCache = null;
13625         long time;
13626         while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
13627             HistoryItem rec = new HistoryItem(time, in);
13628             addHistoryRecordLocked(rec);
13629         }
13630     }
13631
13632     void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
13633         if (DEBUG_HISTORY) {
13634             StringBuilder sb = new StringBuilder(128);
13635             sb.append("****************** WRITING mHistoryBaseTime: ");
13636             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13637             sb.append(" mLastHistoryElapsedRealtime: ");
13638             TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
13639             Slog.i(TAG, sb.toString());
13640         }
13641         out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
13642         if (!inclData) {
13643             out.writeInt(0);
13644             out.writeInt(0);
13645             return;
13646         }
13647         out.writeInt(mHistoryTagPool.size());
13648         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
13649             HistoryTag tag = ent.getKey();
13650             out.writeInt(ent.getValue());
13651             out.writeString(tag.string);
13652             out.writeInt(tag.uid);
13653         }
13654         out.writeInt(mHistoryBuffer.dataSize());
13655         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
13656                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
13657         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
13658
13659         if (andOldHistory) {
13660             writeOldHistory(out);
13661         }
13662     }
13663
13664     void writeOldHistory(Parcel out) {
13665         if (!USE_OLD_HISTORY) {
13666             return;
13667         }
13668         HistoryItem rec = mHistory;
13669         while (rec != null) {
13670             if (rec.time >= 0) rec.writeToParcel(out, 0);
13671             rec = rec.next;
13672         }
13673         out.writeLong(-1);
13674     }
13675
13676     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
13677         final int version = in.readInt();
13678         if (version != VERSION) {
13679             Slog.w("BatteryStats", "readFromParcel: version got " + version
13680                 + ", expected " + VERSION + "; erasing old stats");
13681             return;
13682         }
13683
13684         readHistory(in, true);
13685
13686         mStartCount = in.readInt();
13687         mUptime = in.readLong();
13688         mRealtime = in.readLong();
13689         mStartClockTime = in.readLong();
13690         mStartPlatformVersion = in.readString();
13691         mEndPlatformVersion = in.readString();
13692         mOnBatteryTimeBase.readSummaryFromParcel(in);
13693         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
13694         mDischargeUnplugLevel = in.readInt();
13695         mDischargePlugLevel = in.readInt();
13696         mDischargeCurrentLevel = in.readInt();
13697         mCurrentBatteryLevel = in.readInt();
13698         mEstimatedBatteryCapacity = in.readInt();
13699         mMinLearnedBatteryCapacity = in.readInt();
13700         mMaxLearnedBatteryCapacity = in.readInt();
13701         mLowDischargeAmountSinceCharge = in.readInt();
13702         mHighDischargeAmountSinceCharge = in.readInt();
13703         mDischargeAmountScreenOnSinceCharge = in.readInt();
13704         mDischargeAmountScreenOffSinceCharge = in.readInt();
13705         mDischargeAmountScreenDozeSinceCharge = in.readInt();
13706         mDischargeStepTracker.readFromParcel(in);
13707         mChargeStepTracker.readFromParcel(in);
13708         mDailyDischargeStepTracker.readFromParcel(in);
13709         mDailyChargeStepTracker.readFromParcel(in);
13710         mDischargeCounter.readSummaryFromParcelLocked(in);
13711         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
13712         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
13713         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
13714         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
13715         int NPKG = in.readInt();
13716         if (NPKG > 0) {
13717             mDailyPackageChanges = new ArrayList<>(NPKG);
13718             while (NPKG > 0) {
13719                 NPKG--;
13720                 PackageChange pc = new PackageChange();
13721                 pc.mPackageName = in.readString();
13722                 pc.mUpdate = in.readInt() != 0;
13723                 pc.mVersionCode = in.readLong();
13724                 mDailyPackageChanges.add(pc);
13725             }
13726         } else {
13727             mDailyPackageChanges = null;
13728         }
13729         mDailyStartTime = in.readLong();
13730         mNextMinDailyDeadline = in.readLong();
13731         mNextMaxDailyDeadline = in.readLong();
13732
13733         mStartCount++;
13734
13735         mScreenState = Display.STATE_UNKNOWN;
13736         mScreenOnTimer.readSummaryFromParcelLocked(in);
13737         mScreenDozeTimer.readSummaryFromParcelLocked(in);
13738         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
13739             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
13740         }
13741         mInteractive = false;
13742         mInteractiveTimer.readSummaryFromParcelLocked(in);
13743         mPhoneOn = false;
13744         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
13745         mLongestLightIdleTime = in.readLong();
13746         mLongestFullIdleTime = in.readLong();
13747         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
13748         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
13749         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
13750         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
13751         mPhoneOnTimer.readSummaryFromParcelLocked(in);
13752         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
13753             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13754         }
13755         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
13756         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
13757             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
13758         }
13759         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13760             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13761             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13762         }
13763         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13764         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
13765         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
13766         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
13767         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
13768         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
13769         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
13770         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13771         mWifiOn = false;
13772         mWifiOnTimer.readSummaryFromParcelLocked(in);
13773         mGlobalWifiRunning = false;
13774         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
13775         for (int i=0; i<NUM_WIFI_STATES; i++) {
13776             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
13777         }
13778         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
13779             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
13780         }
13781         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
13782             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13783         }
13784         mWifiActiveTimer.readSummaryFromParcelLocked(in);
13785         mWifiActivity.readSummaryFromParcel(in);
13786         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
13787             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
13788         }
13789         mBluetoothActivity.readSummaryFromParcel(in);
13790         mModemActivity.readSummaryFromParcel(in);
13791         mHasWifiReporting = in.readInt() != 0;
13792         mHasBluetoothReporting = in.readInt() != 0;
13793         mHasModemReporting = in.readInt() != 0;
13794
13795         mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
13796         mFlashlightOnNesting = 0;
13797         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
13798         mCameraOnNesting = 0;
13799         mCameraOnTimer.readSummaryFromParcelLocked(in);
13800         mBluetoothScanNesting = 0;
13801         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
13802         mIsCellularTxPowerHigh = false;
13803
13804         int NRPMS = in.readInt();
13805         if (NRPMS > 10000) {
13806             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
13807         }
13808         for (int irpm = 0; irpm < NRPMS; irpm++) {
13809             if (in.readInt() != 0) {
13810                 String rpmName = in.readString();
13811                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13812             }
13813         }
13814         int NSORPMS = in.readInt();
13815         if (NSORPMS > 10000) {
13816             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
13817         }
13818         for (int irpm = 0; irpm < NSORPMS; irpm++) {
13819             if (in.readInt() != 0) {
13820                 String rpmName = in.readString();
13821                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13822             }
13823         }
13824
13825         int NKW = in.readInt();
13826         if (NKW > 10000) {
13827             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
13828         }
13829         for (int ikw = 0; ikw < NKW; ikw++) {
13830             if (in.readInt() != 0) {
13831                 String kwltName = in.readString();
13832                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
13833             }
13834         }
13835
13836         int NWR = in.readInt();
13837         if (NWR > 10000) {
13838             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
13839         }
13840         for (int iwr = 0; iwr < NWR; iwr++) {
13841             if (in.readInt() != 0) {
13842                 String reasonName = in.readString();
13843                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
13844             }
13845         }
13846
13847         int NMS = in.readInt();
13848         for (int ims = 0; ims < NMS; ims++) {
13849             if (in.readInt() != 0) {
13850                 long kmstName = in.readLong();
13851                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
13852             }
13853         }
13854
13855         final int NU = in.readInt();
13856         if (NU > 10000) {
13857             throw new ParcelFormatException("File corrupt: too many uids " + NU);
13858         }
13859         for (int iu = 0; iu < NU; iu++) {
13860             int uid = in.readInt();
13861             Uid u = new Uid(this, uid);
13862             mUidStats.put(uid, u);
13863
13864             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
13865             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
13866
13867             u.mWifiRunning = false;
13868             if (in.readInt() != 0) {
13869                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
13870             }
13871             u.mFullWifiLockOut = false;
13872             if (in.readInt() != 0) {
13873                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
13874             }
13875             u.mWifiScanStarted = false;
13876             if (in.readInt() != 0) {
13877                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
13878             }
13879             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
13880             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
13881                 if (in.readInt() != 0) {
13882                     u.makeWifiBatchedScanBin(i, null);
13883                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
13884                 }
13885             }
13886             u.mWifiMulticastEnabled = false;
13887             if (in.readInt() != 0) {
13888                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
13889             }
13890             if (in.readInt() != 0) {
13891                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13892             }
13893             if (in.readInt() != 0) {
13894                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13895             }
13896             if (in.readInt() != 0) {
13897                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13898             }
13899             if (in.readInt() != 0) {
13900                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13901             }
13902             if (in.readInt() != 0) {
13903                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
13904             }
13905             if (in.readInt() != 0) {
13906                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
13907             }
13908             if (in.readInt() != 0) {
13909                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
13910             }
13911             if (in.readInt() != 0) {
13912                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
13913             }
13914             if (in.readInt() != 0) {
13915                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
13916             }
13917             if (in.readInt() != 0) {
13918                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
13919             }
13920             if (in.readInt() != 0) {
13921                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
13922             }
13923             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
13924             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
13925                 if (in.readInt() != 0) {
13926                     u.makeProcessState(i, null);
13927                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
13928                 }
13929             }
13930             if (in.readInt() != 0) {
13931                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
13932             }
13933
13934             if (in.readInt() != 0) {
13935                 if (u.mUserActivityCounters == null) {
13936                     u.initUserActivityLocked();
13937                 }
13938                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
13939                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
13940                 }
13941             }
13942
13943             if (in.readInt() != 0) {
13944                 if (u.mNetworkByteActivityCounters == null) {
13945                     u.initNetworkActivityLocked();
13946                 }
13947                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13948                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13949                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13950                 }
13951                 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
13952                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
13953             }
13954
13955             u.mUserCpuTime.readSummaryFromParcelLocked(in);
13956             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
13957
13958             if (in.readInt() != 0) {
13959                 final int numClusters = in.readInt();
13960                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
13961                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
13962                 }
13963
13964                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13965                 for (int cluster = 0; cluster < numClusters; cluster++) {
13966                     if (in.readInt() != 0) {
13967                         final int NSB = in.readInt();
13968                         if (mPowerProfile != null &&
13969                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
13970                             throw new ParcelFormatException("File corrupt: too many speed bins " +
13971                                     NSB);
13972                         }
13973
13974                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
13975                         for (int speed = 0; speed < NSB; speed++) {
13976                             if (in.readInt() != 0) {
13977                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
13978                                         mOnBatteryTimeBase);
13979                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
13980                             }
13981                         }
13982                     } else {
13983                         u.mCpuClusterSpeedTimesUs[cluster] = null;
13984                     }
13985                 }
13986             } else {
13987                 u.mCpuClusterSpeedTimesUs = null;
13988             }
13989
13990             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
13991                     in, mOnBatteryTimeBase);
13992             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
13993                     in, mOnBatteryScreenOffTimeBase);
13994
13995             u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
13996             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
13997
13998             int length = in.readInt();
13999             if (length == Uid.NUM_PROCESS_STATE) {
14000                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
14001                 for (int procState = 0; procState < length; ++procState) {
14002                     u.mProcStateTimeMs[procState]
14003                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
14004                                     in, mOnBatteryTimeBase);
14005                 }
14006             } else {
14007                 u.mProcStateTimeMs = null;
14008             }
14009             length = in.readInt();
14010             if (length == Uid.NUM_PROCESS_STATE) {
14011                 u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
14012                 for (int procState = 0; procState < length; ++procState) {
14013                     u.mProcStateScreenOffTimeMs[procState]
14014                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
14015                                     in, mOnBatteryScreenOffTimeBase);
14016                 }
14017             } else {
14018                 u.mProcStateScreenOffTimeMs = null;
14019             }
14020
14021             if (in.readInt() != 0) {
14022                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
14023                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
14024             } else {
14025                 u.mMobileRadioApWakeupCount = null;
14026             }
14027
14028             if (in.readInt() != 0) {
14029                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
14030                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
14031             } else {
14032                 u.mWifiRadioApWakeupCount = null;
14033             }
14034
14035             int NW = in.readInt();
14036             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
14037                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
14038             }
14039             for (int iw = 0; iw < NW; iw++) {
14040                 String wlName = in.readString();
14041                 u.readWakeSummaryFromParcelLocked(wlName, in);
14042             }
14043
14044             int NS = in.readInt();
14045             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
14046                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
14047             }
14048             for (int is = 0; is < NS; is++) {
14049                 String name = in.readString();
14050                 u.readSyncSummaryFromParcelLocked(name, in);
14051             }
14052
14053             int NJ = in.readInt();
14054             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
14055                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
14056             }
14057             for (int ij = 0; ij < NJ; ij++) {
14058                 String name = in.readString();
14059                 u.readJobSummaryFromParcelLocked(name, in);
14060             }
14061
14062             u.readJobCompletionsFromParcelLocked(in);
14063
14064             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
14065             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
14066             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
14067             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
14068                 if (in.readInt() != 0) {
14069                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
14070                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
14071                 }
14072             }
14073
14074             int NP = in.readInt();
14075             if (NP > 1000) {
14076                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
14077             }
14078             for (int is = 0; is < NP; is++) {
14079                 int seNumber = in.readInt();
14080                 if (in.readInt() != 0) {
14081                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
14082                 }
14083             }
14084
14085             NP = in.readInt();
14086             if (NP > 1000) {
14087                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
14088             }
14089             for (int ip = 0; ip < NP; ip++) {
14090                 String procName = in.readString();
14091                 Uid.Proc p = u.getProcessStatsLocked(procName);
14092                 p.mUserTime = p.mLoadedUserTime = in.readLong();
14093                 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
14094                 p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
14095                 p.mStarts = p.mLoadedStarts = in.readInt();
14096                 p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
14097                 p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
14098                 p.readExcessivePowerFromParcelLocked(in);
14099             }
14100
14101             NP = in.readInt();
14102             if (NP > 10000) {
14103                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
14104             }
14105             for (int ip = 0; ip < NP; ip++) {
14106                 String pkgName = in.readString();
14107                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
14108                 final int NWA = in.readInt();
14109                 if (NWA > 1000) {
14110                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
14111                 }
14112                 p.mWakeupAlarms.clear();
14113                 for (int iwa=0; iwa<NWA; iwa++) {
14114                     String tag = in.readString();
14115                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
14116                     c.readSummaryFromParcelLocked(in);
14117                     p.mWakeupAlarms.put(tag, c);
14118                 }
14119                 NS = in.readInt();
14120                 if (NS > 1000) {
14121                     throw new ParcelFormatException("File corrupt: too many services " + NS);
14122                 }
14123                 for (int is = 0; is < NS; is++) {
14124                     String servName = in.readString();
14125                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
14126                     s.mStartTime = s.mLoadedStartTime = in.readLong();
14127                     s.mStarts = s.mLoadedStarts = in.readInt();
14128                     s.mLaunches = s.mLoadedLaunches = in.readInt();
14129                 }
14130             }
14131         }
14132     }
14133
14134     /**
14135      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
14136      * disk.  This format does not allow a lossless round-trip.
14137      *
14138      * @param out the Parcel to be written to.
14139      */
14140     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
14141         pullPendingStateUpdatesLocked();
14142
14143         // Pull the clock time.  This may update the time and make a new history entry
14144         // if we had originally pulled a time before the RTC was set.
14145         long startClockTime = getStartClockTime();
14146
14147         final long NOW_SYS = mClocks.uptimeMillis() * 1000;
14148         final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
14149
14150         out.writeInt(VERSION);
14151
14152         writeHistory(out, inclHistory, true);
14153
14154         out.writeInt(mStartCount);
14155         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
14156         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
14157         out.writeLong(startClockTime);
14158         out.writeString(mStartPlatformVersion);
14159         out.writeString(mEndPlatformVersion);
14160         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14161         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14162         out.writeInt(mDischargeUnplugLevel);
14163         out.writeInt(mDischargePlugLevel);
14164         out.writeInt(mDischargeCurrentLevel);
14165         out.writeInt(mCurrentBatteryLevel);
14166         out.writeInt(mEstimatedBatteryCapacity);
14167         out.writeInt(mMinLearnedBatteryCapacity);
14168         out.writeInt(mMaxLearnedBatteryCapacity);
14169         out.writeInt(getLowDischargeAmountSinceCharge());
14170         out.writeInt(getHighDischargeAmountSinceCharge());
14171         out.writeInt(getDischargeAmountScreenOnSinceCharge());
14172         out.writeInt(getDischargeAmountScreenOffSinceCharge());
14173         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
14174         mDischargeStepTracker.writeToParcel(out);
14175         mChargeStepTracker.writeToParcel(out);
14176         mDailyDischargeStepTracker.writeToParcel(out);
14177         mDailyChargeStepTracker.writeToParcel(out);
14178         mDischargeCounter.writeSummaryFromParcelLocked(out);
14179         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
14180         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
14181         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
14182         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
14183         if (mDailyPackageChanges != null) {
14184             final int NPKG = mDailyPackageChanges.size();
14185             out.writeInt(NPKG);
14186             for (int i=0; i<NPKG; i++) {
14187                 PackageChange pc = mDailyPackageChanges.get(i);
14188                 out.writeString(pc.mPackageName);
14189                 out.writeInt(pc.mUpdate ? 1 : 0);
14190                 out.writeLong(pc.mVersionCode);
14191             }
14192         } else {
14193             out.writeInt(0);
14194         }
14195         out.writeLong(mDailyStartTime);
14196         out.writeLong(mNextMinDailyDeadline);
14197         out.writeLong(mNextMaxDailyDeadline);
14198
14199         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14200         mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14201         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14202             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14203         }
14204         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14205         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14206         out.writeLong(mLongestLightIdleTime);
14207         out.writeLong(mLongestFullIdleTime);
14208         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14209         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14210         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14211         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14212         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14213         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14214             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14215         }
14216         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14217         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14218             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14219         }
14220         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14221             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14222             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14223         }
14224         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14225         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14226         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
14227         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
14228         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
14229         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14230         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14231         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14232         for (int i=0; i<NUM_WIFI_STATES; i++) {
14233             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14234         }
14235         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14236             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14237         }
14238         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14239             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14240         }
14241         mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14242         mWifiActivity.writeSummaryToParcel(out);
14243         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14244             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14245         }
14246         mBluetoothActivity.writeSummaryToParcel(out);
14247         mModemActivity.writeSummaryToParcel(out);
14248         out.writeInt(mHasWifiReporting ? 1 : 0);
14249         out.writeInt(mHasBluetoothReporting ? 1 : 0);
14250         out.writeInt(mHasModemReporting ? 1 : 0);
14251
14252         out.writeInt(mNumConnectivityChange);
14253         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14254         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14255         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14256
14257         out.writeInt(mRpmStats.size());
14258         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
14259             Timer rpmt = ent.getValue();
14260             if (rpmt != null) {
14261                 out.writeInt(1);
14262                 out.writeString(ent.getKey());
14263                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14264             } else {
14265                 out.writeInt(0);
14266             }
14267         }
14268         out.writeInt(mScreenOffRpmStats.size());
14269         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
14270             Timer rpmt = ent.getValue();
14271             if (rpmt != null) {
14272                 out.writeInt(1);
14273                 out.writeString(ent.getKey());
14274                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14275             } else {
14276                 out.writeInt(0);
14277             }
14278         }
14279
14280         out.writeInt(mKernelWakelockStats.size());
14281         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14282             Timer kwlt = ent.getValue();
14283             if (kwlt != null) {
14284                 out.writeInt(1);
14285                 out.writeString(ent.getKey());
14286                 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14287             } else {
14288                 out.writeInt(0);
14289             }
14290         }
14291
14292         out.writeInt(mWakeupReasonStats.size());
14293         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
14294             SamplingTimer timer = ent.getValue();
14295             if (timer != null) {
14296                 out.writeInt(1);
14297                 out.writeString(ent.getKey());
14298                 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14299             } else {
14300                 out.writeInt(0);
14301             }
14302         }
14303
14304         out.writeInt(mKernelMemoryStats.size());
14305         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
14306             Timer kmt = mKernelMemoryStats.valueAt(i);
14307             if (kmt != null) {
14308                 out.writeInt(1);
14309                 out.writeLong(mKernelMemoryStats.keyAt(i));
14310                 kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14311             } else {
14312                 out.writeInt(0);
14313             }
14314         }
14315
14316         final int NU = mUidStats.size();
14317         out.writeInt(NU);
14318         for (int iu = 0; iu < NU; iu++) {
14319             out.writeInt(mUidStats.keyAt(iu));
14320             Uid u = mUidStats.valueAt(iu);
14321
14322             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14323             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14324
14325             if (u.mWifiRunningTimer != null) {
14326                 out.writeInt(1);
14327                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14328             } else {
14329                 out.writeInt(0);
14330             }
14331             if (u.mFullWifiLockTimer != null) {
14332                 out.writeInt(1);
14333                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14334             } else {
14335                 out.writeInt(0);
14336             }
14337             if (u.mWifiScanTimer != null) {
14338                 out.writeInt(1);
14339                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14340             } else {
14341                 out.writeInt(0);
14342             }
14343             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
14344                 if (u.mWifiBatchedScanTimer[i] != null) {
14345                     out.writeInt(1);
14346                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14347                 } else {
14348                     out.writeInt(0);
14349                 }
14350             }
14351             if (u.mWifiMulticastTimer != null) {
14352                 out.writeInt(1);
14353                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14354             } else {
14355                 out.writeInt(0);
14356             }
14357             if (u.mAudioTurnedOnTimer != null) {
14358                 out.writeInt(1);
14359                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14360             } else {
14361                 out.writeInt(0);
14362             }
14363             if (u.mVideoTurnedOnTimer != null) {
14364                 out.writeInt(1);
14365                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14366             } else {
14367                 out.writeInt(0);
14368             }
14369             if (u.mFlashlightTurnedOnTimer != null) {
14370                 out.writeInt(1);
14371                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14372             } else {
14373                 out.writeInt(0);
14374             }
14375             if (u.mCameraTurnedOnTimer != null) {
14376                 out.writeInt(1);
14377                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14378             } else {
14379                 out.writeInt(0);
14380             }
14381             if (u.mForegroundActivityTimer != null) {
14382                 out.writeInt(1);
14383                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14384             } else {
14385                 out.writeInt(0);
14386             }
14387             if (u.mForegroundServiceTimer != null) {
14388                 out.writeInt(1);
14389                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14390             } else {
14391                 out.writeInt(0);
14392             }
14393             if (u.mAggregatedPartialWakelockTimer != null) {
14394                 out.writeInt(1);
14395                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14396             } else {
14397                 out.writeInt(0);
14398             }
14399             if (u.mBluetoothScanTimer != null) {
14400                 out.writeInt(1);
14401                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14402             } else {
14403                 out.writeInt(0);
14404             }
14405             if (u.mBluetoothUnoptimizedScanTimer != null) {
14406                 out.writeInt(1);
14407                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14408             } else {
14409                 out.writeInt(0);
14410             }
14411             if (u.mBluetoothScanResultCounter != null) {
14412                 out.writeInt(1);
14413                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
14414             } else {
14415                 out.writeInt(0);
14416             }
14417             if (u.mBluetoothScanResultBgCounter != null) {
14418                 out.writeInt(1);
14419                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
14420             } else {
14421                 out.writeInt(0);
14422             }
14423             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
14424                 if (u.mProcessStateTimer[i] != null) {
14425                     out.writeInt(1);
14426                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14427                 } else {
14428                     out.writeInt(0);
14429                 }
14430             }
14431             if (u.mVibratorOnTimer != null) {
14432                 out.writeInt(1);
14433                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14434             } else {
14435                 out.writeInt(0);
14436             }
14437
14438             if (u.mUserActivityCounters == null) {
14439                 out.writeInt(0);
14440             } else {
14441                 out.writeInt(1);
14442                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
14443                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
14444                 }
14445             }
14446
14447             if (u.mNetworkByteActivityCounters == null) {
14448                 out.writeInt(0);
14449             } else {
14450                 out.writeInt(1);
14451                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14452                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14453                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14454                 }
14455                 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
14456                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
14457             }
14458
14459             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
14460             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
14461
14462             if (u.mCpuClusterSpeedTimesUs != null) {
14463                 out.writeInt(1);
14464                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
14465                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
14466                     if (cpuSpeeds != null) {
14467                         out.writeInt(1);
14468                         out.writeInt(cpuSpeeds.length);
14469                         for (LongSamplingCounter c : cpuSpeeds) {
14470                             if (c != null) {
14471                                 out.writeInt(1);
14472                                 c.writeSummaryFromParcelLocked(out);
14473                             } else {
14474                                 out.writeInt(0);
14475                             }
14476                         }
14477                     } else {
14478                         out.writeInt(0);
14479                     }
14480                 }
14481             } else {
14482                 out.writeInt(0);
14483             }
14484
14485             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
14486             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
14487
14488             u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
14489             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
14490
14491             if (u.mProcStateTimeMs != null) {
14492                 out.writeInt(u.mProcStateTimeMs.length);
14493                 for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
14494                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14495                 }
14496             } else {
14497                 out.writeInt(0);
14498             }
14499             if (u.mProcStateScreenOffTimeMs != null) {
14500                 out.writeInt(u.mProcStateScreenOffTimeMs.length);
14501                 for (LongSamplingCounterArray counters : u.mProcStateScreenOffTimeMs) {
14502                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14503                 }
14504             } else {
14505                 out.writeInt(0);
14506             }
14507
14508             if (u.mMobileRadioApWakeupCount != null) {
14509                 out.writeInt(1);
14510                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14511             } else {
14512                 out.writeInt(0);
14513             }
14514
14515             if (u.mWifiRadioApWakeupCount != null) {
14516                 out.writeInt(1);
14517                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14518             } else {
14519                 out.writeInt(0);
14520             }
14521
14522             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
14523             int NW = wakeStats.size();
14524             out.writeInt(NW);
14525             for (int iw=0; iw<NW; iw++) {
14526                 out.writeString(wakeStats.keyAt(iw));
14527                 Uid.Wakelock wl = wakeStats.valueAt(iw);
14528                 if (wl.mTimerFull != null) {
14529                     out.writeInt(1);
14530                     wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14531                 } else {
14532                     out.writeInt(0);
14533                 }
14534                 if (wl.mTimerPartial != null) {
14535                     out.writeInt(1);
14536                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14537                 } else {
14538                     out.writeInt(0);
14539                 }
14540                 if (wl.mTimerWindow != null) {
14541                     out.writeInt(1);
14542                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14543                 } else {
14544                     out.writeInt(0);
14545                 }
14546                 if (wl.mTimerDraw != null) {
14547                     out.writeInt(1);
14548                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14549                 } else {
14550                     out.writeInt(0);
14551                 }
14552             }
14553
14554             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
14555             int NS = syncStats.size();
14556             out.writeInt(NS);
14557             for (int is=0; is<NS; is++) {
14558                 out.writeString(syncStats.keyAt(is));
14559                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14560             }
14561
14562             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
14563             int NJ = jobStats.size();
14564             out.writeInt(NJ);
14565             for (int ij=0; ij<NJ; ij++) {
14566                 out.writeString(jobStats.keyAt(ij));
14567                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14568             }
14569
14570             u.writeJobCompletionsToParcelLocked(out);
14571
14572             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
14573             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
14574             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
14575             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
14576                 if (u.mJobsFreshnessBuckets[i] != null) {
14577                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
14578                 } else {
14579                     out.writeInt(0);
14580                 }
14581             }
14582
14583             int NSE = u.mSensorStats.size();
14584             out.writeInt(NSE);
14585             for (int ise=0; ise<NSE; ise++) {
14586                 out.writeInt(u.mSensorStats.keyAt(ise));
14587                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
14588                 if (se.mTimer != null) {
14589                     out.writeInt(1);
14590                     se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14591                 } else {
14592                     out.writeInt(0);
14593                 }
14594             }
14595
14596             int NP = u.mProcessStats.size();
14597             out.writeInt(NP);
14598             for (int ip=0; ip<NP; ip++) {
14599                 out.writeString(u.mProcessStats.keyAt(ip));
14600                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
14601                 out.writeLong(ps.mUserTime);
14602                 out.writeLong(ps.mSystemTime);
14603                 out.writeLong(ps.mForegroundTime);
14604                 out.writeInt(ps.mStarts);
14605                 out.writeInt(ps.mNumCrashes);
14606                 out.writeInt(ps.mNumAnrs);
14607                 ps.writeExcessivePowerToParcelLocked(out);
14608             }
14609
14610             NP = u.mPackageStats.size();
14611             out.writeInt(NP);
14612             if (NP > 0) {
14613                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
14614                     : u.mPackageStats.entrySet()) {
14615                     out.writeString(ent.getKey());
14616                     Uid.Pkg ps = ent.getValue();
14617                     final int NWA = ps.mWakeupAlarms.size();
14618                     out.writeInt(NWA);
14619                     for (int iwa=0; iwa<NWA; iwa++) {
14620                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
14621                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
14622                     }
14623                     NS = ps.mServiceStats.size();
14624                     out.writeInt(NS);
14625                     for (int is=0; is<NS; is++) {
14626                         out.writeString(ps.mServiceStats.keyAt(is));
14627                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
14628                         long time = ss.getStartTimeToNowLocked(
14629                                 mOnBatteryTimeBase.getUptime(NOW_SYS));
14630                         out.writeLong(time);
14631                         out.writeInt(ss.mStarts);
14632                         out.writeInt(ss.mLaunches);
14633                     }
14634                 }
14635             }
14636         }
14637     }
14638
14639     public void readFromParcel(Parcel in) {
14640         readFromParcelLocked(in);
14641     }
14642
14643     void readFromParcelLocked(Parcel in) {
14644         int magic = in.readInt();
14645         if (magic != MAGIC) {
14646             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
14647         }
14648
14649         readHistory(in, false);
14650
14651         mStartCount = in.readInt();
14652         mStartClockTime = in.readLong();
14653         mStartPlatformVersion = in.readString();
14654         mEndPlatformVersion = in.readString();
14655         mUptime = in.readLong();
14656         mUptimeStart = in.readLong();
14657         mRealtime = in.readLong();
14658         mRealtimeStart = in.readLong();
14659         mOnBattery = in.readInt() != 0;
14660         mEstimatedBatteryCapacity = in.readInt();
14661         mMinLearnedBatteryCapacity = in.readInt();
14662         mMaxLearnedBatteryCapacity = in.readInt();
14663         mOnBatteryInternal = false; // we are no longer really running.
14664         mOnBatteryTimeBase.readFromParcel(in);
14665         mOnBatteryScreenOffTimeBase.readFromParcel(in);
14666
14667         mScreenState = Display.STATE_UNKNOWN;
14668         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14669         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14670         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14671             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
14672                     mOnBatteryTimeBase, in);
14673         }
14674         mInteractive = false;
14675         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
14676         mPhoneOn = false;
14677         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
14678                 mOnBatteryTimeBase, in);
14679         mLongestLightIdleTime = in.readLong();
14680         mLongestFullIdleTime = in.readLong();
14681         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
14682                 mOnBatteryTimeBase, in);
14683         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
14684                 mOnBatteryTimeBase, in);
14685         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
14686                 mOnBatteryTimeBase, in);
14687         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
14688         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
14689         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14690             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
14691                     null, mOnBatteryTimeBase, in);
14692         }
14693         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
14694                 mOnBatteryTimeBase, in);
14695         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14696             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
14697                     null, mOnBatteryTimeBase, in);
14698         }
14699         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14700             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14701             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14702         }
14703         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14704         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
14705                 mOnBatteryTimeBase, in);
14706         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
14707                 mOnBatteryTimeBase, in);
14708         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14709         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14710         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
14711         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null, -4, null,
14712                 mOnBatteryTimeBase, in);
14713         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14714         mWifiOn = false;
14715         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
14716         mGlobalWifiRunning = false;
14717         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
14718                 mOnBatteryTimeBase, in);
14719         for (int i=0; i<NUM_WIFI_STATES; i++) {
14720             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
14721                     null, mOnBatteryTimeBase, in);
14722         }
14723         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14724             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
14725                     null, mOnBatteryTimeBase, in);
14726         }
14727         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14728             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
14729                     null, mOnBatteryTimeBase, in);
14730         }
14731         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null,
14732             mOnBatteryTimeBase, in);
14733         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14734                 NUM_WIFI_TX_LEVELS, in);
14735         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14736             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
14737                 null, mOnBatteryTimeBase, in);
14738         }
14739         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14740                 NUM_BT_TX_LEVELS, in);
14741         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14742                 ModemActivityInfo.TX_POWER_LEVELS, in);
14743         mHasWifiReporting = in.readInt() != 0;
14744         mHasBluetoothReporting = in.readInt() != 0;
14745         mHasModemReporting = in.readInt() != 0;
14746
14747         mNumConnectivityChange = in.readInt();
14748         mLoadedNumConnectivityChange = in.readInt();
14749         mUnpluggedNumConnectivityChange = in.readInt();
14750         mAudioOnNesting = 0;
14751         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
14752         mVideoOnNesting = 0;
14753         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
14754         mFlashlightOnNesting = 0;
14755         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
14756         mCameraOnNesting = 0;
14757         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
14758         mBluetoothScanNesting = 0;
14759         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
14760         mIsCellularTxPowerHigh = false;
14761         mDischargeUnplugLevel = in.readInt();
14762         mDischargePlugLevel = in.readInt();
14763         mDischargeCurrentLevel = in.readInt();
14764         mCurrentBatteryLevel = in.readInt();
14765         mLowDischargeAmountSinceCharge = in.readInt();
14766         mHighDischargeAmountSinceCharge = in.readInt();
14767         mDischargeAmountScreenOn = in.readInt();
14768         mDischargeAmountScreenOnSinceCharge = in.readInt();
14769         mDischargeAmountScreenOff = in.readInt();
14770         mDischargeAmountScreenOffSinceCharge = in.readInt();
14771         mDischargeAmountScreenDoze = in.readInt();
14772         mDischargeAmountScreenDozeSinceCharge = in.readInt();
14773         mDischargeStepTracker.readFromParcel(in);
14774         mChargeStepTracker.readFromParcel(in);
14775         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14776         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
14777         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14778         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14779         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14780         mLastWriteTime = in.readLong();
14781
14782         mRpmStats.clear();
14783         int NRPMS = in.readInt();
14784         for (int irpm = 0; irpm < NRPMS; irpm++) {
14785             if (in.readInt() != 0) {
14786                 String rpmName = in.readString();
14787                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14788                 mRpmStats.put(rpmName, rpmt);
14789             }
14790         }
14791         mScreenOffRpmStats.clear();
14792         int NSORPMS = in.readInt();
14793         for (int irpm = 0; irpm < NSORPMS; irpm++) {
14794             if (in.readInt() != 0) {
14795                 String rpmName = in.readString();
14796                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14797                 mScreenOffRpmStats.put(rpmName, rpmt);
14798             }
14799         }
14800
14801         mKernelWakelockStats.clear();
14802         int NKW = in.readInt();
14803         for (int ikw = 0; ikw < NKW; ikw++) {
14804             if (in.readInt() != 0) {
14805                 String wakelockName = in.readString();
14806                 SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14807                 mKernelWakelockStats.put(wakelockName, kwlt);
14808             }
14809         }
14810
14811         mWakeupReasonStats.clear();
14812         int NWR = in.readInt();
14813         for (int iwr = 0; iwr < NWR; iwr++) {
14814             if (in.readInt() != 0) {
14815                 String reasonName = in.readString();
14816                 SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14817                 mWakeupReasonStats.put(reasonName, timer);
14818             }
14819         }
14820
14821         mKernelMemoryStats.clear();
14822         int nmt = in.readInt();
14823         for (int imt = 0; imt < nmt; imt++) {
14824             if (in.readInt() != 0) {
14825                 Long bucket = in.readLong();
14826                 SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14827                 mKernelMemoryStats.put(bucket, kmt);
14828             }
14829         }
14830
14831         mPartialTimers.clear();
14832         mFullTimers.clear();
14833         mWindowTimers.clear();
14834         mWifiRunningTimers.clear();
14835         mFullWifiLockTimers.clear();
14836         mWifiScanTimers.clear();
14837         mWifiBatchedScanTimers.clear();
14838         mWifiMulticastTimers.clear();
14839         mAudioTurnedOnTimers.clear();
14840         mVideoTurnedOnTimers.clear();
14841         mFlashlightTurnedOnTimers.clear();
14842         mCameraTurnedOnTimers.clear();
14843
14844         int numUids = in.readInt();
14845         mUidStats.clear();
14846         for (int i = 0; i < numUids; i++) {
14847             int uid = in.readInt();
14848             Uid u = new Uid(this, uid);
14849             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
14850             mUidStats.append(uid, u);
14851         }
14852     }
14853
14854     public void writeToParcel(Parcel out, int flags) {
14855         writeToParcelLocked(out, true, flags);
14856     }
14857
14858     public void writeToParcelWithoutUids(Parcel out, int flags) {
14859         writeToParcelLocked(out, false, flags);
14860     }
14861
14862     @SuppressWarnings("unused")
14863     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
14864         // Need to update with current kernel wake lock counts.
14865         pullPendingStateUpdatesLocked();
14866
14867         // Pull the clock time.  This may update the time and make a new history entry
14868         // if we had originally pulled a time before the RTC was set.
14869         long startClockTime = getStartClockTime();
14870
14871         final long uSecUptime = mClocks.uptimeMillis() * 1000;
14872         final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
14873         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
14874         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
14875
14876         out.writeInt(MAGIC);
14877
14878         writeHistory(out, true, false);
14879
14880         out.writeInt(mStartCount);
14881         out.writeLong(startClockTime);
14882         out.writeString(mStartPlatformVersion);
14883         out.writeString(mEndPlatformVersion);
14884         out.writeLong(mUptime);
14885         out.writeLong(mUptimeStart);
14886         out.writeLong(mRealtime);
14887         out.writeLong(mRealtimeStart);
14888         out.writeInt(mOnBattery ? 1 : 0);
14889         out.writeInt(mEstimatedBatteryCapacity);
14890         out.writeInt(mMinLearnedBatteryCapacity);
14891         out.writeInt(mMaxLearnedBatteryCapacity);
14892         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14893         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14894
14895         mScreenOnTimer.writeToParcel(out, uSecRealtime);
14896         mScreenDozeTimer.writeToParcel(out, uSecRealtime);
14897         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14898             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
14899         }
14900         mInteractiveTimer.writeToParcel(out, uSecRealtime);
14901         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
14902         out.writeLong(mLongestLightIdleTime);
14903         out.writeLong(mLongestFullIdleTime);
14904         mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
14905         mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
14906         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
14907         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
14908         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
14909         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14910             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14911         }
14912         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
14913         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14914             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
14915         }
14916         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14917             mNetworkByteActivityCounters[i].writeToParcel(out);
14918             mNetworkPacketActivityCounters[i].writeToParcel(out);
14919         }
14920         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
14921         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
14922         mMobileRadioActiveAdjustedTime.writeToParcel(out);
14923         mMobileRadioActiveUnknownTime.writeToParcel(out);
14924         mMobileRadioActiveUnknownCount.writeToParcel(out);
14925         mWifiMulticastWakelockTimer.writeToParcel(out, uSecRealtime);
14926         mWifiOnTimer.writeToParcel(out, uSecRealtime);
14927         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
14928         for (int i=0; i<NUM_WIFI_STATES; i++) {
14929             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
14930         }
14931         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14932             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
14933         }
14934         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14935             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14936         }
14937         mWifiActiveTimer.writeToParcel(out, uSecRealtime);
14938         mWifiActivity.writeToParcel(out, 0);
14939         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14940             mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
14941         }
14942         mBluetoothActivity.writeToParcel(out, 0);
14943         mModemActivity.writeToParcel(out, 0);
14944         out.writeInt(mHasWifiReporting ? 1 : 0);
14945         out.writeInt(mHasBluetoothReporting ? 1 : 0);
14946         out.writeInt(mHasModemReporting ? 1 : 0);
14947
14948         out.writeInt(mNumConnectivityChange);
14949         out.writeInt(mLoadedNumConnectivityChange);
14950         out.writeInt(mUnpluggedNumConnectivityChange);
14951         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
14952         mCameraOnTimer.writeToParcel(out, uSecRealtime);
14953         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
14954         out.writeInt(mDischargeUnplugLevel);
14955         out.writeInt(mDischargePlugLevel);
14956         out.writeInt(mDischargeCurrentLevel);
14957         out.writeInt(mCurrentBatteryLevel);
14958         out.writeInt(mLowDischargeAmountSinceCharge);
14959         out.writeInt(mHighDischargeAmountSinceCharge);
14960         out.writeInt(mDischargeAmountScreenOn);
14961         out.writeInt(mDischargeAmountScreenOnSinceCharge);
14962         out.writeInt(mDischargeAmountScreenOff);
14963         out.writeInt(mDischargeAmountScreenOffSinceCharge);
14964         out.writeInt(mDischargeAmountScreenDoze);
14965         out.writeInt(mDischargeAmountScreenDozeSinceCharge);
14966         mDischargeStepTracker.writeToParcel(out);
14967         mChargeStepTracker.writeToParcel(out);
14968         mDischargeCounter.writeToParcel(out);
14969         mDischargeScreenOffCounter.writeToParcel(out);
14970         mDischargeScreenDozeCounter.writeToParcel(out);
14971         mDischargeLightDozeCounter.writeToParcel(out);
14972         mDischargeDeepDozeCounter.writeToParcel(out);
14973         out.writeLong(mLastWriteTime);
14974
14975         out.writeInt(mRpmStats.size());
14976         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
14977             SamplingTimer rpmt = ent.getValue();
14978             if (rpmt != null) {
14979                 out.writeInt(1);
14980                 out.writeString(ent.getKey());
14981                 rpmt.writeToParcel(out, uSecRealtime);
14982             } else {
14983                 out.writeInt(0);
14984             }
14985         }
14986         out.writeInt(mScreenOffRpmStats.size());
14987         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
14988             SamplingTimer rpmt = ent.getValue();
14989             if (rpmt != null) {
14990                 out.writeInt(1);
14991                 out.writeString(ent.getKey());
14992                 rpmt.writeToParcel(out, uSecRealtime);
14993             } else {
14994                 out.writeInt(0);
14995             }
14996         }
14997
14998         if (inclUids) {
14999             out.writeInt(mKernelWakelockStats.size());
15000             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
15001                 SamplingTimer kwlt = ent.getValue();
15002                 if (kwlt != null) {
15003                     out.writeInt(1);
15004                     out.writeString(ent.getKey());
15005                     kwlt.writeToParcel(out, uSecRealtime);
15006                 } else {
15007                     out.writeInt(0);
15008                 }
15009             }
15010             out.writeInt(mWakeupReasonStats.size());
15011             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
15012                 SamplingTimer timer = ent.getValue();
15013                 if (timer != null) {
15014                     out.writeInt(1);
15015                     out.writeString(ent.getKey());
15016                     timer.writeToParcel(out, uSecRealtime);
15017                 } else {
15018                     out.writeInt(0);
15019                 }
15020             }
15021         } else {
15022             out.writeInt(0);
15023             out.writeInt(0);
15024         }
15025
15026         out.writeInt(mKernelMemoryStats.size());
15027         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
15028             SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
15029             if (kmt != null) {
15030                 out.writeInt(1);
15031                 out.writeLong(mKernelMemoryStats.keyAt(i));
15032                 kmt.writeToParcel(out, uSecRealtime);
15033             } else {
15034                 out.writeInt(0);
15035             }
15036         }
15037
15038         if (inclUids) {
15039             int size = mUidStats.size();
15040             out.writeInt(size);
15041             for (int i = 0; i < size; i++) {
15042                 out.writeInt(mUidStats.keyAt(i));
15043                 Uid uid = mUidStats.valueAt(i);
15044
15045                 uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
15046             }
15047         } else {
15048             out.writeInt(0);
15049         }
15050     }
15051
15052     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
15053         new Parcelable.Creator<BatteryStatsImpl>() {
15054         public BatteryStatsImpl createFromParcel(Parcel in) {
15055             return new BatteryStatsImpl(in);
15056         }
15057
15058         public BatteryStatsImpl[] newArray(int size) {
15059             return new BatteryStatsImpl[size];
15060         }
15061     };
15062
15063     public void prepareForDumpLocked() {
15064         // Need to retrieve current kernel wake lock stats before printing.
15065         pullPendingStateUpdatesLocked();
15066
15067         // Pull the clock time.  This may update the time and make a new history entry
15068         // if we had originally pulled a time before the RTC was set.
15069         getStartClockTime();
15070     }
15071
15072     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
15073         if (DEBUG) {
15074             pw.println("mOnBatteryTimeBase:");
15075             mOnBatteryTimeBase.dump(pw, "  ");
15076             pw.println("mOnBatteryScreenOffTimeBase:");
15077             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
15078             Printer pr = new PrintWriterPrinter(pw);
15079             pr.println("*** Screen on timer:");
15080             mScreenOnTimer.logState(pr, "  ");
15081             pr.println("*** Screen doze timer:");
15082             mScreenDozeTimer.logState(pr, "  ");
15083             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
15084                 pr.println("*** Screen brightness #" + i + ":");
15085                 mScreenBrightnessTimer[i].logState(pr, "  ");
15086             }
15087             pr.println("*** Interactive timer:");
15088             mInteractiveTimer.logState(pr, "  ");
15089             pr.println("*** Power save mode timer:");
15090             mPowerSaveModeEnabledTimer.logState(pr, "  ");
15091             pr.println("*** Device idle mode light timer:");
15092             mDeviceIdleModeLightTimer.logState(pr, "  ");
15093             pr.println("*** Device idle mode full timer:");
15094             mDeviceIdleModeFullTimer.logState(pr, "  ");
15095             pr.println("*** Device light idling timer:");
15096             mDeviceLightIdlingTimer.logState(pr, "  ");
15097             pr.println("*** Device idling timer:");
15098             mDeviceIdlingTimer.logState(pr, "  ");
15099             pr.println("*** Phone timer:");
15100             mPhoneOnTimer.logState(pr, "  ");
15101             for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
15102                 pr.println("*** Phone signal strength #" + i + ":");
15103                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
15104             }
15105             pr.println("*** Signal scanning :");
15106             mPhoneSignalScanningTimer.logState(pr, "  ");
15107             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
15108                 pr.println("*** Data connection type #" + i + ":");
15109                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
15110             }
15111             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
15112             pr.println("*** Mobile network active timer:");
15113             mMobileRadioActiveTimer.logState(pr, "  ");
15114             pr.println("*** Mobile network active adjusted timer:");
15115             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
15116             pr.println("*** Wifi Multicast WakeLock Timer:");
15117             mWifiMulticastWakelockTimer.logState(pr, "  ");
15118             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
15119             pr.println("*** Wifi timer:");
15120             mWifiOnTimer.logState(pr, "  ");
15121             pr.println("*** WifiRunning timer:");
15122             mGlobalWifiRunningTimer.logState(pr, "  ");
15123             for (int i=0; i<NUM_WIFI_STATES; i++) {
15124                 pr.println("*** Wifi state #" + i + ":");
15125                 mWifiStateTimer[i].logState(pr, "  ");
15126             }
15127             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15128                 pr.println("*** Wifi suppl state #" + i + ":");
15129                 mWifiSupplStateTimer[i].logState(pr, "  ");
15130             }
15131             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15132                 pr.println("*** Wifi signal strength #" + i + ":");
15133                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
15134             }
15135             for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
15136                 pr.println("*** GPS signal quality #" + i + ":");
15137                 mGpsSignalQualityTimer[i].logState(pr, "  ");
15138             }
15139             pr.println("*** Flashlight timer:");
15140             mFlashlightOnTimer.logState(pr, "  ");
15141             pr.println("*** Camera timer:");
15142             mCameraOnTimer.logState(pr, "  ");
15143         }
15144         super.dumpLocked(context, pw, flags, reqUid, histStart);
15145         pw.print("Total cpu time reads: ");
15146         pw.println(mNumCpuTimeReads);
15147         pw.print("Batched cpu time reads: ");
15148         pw.println(mNumBatchedCpuTimeReads);
15149         pw.print("Batching Duration (min): ");
15150         pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTime) / (60 * 1000));
15151     }
15152 }