1 /*
2  * Copyright (C) 2006-2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.os;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.ActivityManager;
22 import android.bluetooth.BluetoothActivityEnergyInfo;
23 import android.bluetooth.UidTraffic;
24 import android.content.BroadcastReceiver;
25 import android.content.ContentResolver;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.database.ContentObserver;
30 import android.hardware.usb.UsbManager;
31 import android.net.ConnectivityManager;
32 import android.net.NetworkStats;
33 import android.net.Uri;
34 import android.net.wifi.WifiActivityEnergyInfo;
35 import android.net.wifi.WifiManager;
36 import android.os.BatteryManager;
37 import android.os.BatteryStats;
38 import android.os.Build;
39 import android.os.FileUtils;
40 import android.os.Handler;
41 import android.os.IBatteryPropertiesRegistrar;
42 import android.os.Looper;
43 import android.os.Message;
44 import android.os.OsProtoEnums;
45 import android.os.Parcel;
46 import android.os.ParcelFormatException;
47 import android.os.Parcelable;
48 import android.os.PowerManager;
49 import android.os.Process;
50 import android.os.RemoteException;
51 import android.os.ServiceManager;
52 import android.os.SystemClock;
53 import android.os.UserHandle;
54 import android.os.WorkSource;
55 import android.os.WorkSource.WorkChain;
56 import android.os.connectivity.CellularBatteryStats;
57 import android.os.connectivity.GpsBatteryStats;
58 import android.os.connectivity.WifiBatteryStats;
59 import android.provider.Settings;
60 import android.telephony.DataConnectionRealTimeInfo;
61 import android.telephony.ModemActivityInfo;
62 import android.telephony.ServiceState;
63 import android.telephony.SignalStrength;
64 import android.telephony.TelephonyManager;
65 import android.text.TextUtils;
66 import android.util.ArrayMap;
67 import android.util.IntArray;
68 import android.util.KeyValueListParser;
69 import android.util.Log;
70 import android.util.LogWriter;
71 import android.util.LongSparseArray;
72 import android.util.LongSparseLongArray;
73 import android.util.MutableInt;
74 import android.util.Pools;
75 import android.util.PrintWriterPrinter;
76 import android.util.Printer;
77 import android.util.Slog;
78 import android.util.SparseArray;
79 import android.util.SparseIntArray;
80 import android.util.SparseLongArray;
81 import android.util.StatsLog;
82 import android.util.TimeUtils;
83 import android.util.Xml;
84 import android.view.Display;
85 
86 import com.android.internal.annotations.GuardedBy;
87 import com.android.internal.annotations.VisibleForTesting;
88 import com.android.internal.location.gnssmetrics.GnssMetrics;
89 import com.android.internal.net.NetworkStatsFactory;
90 import com.android.internal.util.ArrayUtils;
91 import com.android.internal.util.FastPrintWriter;
92 import com.android.internal.util.FastXmlSerializer;
93 import com.android.internal.util.JournaledFile;
94 import com.android.internal.util.XmlUtils;
95 
96 import libcore.util.EmptyArray;
97 
98 import org.xmlpull.v1.XmlPullParser;
99 import org.xmlpull.v1.XmlPullParserException;
100 import org.xmlpull.v1.XmlSerializer;
101 
102 import java.io.ByteArrayOutputStream;
103 import java.io.File;
104 import java.io.FileInputStream;
105 import java.io.FileNotFoundException;
106 import java.io.FileOutputStream;
107 import java.io.IOException;
108 import java.io.PrintWriter;
109 import java.nio.charset.StandardCharsets;
110 import java.util.ArrayList;
111 import java.util.Arrays;
112 import java.util.Calendar;
113 import java.util.HashMap;
114 import java.util.Iterator;
115 import java.util.LinkedList;
116 import java.util.List;
117 import java.util.Map;
118 import java.util.Queue;
119 import java.util.concurrent.Future;
120 import java.util.concurrent.atomic.AtomicInteger;
121 import java.util.concurrent.locks.ReentrantLock;
122 
123 /**
124  * All information we are collecting about things that can happen that impact
125  * battery life.  All times are represented in microseconds except where indicated
126  * otherwise.
127  */
128 public class BatteryStatsImpl extends BatteryStats {
129     private static final String TAG = "BatteryStatsImpl";
130     private static final boolean DEBUG = false;
131     public static final boolean DEBUG_ENERGY = false;
132     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
133     private static final boolean DEBUG_MEMORY = false;
134     private static final boolean DEBUG_HISTORY = false;
135     private static final boolean USE_OLD_HISTORY = false;   // for debugging.
136 
137     // TODO: remove "tcp" from network methods, since we measure total stats.
138 
139     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
140     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
141 
142     // Current on-disk Parcel version
143     private static final int VERSION = 177 + (USE_OLD_HISTORY ? 1000 : 0);
144 
145     // Maximum number of items we will record in the history.
146     private static final int MAX_HISTORY_ITEMS;
147 
148     // No, really, THIS is the maximum number of items we will record in the history.
149     private static final int MAX_MAX_HISTORY_ITEMS;
150 
151     // The maximum number of names wakelocks we will keep track of
152     // per uid; once the limit is reached, we batch the remaining wakelocks
153     // in to one common name.
154     private static final int MAX_WAKELOCKS_PER_UID;
155 
156     static final int MAX_HISTORY_BUFFER; // 256KB
157     static final int MAX_MAX_HISTORY_BUFFER; // 320KB
158 
159     static {
160         if (ActivityManager.isLowRamDeviceStatic()) {
161             MAX_HISTORY_ITEMS = 800;
162             MAX_MAX_HISTORY_ITEMS = 1200;
163             MAX_WAKELOCKS_PER_UID = 40;
164             MAX_HISTORY_BUFFER = 96*1024;  // 96KB
165             MAX_MAX_HISTORY_BUFFER = 128*1024; // 128KB
166         } else {
167             MAX_HISTORY_ITEMS = 4000;
168             MAX_MAX_HISTORY_ITEMS = 6000;
169             MAX_WAKELOCKS_PER_UID = 200;
170             MAX_HISTORY_BUFFER = 512*1024;  // 512KB
171             MAX_MAX_HISTORY_BUFFER = 640*1024;  // 640KB
172         }
173     }
174 
175     // Number of transmit power states the Wifi controller can be in.
176     private static final int NUM_WIFI_TX_LEVELS = 1;
177 
178     // Number of transmit power states the Bluetooth controller can be in.
179     private static final int NUM_BT_TX_LEVELS = 1;
180 
181     /**
182      * Holding a wakelock costs more than just using the cpu.
183      * Currently, we assign only half the cpu time to an app that is running but
184      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
185      * If no app is holding a wakelock, then the distribution is normal.
186      */
187     @VisibleForTesting
188     public static final int WAKE_LOCK_WEIGHT = 50;
189 
190     protected Clocks mClocks;
191 
192     private final JournaledFile mFile;
193     public final AtomicFile mCheckinFile;
194     public final AtomicFile mDailyFile;
195 
196     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
197     static final int MSG_REPORT_POWER_CHANGE = 2;
198     static final int MSG_REPORT_CHARGING = 3;
199     static final int MSG_REPORT_RESET_STATS = 4;
200     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
201 
202     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
203     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
204 
205     @VisibleForTesting
206     protected KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
207     @VisibleForTesting
208     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
209     @VisibleForTesting
210     protected KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
211             new KernelUidCpuFreqTimeReader();
212     @VisibleForTesting
213     protected KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader =
214             new KernelUidCpuActiveTimeReader();
215     @VisibleForTesting
216     protected KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
217             new KernelUidCpuClusterTimeReader();
218     @VisibleForTesting
219     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
220 
221     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
222             = new KernelMemoryBandwidthStats();
223     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
getKernelMemoryStats()224     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
225         return mKernelMemoryStats;
226     }
227 
228     @GuardedBy("this")
229     public boolean mPerProcStateCpuTimesAvailable = true;
230 
231     /**
232      * Uids for which per-procstate cpu times need to be updated.
233      *
234      * Contains uid -> procState mappings.
235      */
236     @GuardedBy("this")
237     @VisibleForTesting
238     protected final SparseIntArray mPendingUids = new SparseIntArray();
239 
240     @GuardedBy("this")
241     private long mNumSingleUidCpuTimeReads;
242     @GuardedBy("this")
243     private long mNumBatchedSingleUidCpuTimeReads;
244     @GuardedBy("this")
245     private long mCpuTimeReadsTrackingStartTime = SystemClock.uptimeMillis();
246     @GuardedBy("this")
247     private int mNumUidsRemoved;
248     @GuardedBy("this")
249     private int mNumAllUidCpuTimeReads;
250 
251     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
252     private final RpmStats mTmpRpmStats = new RpmStats();
253     /** The soonest the RPM stats can be updated after it was last updated. */
254     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
255     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
256     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
257     /**
258      * Use a queue to delay removing UIDs from {@link KernelUidCpuTimeReader},
259      * {@link KernelUidCpuActiveTimeReader}, {@link KernelUidCpuClusterTimeReader},
260      * {@link KernelUidCpuFreqTimeReader} and from the Kernel.
261      *
262      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
263      * Batterystats both need to access UID cpu time. To resolve this race condition, only
264      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
265      * implemented so that STATSD can capture those UID times before they are deleted.
266      */
267     @GuardedBy("this")
268     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
269     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
270 
271     @VisibleForTesting
272     public final class UidToRemove {
273         int startUid;
274         int endUid;
275         long timeAddedInQueue;
276 
277         /** Remove just one UID */
UidToRemove(int uid, long timestamp)278         public UidToRemove(int uid, long timestamp) {
279             this(uid, uid, timestamp);
280         }
281 
282         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)283         public UidToRemove(int startUid, int endUid, long timestamp) {
284             this.startUid = startUid;
285             this.endUid = endUid;
286             timeAddedInQueue = timestamp;
287         }
288 
remove()289         void remove() {
290             if (startUid == endUid) {
291                 mKernelUidCpuTimeReader.removeUid(startUid);
292                 mKernelUidCpuFreqTimeReader.removeUid(startUid);
293                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
294                     mKernelUidCpuActiveTimeReader.removeUid(startUid);
295                     mKernelUidCpuClusterTimeReader.removeUid(startUid);
296                 }
297                 if (mKernelSingleUidTimeReader != null) {
298                     mKernelSingleUidTimeReader.removeUid(startUid);
299                 }
300                 mNumUidsRemoved++;
301             } else if (startUid < endUid) {
302                 mKernelUidCpuFreqTimeReader.removeUidsInRange(startUid, endUid);
303                 mKernelUidCpuTimeReader.removeUidsInRange(startUid, endUid);
304                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
305                     mKernelUidCpuActiveTimeReader.removeUidsInRange(startUid, endUid);
306                     mKernelUidCpuClusterTimeReader.removeUidsInRange(startUid, endUid);
307                 }
308                 if (mKernelSingleUidTimeReader != null) {
309                     mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
310                 }
311                 // Treat as one. We don't know how many uids there are in between.
312                 mNumUidsRemoved++;
313             } else {
314                 Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
315             }
316         }
317     }
318 
319     public interface BatteryCallback {
batteryNeedsCpuUpdate()320         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)321         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)322         public void batterySendBroadcast(Intent intent);
batteryStatsReset()323         public void batteryStatsReset();
324     }
325 
326     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)327         public void fillLowPowerStats(RpmStats rpmStats);
getPlatformLowPowerStats()328         public String getPlatformLowPowerStats();
getSubsystemLowPowerStats()329         public String getSubsystemLowPowerStats();
330     }
331 
332     public static abstract class UserInfoProvider {
333         private int[] userIds;
getUserIds()334         protected abstract @Nullable int[] getUserIds();
335         @VisibleForTesting
refreshUserIds()336         public final void refreshUserIds() {
337             userIds = getUserIds();
338         }
339         @VisibleForTesting
exists(int userId)340         public boolean exists(int userId) {
341             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
342         }
343     }
344 
345     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
346 
347     final class MyHandler extends Handler {
MyHandler(Looper looper)348         public MyHandler(Looper looper) {
349             super(looper, null, true);
350         }
351 
352         @Override
handleMessage(Message msg)353         public void handleMessage(Message msg) {
354             BatteryCallback cb = mCallback;
355             switch (msg.what) {
356                 case MSG_REPORT_CPU_UPDATE_NEEDED:
357                     if (cb != null) {
358                         cb.batteryNeedsCpuUpdate();
359                     }
360                     break;
361                 case MSG_REPORT_POWER_CHANGE:
362                     if (cb != null) {
363                         cb.batteryPowerChanged(msg.arg1 != 0);
364                     }
365                     break;
366                 case MSG_REPORT_CHARGING:
367                     if (cb != null) {
368                         final String action;
369                         synchronized (BatteryStatsImpl.this) {
370                             action = mCharging ? BatteryManager.ACTION_CHARGING
371                                     : BatteryManager.ACTION_DISCHARGING;
372                         }
373                         Intent intent = new Intent(action);
374                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
375                         cb.batterySendBroadcast(intent);
376                     }
377                     break;
378                 case MSG_REPORT_RESET_STATS:
379                     if (cb != null) {
380                         cb.batteryStatsReset();
381                     }
382                 }
383         }
384     }
385 
postBatteryNeedsCpuUpdateMsg()386     public void postBatteryNeedsCpuUpdateMsg() {
387         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
388     }
389 
390     /**
391      * Update per-freq cpu times for all the uids in {@link #mPendingUids}.
392      */
updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff)393     public void updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
394         final SparseIntArray uidStates;
395         synchronized (BatteryStatsImpl.this) {
396             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
397                 return;
398             }
399             if(!initKernelSingleUidTimeReaderLocked()) {
400                 return;
401             }
402             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
403             // compute deltas since it might result in mis-attributing cpu times to wrong states.
404             if (mKernelSingleUidTimeReader.hasStaleData()) {
405                 mPendingUids.clear();
406                 return;
407             }
408 
409             if (mPendingUids.size() == 0) {
410                 return;
411             }
412             uidStates = mPendingUids.clone();
413             mPendingUids.clear();
414         }
415         for (int i = uidStates.size() - 1; i >= 0; --i) {
416             final int uid = uidStates.keyAt(i);
417             final int procState = uidStates.valueAt(i);
418             final int[] isolatedUids;
419             final Uid u;
420             synchronized (BatteryStatsImpl.this) {
421                 // It's possible that uid no longer exists and any internal references have
422                 // already been deleted, so using {@link #getAvailableUidStatsLocked} to avoid
423                 // creating an UidStats object if it doesn't already exist.
424                 u = getAvailableUidStatsLocked(uid);
425                 if (u == null) {
426                     continue;
427                 }
428                 if (u.mChildUids == null) {
429                     isolatedUids = null;
430                 } else {
431                     isolatedUids = u.mChildUids.toArray();
432                     for (int j = isolatedUids.length - 1; j >= 0; --j) {
433                         isolatedUids[j] = u.mChildUids.get(j);
434                     }
435                 }
436             }
437             long[] cpuTimesMs = mKernelSingleUidTimeReader.readDeltaMs(uid);
438             if (isolatedUids != null) {
439                 for (int j = isolatedUids.length - 1; j >= 0; --j) {
440                     cpuTimesMs = addCpuTimes(cpuTimesMs,
441                             mKernelSingleUidTimeReader.readDeltaMs(isolatedUids[j]));
442                 }
443             }
444             if (onBattery && cpuTimesMs != null) {
445                 synchronized (BatteryStatsImpl.this) {
446                     u.addProcStateTimesMs(procState, cpuTimesMs, onBattery);
447                     u.addProcStateScreenOffTimesMs(procState, cpuTimesMs, onBatteryScreenOff);
448                 }
449             }
450         }
451     }
452 
clearPendingRemovedUids()453     public void clearPendingRemovedUids() {
454         long cutOffTime = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
455         while (!mPendingRemovedUids.isEmpty()
456                 && mPendingRemovedUids.peek().timeAddedInQueue < cutOffTime) {
457             mPendingRemovedUids.poll().remove();
458         }
459     }
460 
copyFromAllUidsCpuTimes()461     public void copyFromAllUidsCpuTimes() {
462         synchronized (BatteryStatsImpl.this) {
463             copyFromAllUidsCpuTimes(
464                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
465         }
466     }
467 
468     /**
469      * When the battery/screen state changes, we don't attribute the cpu times to any process
470      * but we still need to snapshots of all uids to get correct deltas later on. Since we
471      * already read this data for updating per-freq cpu times, we can use the same data for
472      * per-procstate cpu times.
473      */
copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)474     public void copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
475         synchronized (BatteryStatsImpl.this) {
476             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
477                 return;
478             }
479             if(!initKernelSingleUidTimeReaderLocked()) {
480                 return;
481             }
482 
483             final SparseArray<long[]> allUidCpuFreqTimesMs =
484                     mKernelUidCpuFreqTimeReader.getAllUidCpuFreqTimeMs();
485             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
486             // compute deltas since it might result in mis-attributing cpu times to wrong states.
487             if (mKernelSingleUidTimeReader.hasStaleData()) {
488                 mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
489                 mKernelSingleUidTimeReader.markDataAsStale(false);
490                 mPendingUids.clear();
491                 return;
492             }
493             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
494                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
495                 final Uid u = getAvailableUidStatsLocked(mapUid(uid));
496                 if (u == null) {
497                     continue;
498                 }
499                 final long[] cpuTimesMs = allUidCpuFreqTimesMs.valueAt(i);
500                 if (cpuTimesMs == null) {
501                     continue;
502                 }
503                 final long[] deltaTimesMs = mKernelSingleUidTimeReader.computeDelta(
504                         uid, cpuTimesMs.clone());
505                 if (onBattery && deltaTimesMs != null) {
506                     final int procState;
507                     final int idx = mPendingUids.indexOfKey(uid);
508                     if (idx >= 0) {
509                         procState = mPendingUids.valueAt(idx);
510                         mPendingUids.removeAt(idx);
511                     } else {
512                         procState = u.mProcessState;
513                     }
514                     if (procState >= 0 && procState < Uid.NUM_PROCESS_STATE) {
515                         u.addProcStateTimesMs(procState, deltaTimesMs, onBattery);
516                         u.addProcStateScreenOffTimesMs(procState, deltaTimesMs, onBatteryScreenOff);
517                     }
518                 }
519             }
520         }
521     }
522 
523     @VisibleForTesting
addCpuTimes(long[] timesA, long[] timesB)524     public long[] addCpuTimes(long[] timesA, long[] timesB) {
525         if (timesA != null && timesB != null) {
526             for (int i = timesA.length - 1; i >= 0; --i) {
527                 timesA[i] += timesB[i];
528             }
529             return timesA;
530         }
531         return timesA == null ? (timesB == null ? null : timesB) : timesA;
532     }
533 
534     @GuardedBy("this")
initKernelSingleUidTimeReaderLocked()535     private boolean initKernelSingleUidTimeReaderLocked() {
536         if (mKernelSingleUidTimeReader == null) {
537             if (mPowerProfile == null) {
538                 return false;
539             }
540             if (mCpuFreqs == null) {
541                 mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
542             }
543             if (mCpuFreqs != null) {
544                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
545             } else {
546                 mPerProcStateCpuTimesAvailable = mKernelUidCpuFreqTimeReader.allUidTimesAvailable();
547                 return false;
548             }
549         }
550         mPerProcStateCpuTimesAvailable = mKernelUidCpuFreqTimeReader.allUidTimesAvailable()
551                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
552         return true;
553     }
554 
555     public interface Clocks {
elapsedRealtime()556         public long elapsedRealtime();
uptimeMillis()557         public long uptimeMillis();
558     }
559 
560     public static class SystemClocks implements Clocks {
elapsedRealtime()561         public long elapsedRealtime() {
562             return SystemClock.elapsedRealtime();
563         }
564 
uptimeMillis()565         public long uptimeMillis() {
566             return SystemClock.uptimeMillis();
567         }
568     }
569 
570     public interface ExternalStatsSync {
571         int UPDATE_CPU = 0x01;
572         int UPDATE_WIFI = 0x02;
573         int UPDATE_RADIO = 0x04;
574         int UPDATE_BT = 0x08;
575         int UPDATE_RPM = 0x10; // 16
576         int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM;
577 
scheduleSync(String reason, int flags)578         Future<?> scheduleSync(String reason, int flags);
scheduleCpuSyncDueToRemovedUid(int uid)579         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff, long delayMillis)580         Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff,
581                 long delayMillis);
scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)582         Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
scheduleCpuSyncDueToSettingChange()583         Future<?> scheduleCpuSyncDueToSettingChange();
scheduleCpuSyncDueToScreenStateChange(boolean onBattery, boolean onBatteryScreenOff)584         Future<?> scheduleCpuSyncDueToScreenStateChange(boolean onBattery,
585                 boolean onBatteryScreenOff);
scheduleCpuSyncDueToWakelockChange(long delayMillis)586         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
cancelCpuSyncDueToWakelockChange()587         void cancelCpuSyncDueToWakelockChange();
scheduleSyncDueToBatteryLevelChange(long delayMillis)588         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
589     }
590 
591     public Handler mHandler;
592     private ExternalStatsSync mExternalSync = null;
593     @VisibleForTesting
594     protected UserInfoProvider mUserInfoProvider = null;
595 
596     private BatteryCallback mCallback;
597 
598     /**
599      * Mapping isolated uids to the actual owning app uid.
600      */
601     final SparseIntArray mIsolatedUids = new SparseIntArray();
602 
603     /**
604      * The statistics we have collected organized by uids.
605      */
606     final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
607 
608     // A set of pools of currently active timers.  When a timer is queried, we will divide the
609     // elapsed time by the number of active timers to arrive at that timer's share of the time.
610     // In order to do this, we must refresh each timer whenever the number of active timers
611     // changes.
612     @VisibleForTesting
613     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
614     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
615     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
616     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
617     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
618     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
619     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
620     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
621     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
622     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
623     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
624     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
625     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
626     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
627     final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
628 
629     // Last partial timers we use for distributing CPU usage.
630     @VisibleForTesting
631     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
632 
633     // These are the objects that will want to do something when the device
634     // is unplugged from power.
635     protected final TimeBase mOnBatteryTimeBase = new TimeBase();
636 
637     // These are the objects that will want to do something when the device
638     // is unplugged from power *and* the screen is off or doze.
639     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase();
640 
641     // Set to true when we want to distribute CPU across wakelocks for the next
642     // CPU update, even if we aren't currently running wake locks.
643     boolean mDistributeWakelockCpu;
644 
645     boolean mShuttingDown;
646 
647     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
648 
649     long mHistoryBaseTime;
650     protected boolean mHaveBatteryLevel = false;
651     protected boolean mRecordingHistory = false;
652     int mNumHistoryItems;
653 
654     final Parcel mHistoryBuffer = Parcel.obtain();
655     final HistoryItem mHistoryLastWritten = new HistoryItem();
656     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
657     final HistoryItem mHistoryReadTmp = new HistoryItem();
658     final HistoryItem mHistoryAddTmp = new HistoryItem();
659     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
660     String[] mReadHistoryStrings;
661     int[] mReadHistoryUids;
662     int mReadHistoryChars;
663     int mNextHistoryTagIdx = 0;
664     int mNumHistoryTagChars = 0;
665     int mHistoryBufferLastPos = -1;
666     boolean mHistoryOverflow = false;
667     int mActiveHistoryStates = 0xffffffff;
668     int mActiveHistoryStates2 = 0xffffffff;
669     long mLastHistoryElapsedRealtime = 0;
670     long mTrackRunningHistoryElapsedRealtime = 0;
671     long mTrackRunningHistoryUptime = 0;
672 
673     final HistoryItem mHistoryCur = new HistoryItem();
674 
675     HistoryItem mHistory;
676     HistoryItem mHistoryEnd;
677     HistoryItem mHistoryLastEnd;
678     HistoryItem mHistoryCache;
679 
680     // Used by computeHistoryStepDetails
681     HistoryStepDetails mLastHistoryStepDetails = null;
682     byte mLastHistoryStepLevel = 0;
683     final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
684     final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
685     final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
686 
687     /**
688      * Total time (in milliseconds) spent executing in user code.
689      */
690     long mLastStepCpuUserTime;
691     long mCurStepCpuUserTime;
692     /**
693      * Total time (in milliseconds) spent executing in kernel code.
694      */
695     long mLastStepCpuSystemTime;
696     long mCurStepCpuSystemTime;
697     /**
698      * Times from /proc/stat (but measured in milliseconds).
699      */
700     long mLastStepStatUserTime;
701     long mLastStepStatSystemTime;
702     long mLastStepStatIOWaitTime;
703     long mLastStepStatIrqTime;
704     long mLastStepStatSoftIrqTime;
705     long mLastStepStatIdleTime;
706     long mCurStepStatUserTime;
707     long mCurStepStatSystemTime;
708     long mCurStepStatIOWaitTime;
709     long mCurStepStatIrqTime;
710     long mCurStepStatSoftIrqTime;
711     long mCurStepStatIdleTime;
712 
713     private HistoryItem mHistoryIterator;
714     private boolean mReadOverflow;
715     private boolean mIteratingHistory;
716 
717     int mStartCount;
718 
719     long mStartClockTime;
720     String mStartPlatformVersion;
721     String mEndPlatformVersion;
722 
723     long mUptime;
724     long mUptimeStart;
725     long mRealtime;
726     long mRealtimeStart;
727 
728     int mWakeLockNesting;
729     boolean mWakeLockImportant;
730     public boolean mRecordAllHistory;
731     boolean mNoAutoReset;
732 
733     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
734     protected int mScreenState = Display.STATE_UNKNOWN;
735     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
736     protected StopwatchTimer mScreenOnTimer;
737     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
738     protected StopwatchTimer mScreenDozeTimer;
739 
740     int mScreenBrightnessBin = -1;
741     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
742 
743     boolean mPretendScreenOff;
744 
745     boolean mInteractive;
746     StopwatchTimer mInteractiveTimer;
747 
748     boolean mPowerSaveModeEnabled;
749     StopwatchTimer mPowerSaveModeEnabledTimer;
750 
751     boolean mDeviceIdling;
752     StopwatchTimer mDeviceIdlingTimer;
753 
754     boolean mDeviceLightIdling;
755     StopwatchTimer mDeviceLightIdlingTimer;
756 
757     int mDeviceIdleMode;
758     long mLastIdleTimeStart;
759     long mLongestLightIdleTime;
760     long mLongestFullIdleTime;
761     StopwatchTimer mDeviceIdleModeLightTimer;
762     StopwatchTimer mDeviceIdleModeFullTimer;
763 
764     boolean mPhoneOn;
765     StopwatchTimer mPhoneOnTimer;
766 
767     int mAudioOnNesting;
768     StopwatchTimer mAudioOnTimer;
769 
770     int mVideoOnNesting;
771     StopwatchTimer mVideoOnTimer;
772 
773     int mFlashlightOnNesting;
774     StopwatchTimer mFlashlightOnTimer;
775 
776     int mCameraOnNesting;
777     StopwatchTimer mCameraOnTimer;
778 
779     private static final int USB_DATA_UNKNOWN = 0;
780     private static final int USB_DATA_DISCONNECTED = 1;
781     private static final int USB_DATA_CONNECTED = 2;
782     int mUsbDataState = USB_DATA_UNKNOWN;
783 
784     int mGpsSignalQualityBin = -1;
785     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
786     protected final StopwatchTimer[] mGpsSignalQualityTimer =
787         new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
788 
789     int mPhoneSignalStrengthBin = -1;
790     int mPhoneSignalStrengthBinRaw = -1;
791     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
792             new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
793 
794     StopwatchTimer mPhoneSignalScanningTimer;
795 
796     int mPhoneDataConnectionType = -1;
797     final StopwatchTimer[] mPhoneDataConnectionsTimer =
798             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
799 
800     final LongSamplingCounter[] mNetworkByteActivityCounters =
801             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
802     final LongSamplingCounter[] mNetworkPacketActivityCounters =
803             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
804 
805     /**
806      * The WiFi Overall wakelock timer
807      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
808      * since addition of per UID timers would not result in an accurate value due to overlapp of
809      * per uid wakelock timers
810      */
811     StopwatchTimer mWifiMulticastWakelockTimer;
812 
813     /**
814      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
815      */
816     ControllerActivityCounterImpl mWifiActivity;
817 
818     /**
819      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
820      */
821     ControllerActivityCounterImpl mBluetoothActivity;
822 
823     /**
824      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
825      */
826     ControllerActivityCounterImpl mModemActivity;
827 
828     /**
829      * Whether the device supports WiFi controller energy reporting. This is set to true on
830      * the first WiFi energy report. See {@link #mWifiActivity}.
831      */
832     boolean mHasWifiReporting = false;
833 
834     /**
835      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
836      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
837      */
838     boolean mHasBluetoothReporting = false;
839 
840     /**
841      * Whether the device supports Modem controller energy reporting. This is set to true on
842      * the first Modem energy report. See {@link #mModemActivity}.
843      */
844     boolean mHasModemReporting = false;
845 
846     boolean mWifiOn;
847     StopwatchTimer mWifiOnTimer;
848 
849     boolean mGlobalWifiRunning;
850     StopwatchTimer mGlobalWifiRunningTimer;
851 
852     int mWifiState = -1;
853     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
854 
855     int mWifiSupplState = -1;
856     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
857 
858     int mWifiSignalStrengthBin = -1;
859     final StopwatchTimer[] mWifiSignalStrengthsTimer =
860             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
861 
862     StopwatchTimer mWifiActiveTimer;
863 
864     int mBluetoothScanNesting;
865     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
866     protected StopwatchTimer mBluetoothScanTimer;
867 
868     boolean mIsCellularTxPowerHigh = false;
869 
870     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
871     long mMobileRadioActiveStartTime;
872     StopwatchTimer mMobileRadioActiveTimer;
873     StopwatchTimer mMobileRadioActivePerAppTimer;
874     LongSamplingCounter mMobileRadioActiveAdjustedTime;
875     LongSamplingCounter mMobileRadioActiveUnknownTime;
876     LongSamplingCounter mMobileRadioActiveUnknownCount;
877 
878     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
879 
880     /**
881      * These provide time bases that discount the time the device is plugged
882      * in to power.
883      */
884     boolean mOnBattery;
885     @VisibleForTesting
886     protected boolean mOnBatteryInternal;
887 
888     /**
889      * External reporting of whether the device is actually charging.
890      */
891     boolean mCharging = true;
892     int mLastChargingStateLevel;
893 
894     /*
895      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
896      */
897     int mDischargeStartLevel;
898     int mDischargeUnplugLevel;
899     int mDischargePlugLevel;
900     int mDischargeCurrentLevel;
901     int mCurrentBatteryLevel;
902     int mLowDischargeAmountSinceCharge;
903     int mHighDischargeAmountSinceCharge;
904     int mDischargeScreenOnUnplugLevel;
905     int mDischargeScreenOffUnplugLevel;
906     int mDischargeScreenDozeUnplugLevel;
907     int mDischargeAmountScreenOn;
908     int mDischargeAmountScreenOnSinceCharge;
909     int mDischargeAmountScreenOff;
910     int mDischargeAmountScreenOffSinceCharge;
911     int mDischargeAmountScreenDoze;
912     int mDischargeAmountScreenDozeSinceCharge;
913 
914     private LongSamplingCounter mDischargeScreenOffCounter;
915     private LongSamplingCounter mDischargeScreenDozeCounter;
916     private LongSamplingCounter mDischargeCounter;
917     private LongSamplingCounter mDischargeLightDozeCounter;
918     private LongSamplingCounter mDischargeDeepDozeCounter;
919 
920     static final int MAX_LEVEL_STEPS = 200;
921 
922     int mInitStepMode = 0;
923     int mCurStepMode = 0;
924     int mModStepMode = 0;
925 
926     int mLastDischargeStepLevel;
927     int mMinDischargeStepLevel;
928     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
929     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
930     ArrayList<PackageChange> mDailyPackageChanges;
931 
932     int mLastChargeStepLevel;
933     int mMaxChargeStepLevel;
934     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
935     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
936 
937     static final int MAX_DAILY_ITEMS = 10;
938 
939     long mDailyStartTime = 0;
940     long mNextMinDailyDeadline = 0;
941     long mNextMaxDailyDeadline = 0;
942 
943     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
944 
945     long mLastWriteTime = 0; // Milliseconds
946 
947     private int mPhoneServiceState = -1;
948     private int mPhoneServiceStateRaw = -1;
949     private int mPhoneSimStateRaw = -1;
950 
951     private int mNumConnectivityChange;
952     private int mLoadedNumConnectivityChange;
953     private int mUnpluggedNumConnectivityChange;
954 
955     private int mEstimatedBatteryCapacity = -1;
956 
957     private int mMinLearnedBatteryCapacity = -1;
958     private int mMaxLearnedBatteryCapacity = -1;
959 
960     private long[] mCpuFreqs;
961 
962     @VisibleForTesting
963     protected PowerProfile mPowerProfile;
964 
965     @GuardedBy("this")
966     private final Constants mConstants;
967 
968     /*
969      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
970      * recording their times when on-battery (regardless of screen state).
971      */
972     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
973     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
974     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
975 
976     @Override
getRpmStats()977     public Map<String, ? extends Timer> getRpmStats() {
978         return mRpmStats;
979     }
980 
981     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
982     @Override
getScreenOffRpmStats()983     public Map<String, ? extends Timer> getScreenOffRpmStats() {
984         return mScreenOffRpmStats;
985     }
986 
987     /*
988      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
989      */
990     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
991 
getKernelWakelockStats()992     public Map<String, ? extends Timer> getKernelWakelockStats() {
993         return mKernelWakelockStats;
994     }
995 
996     String mLastWakeupReason = null;
997     long mLastWakeupUptimeMs = 0;
998     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
999 
getWakeupReasonStats()1000     public Map<String, ? extends Timer> getWakeupReasonStats() {
1001         return mWakeupReasonStats;
1002     }
1003 
1004     @Override
getUahDischarge(int which)1005     public long getUahDischarge(int which) {
1006         return mDischargeCounter.getCountLocked(which);
1007     }
1008 
1009     @Override
getUahDischargeScreenOff(int which)1010     public long getUahDischargeScreenOff(int which) {
1011         return mDischargeScreenOffCounter.getCountLocked(which);
1012     }
1013 
1014     @Override
getUahDischargeScreenDoze(int which)1015     public long getUahDischargeScreenDoze(int which) {
1016         return mDischargeScreenDozeCounter.getCountLocked(which);
1017     }
1018 
1019     @Override
getUahDischargeLightDoze(int which)1020     public long getUahDischargeLightDoze(int which) {
1021         return mDischargeLightDozeCounter.getCountLocked(which);
1022     }
1023 
1024     @Override
getUahDischargeDeepDoze(int which)1025     public long getUahDischargeDeepDoze(int which) {
1026         return mDischargeDeepDozeCounter.getCountLocked(which);
1027     }
1028 
1029     @Override
getEstimatedBatteryCapacity()1030     public int getEstimatedBatteryCapacity() {
1031         return mEstimatedBatteryCapacity;
1032     }
1033 
1034     @Override
getMinLearnedBatteryCapacity()1035     public int getMinLearnedBatteryCapacity() {
1036         return mMinLearnedBatteryCapacity;
1037     }
1038 
1039     @Override
getMaxLearnedBatteryCapacity()1040     public int getMaxLearnedBatteryCapacity() {
1041         return mMaxLearnedBatteryCapacity;
1042     }
1043 
BatteryStatsImpl()1044     public BatteryStatsImpl() {
1045         this(new SystemClocks());
1046     }
1047 
BatteryStatsImpl(Clocks clocks)1048     public BatteryStatsImpl(Clocks clocks) {
1049         init(clocks);
1050         mFile = null;
1051         mCheckinFile = null;
1052         mDailyFile = null;
1053         mHandler = null;
1054         mPlatformIdleStateCallback = null;
1055         mUserInfoProvider = null;
1056         mConstants = new Constants(mHandler);
1057         clearHistoryLocked();
1058     }
1059 
init(Clocks clocks)1060     private void init(Clocks clocks) {
1061         mClocks = clocks;
1062     }
1063 
1064     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1065         void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1066         void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
1067     }
1068 
1069     // methods are protected not private to be VisibleForTesting
1070     public static class TimeBase {
1071         protected final ArrayList<TimeBaseObs> mObservers = new ArrayList<>();
1072 
1073         protected long mUptime;
1074         protected long mRealtime;
1075 
1076         protected boolean mRunning;
1077 
1078         protected long mPastUptime;
1079         protected long mUptimeStart;
1080         protected long mPastRealtime;
1081         protected long mRealtimeStart;
1082         protected long mUnpluggedUptime;
1083         protected long mUnpluggedRealtime;
1084 
dump(PrintWriter pw, String prefix)1085         public void dump(PrintWriter pw, String prefix) {
1086             StringBuilder sb = new StringBuilder(128);
1087             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
1088             sb.setLength(0);
1089             sb.append(prefix);
1090                     sb.append("mUptime=");
1091                     formatTimeMs(sb, mUptime / 1000);
1092             pw.println(sb.toString());
1093             sb.setLength(0);
1094             sb.append(prefix);
1095                     sb.append("mRealtime=");
1096                     formatTimeMs(sb, mRealtime / 1000);
1097             pw.println(sb.toString());
1098             sb.setLength(0);
1099             sb.append(prefix);
1100                     sb.append("mPastUptime=");
1101                     formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
1102                     formatTimeMs(sb, mUptimeStart / 1000);
1103                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
1104             pw.println(sb.toString());
1105             sb.setLength(0);
1106             sb.append(prefix);
1107                     sb.append("mPastRealtime=");
1108                     formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
1109                     formatTimeMs(sb, mRealtimeStart / 1000);
1110                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
1111             pw.println(sb.toString());
1112         }
1113 
add(TimeBaseObs observer)1114         public void add(TimeBaseObs observer) {
1115             mObservers.add(observer);
1116         }
1117 
remove(TimeBaseObs observer)1118         public void remove(TimeBaseObs observer) {
1119             if (!mObservers.remove(observer)) {
1120                 Slog.wtf(TAG, "Removed unknown observer: " + observer);
1121             }
1122         }
1123 
hasObserver(TimeBaseObs observer)1124         public boolean hasObserver(TimeBaseObs observer) {
1125             return mObservers.contains(observer);
1126         }
1127 
init(long uptime, long realtime)1128         public void init(long uptime, long realtime) {
1129             mRealtime = 0;
1130             mUptime = 0;
1131             mPastUptime = 0;
1132             mPastRealtime = 0;
1133             mUptimeStart = uptime;
1134             mRealtimeStart = realtime;
1135             mUnpluggedUptime = getUptime(mUptimeStart);
1136             mUnpluggedRealtime = getRealtime(mRealtimeStart);
1137         }
1138 
reset(long uptime, long realtime)1139         public void reset(long uptime, long realtime) {
1140             if (!mRunning) {
1141                 mPastUptime = 0;
1142                 mPastRealtime = 0;
1143             } else {
1144                 mUptimeStart = uptime;
1145                 mRealtimeStart = realtime;
1146                 // TODO: Since mUptimeStart was just reset and we are running, getUptime will
1147                 // just return mPastUptime. Also, are we sure we don't want to reset that?
1148                 mUnpluggedUptime = getUptime(uptime);
1149                 // TODO: likewise.
1150                 mUnpluggedRealtime = getRealtime(realtime);
1151             }
1152         }
1153 
computeUptime(long curTime, int which)1154         public long computeUptime(long curTime, int which) {
1155             switch (which) {
1156                 case STATS_SINCE_CHARGED:
1157                     return mUptime + getUptime(curTime);
1158                 case STATS_CURRENT:
1159                     return getUptime(curTime);
1160                 case STATS_SINCE_UNPLUGGED:
1161                     return getUptime(curTime) - mUnpluggedUptime;
1162             }
1163             return 0;
1164         }
1165 
computeRealtime(long curTime, int which)1166         public long computeRealtime(long curTime, int which) {
1167             switch (which) {
1168                 case STATS_SINCE_CHARGED:
1169                     return mRealtime + getRealtime(curTime);
1170                 case STATS_CURRENT:
1171                     return getRealtime(curTime);
1172                 case STATS_SINCE_UNPLUGGED:
1173                     return getRealtime(curTime) - mUnpluggedRealtime;
1174             }
1175             return 0;
1176         }
1177 
getUptime(long curTime)1178         public long getUptime(long curTime) {
1179             long time = mPastUptime;
1180             if (mRunning) {
1181                 time += curTime - mUptimeStart;
1182             }
1183             return time;
1184         }
1185 
getRealtime(long curTime)1186         public long getRealtime(long curTime) {
1187             long time = mPastRealtime;
1188             if (mRunning) {
1189                 time += curTime - mRealtimeStart;
1190             }
1191             return time;
1192         }
1193 
getUptimeStart()1194         public long getUptimeStart() {
1195             return mUptimeStart;
1196         }
1197 
getRealtimeStart()1198         public long getRealtimeStart() {
1199             return mRealtimeStart;
1200         }
1201 
isRunning()1202         public boolean isRunning() {
1203             return mRunning;
1204         }
1205 
setRunning(boolean running, long uptime, long realtime)1206         public boolean setRunning(boolean running, long uptime, long realtime) {
1207             if (mRunning != running) {
1208                 mRunning = running;
1209                 if (running) {
1210                     mUptimeStart = uptime;
1211                     mRealtimeStart = realtime;
1212                     long batteryUptime = mUnpluggedUptime = getUptime(uptime);
1213                     long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
1214 
1215                     for (int i = mObservers.size() - 1; i >= 0; i--) {
1216                         mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime);
1217                     }
1218                 } else {
1219                     mPastUptime += uptime - mUptimeStart;
1220                     mPastRealtime += realtime - mRealtimeStart;
1221 
1222                     long batteryUptime = getUptime(uptime);
1223                     long batteryRealtime = getRealtime(realtime);
1224 
1225                     for (int i = mObservers.size() - 1; i >= 0; i--) {
1226                         mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime);
1227                     }
1228                 }
1229                 return true;
1230             }
1231             return false;
1232         }
1233 
readSummaryFromParcel(Parcel in)1234         public void readSummaryFromParcel(Parcel in) {
1235             mUptime = in.readLong();
1236             mRealtime = in.readLong();
1237         }
1238 
writeSummaryToParcel(Parcel out, long uptime, long realtime)1239         public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
1240             out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
1241             out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
1242         }
1243 
readFromParcel(Parcel in)1244         public void readFromParcel(Parcel in) {
1245             mRunning = false;
1246             mUptime = in.readLong();
1247             mPastUptime = in.readLong();
1248             mUptimeStart = in.readLong();
1249             mRealtime = in.readLong();
1250             mPastRealtime = in.readLong();
1251             mRealtimeStart = in.readLong();
1252             mUnpluggedUptime = in.readLong();
1253             mUnpluggedRealtime = in.readLong();
1254         }
1255 
writeToParcel(Parcel out, long uptime, long realtime)1256         public void writeToParcel(Parcel out, long uptime, long realtime) {
1257             final long runningUptime = getUptime(uptime);
1258             final long runningRealtime = getRealtime(realtime);
1259             out.writeLong(mUptime);
1260             out.writeLong(runningUptime);
1261             out.writeLong(mUptimeStart);
1262             out.writeLong(mRealtime);
1263             out.writeLong(runningRealtime);
1264             out.writeLong(mRealtimeStart);
1265             out.writeLong(mUnpluggedUptime);
1266             out.writeLong(mUnpluggedRealtime);
1267         }
1268     }
1269 
1270     /**
1271      * State for keeping track of counting information.
1272      */
1273     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
1274         final AtomicInteger mCount = new AtomicInteger();
1275         final TimeBase mTimeBase;
1276         int mLoadedCount;
1277         int mUnpluggedCount;
1278         int mPluggedCount;
1279 
Counter(TimeBase timeBase, Parcel in)1280         public Counter(TimeBase timeBase, Parcel in) {
1281             mTimeBase = timeBase;
1282             mPluggedCount = in.readInt();
1283             mCount.set(mPluggedCount);
1284             mLoadedCount = in.readInt();
1285             mUnpluggedCount = in.readInt();
1286             timeBase.add(this);
1287         }
1288 
Counter(TimeBase timeBase)1289         public Counter(TimeBase timeBase) {
1290             mTimeBase = timeBase;
1291             timeBase.add(this);
1292         }
1293 
writeToParcel(Parcel out)1294         public void writeToParcel(Parcel out) {
1295             out.writeInt(mCount.get());
1296             out.writeInt(mLoadedCount);
1297             out.writeInt(mUnpluggedCount);
1298         }
1299 
1300         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1301         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1302             mUnpluggedCount = mPluggedCount;
1303         }
1304 
1305         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1306         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1307             mPluggedCount = mCount.get();
1308         }
1309 
1310         /**
1311          * Writes a possibly null Counter to a Parcel.
1312          *
1313          * @param out the Parcel to be written to.
1314          * @param counter a Counter, or null.
1315          */
writeCounterToParcel(Parcel out, @Nullable Counter counter)1316         public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
1317             if (counter == null) {
1318                 out.writeInt(0); // indicates null
1319                 return;
1320             }
1321             out.writeInt(1); // indicates non-null
1322 
1323             counter.writeToParcel(out);
1324         }
1325 
1326         /**
1327          * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
1328          * @param timeBase the timebase to assign to the Counter
1329          * @param in the parcel to read from
1330          * @return the Counter or null.
1331          */
readCounterFromParcel(TimeBase timeBase, Parcel in)1332         public static @Nullable Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
1333             if (in.readInt() == 0) {
1334                 return null;
1335             }
1336             return new Counter(timeBase, in);
1337         }
1338 
1339         @Override
getCountLocked(int which)1340         public int getCountLocked(int which) {
1341             int val = mCount.get();
1342             if (which == STATS_SINCE_UNPLUGGED) {
1343                 val -= mUnpluggedCount;
1344             } else if (which != STATS_SINCE_CHARGED) {
1345                 val -= mLoadedCount;
1346             }
1347 
1348             return val;
1349         }
1350 
logState(Printer pw, String prefix)1351         public void logState(Printer pw, String prefix) {
1352             pw.println(prefix + "mCount=" + mCount.get()
1353                     + " mLoadedCount=" + mLoadedCount
1354                     + " mUnpluggedCount=" + mUnpluggedCount
1355                     + " mPluggedCount=" + mPluggedCount);
1356         }
1357 
1358         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()1359         public void stepAtomic() {
1360             if (mTimeBase.isRunning()) {
1361                 mCount.incrementAndGet();
1362             }
1363         }
1364 
addAtomic(int delta)1365         void addAtomic(int delta) {
1366             if (mTimeBase.isRunning()) {
1367                 mCount.addAndGet(delta);
1368             }
1369         }
1370 
1371         /**
1372          * Clear state of this counter.
1373          */
reset(boolean detachIfReset)1374         void reset(boolean detachIfReset) {
1375             mCount.set(0);
1376             mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
1377             if (detachIfReset) {
1378                 detach();
1379             }
1380         }
1381 
detach()1382         void detach() {
1383             mTimeBase.remove(this);
1384         }
1385 
1386         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)1387         public void writeSummaryFromParcelLocked(Parcel out) {
1388             int count = mCount.get();
1389             out.writeInt(count);
1390         }
1391 
1392         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)1393         public void readSummaryFromParcelLocked(Parcel in) {
1394             mLoadedCount = in.readInt();
1395             mCount.set(mLoadedCount);
1396             mUnpluggedCount = mPluggedCount = mLoadedCount;
1397         }
1398     }
1399 
1400     @VisibleForTesting
1401     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
1402         final TimeBase mTimeBase;
1403         public long[] mCounts;
1404         public long[] mLoadedCounts;
1405         public long[] mUnpluggedCounts;
1406 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)1407         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
1408             mTimeBase = timeBase;
1409             mCounts = in.createLongArray();
1410             mLoadedCounts = in.createLongArray();
1411             mUnpluggedCounts = in.createLongArray();
1412             timeBase.add(this);
1413         }
1414 
LongSamplingCounterArray(TimeBase timeBase)1415         public LongSamplingCounterArray(TimeBase timeBase) {
1416             mTimeBase = timeBase;
1417             timeBase.add(this);
1418         }
1419 
writeToParcel(Parcel out)1420         private void writeToParcel(Parcel out) {
1421             out.writeLongArray(mCounts);
1422             out.writeLongArray(mLoadedCounts);
1423             out.writeLongArray(mUnpluggedCounts);
1424         }
1425 
1426         @Override
onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime)1427         public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
1428             mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
1429         }
1430 
1431         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1432         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1433         }
1434 
1435         @Override
getCountsLocked(int which)1436         public long[] getCountsLocked(int which) {
1437             long[] val = copyArray(mCounts, null);
1438             if (which == STATS_SINCE_UNPLUGGED) {
1439                 subtract(val, mUnpluggedCounts);
1440             } else if (which != STATS_SINCE_CHARGED) {
1441                 subtract(val, mLoadedCounts);
1442             }
1443             return val;
1444         }
1445 
1446         @Override
logState(Printer pw, String prefix)1447         public void logState(Printer pw, String prefix) {
1448             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts)
1449                     + " mLoadedCounts=" + Arrays.toString(mLoadedCounts)
1450                     + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts));
1451         }
1452 
addCountLocked(long[] counts)1453         public void addCountLocked(long[] counts) {
1454             addCountLocked(counts, mTimeBase.isRunning());
1455         }
1456 
addCountLocked(long[] counts, boolean isRunning)1457         public void addCountLocked(long[] counts, boolean isRunning) {
1458             if (counts == null) {
1459                 return;
1460             }
1461             if (isRunning) {
1462                 if (mCounts == null) {
1463                     mCounts = new long[counts.length];
1464                 }
1465                 for (int i = 0; i < counts.length; ++i) {
1466                     mCounts[i] += counts[i];
1467                 }
1468             }
1469         }
1470 
getSize()1471         public int getSize() {
1472             return mCounts == null ? 0 : mCounts.length;
1473         }
1474 
1475         /**
1476          * Clear state of this counter.
1477          */
reset(boolean detachIfReset)1478         public void reset(boolean detachIfReset) {
1479             fillArray(mCounts, 0);
1480             fillArray(mLoadedCounts, 0);
1481             fillArray(mUnpluggedCounts, 0);
1482             if (detachIfReset) {
1483                 detach();
1484             }
1485         }
1486 
detach()1487         public void detach() {
1488             mTimeBase.remove(this);
1489         }
1490 
writeSummaryToParcelLocked(Parcel out)1491         private void writeSummaryToParcelLocked(Parcel out) {
1492             out.writeLongArray(mCounts);
1493         }
1494 
readSummaryFromParcelLocked(Parcel in)1495         private void readSummaryFromParcelLocked(Parcel in) {
1496             mCounts = in.createLongArray();
1497             mLoadedCounts = copyArray(mCounts, mLoadedCounts);
1498             mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
1499         }
1500 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)1501         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
1502             if (counterArray != null) {
1503                 out.writeInt(1);
1504                 counterArray.writeToParcel(out);
1505             } else {
1506                 out.writeInt(0);
1507             }
1508         }
1509 
readFromParcel(Parcel in, TimeBase timeBase)1510         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
1511             if (in.readInt() != 0) {
1512                 return new LongSamplingCounterArray(timeBase, in);
1513             } else {
1514                 return null;
1515             }
1516         }
1517 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)1518         public static void writeSummaryToParcelLocked(Parcel out,
1519                 LongSamplingCounterArray counterArray) {
1520             if (counterArray != null) {
1521                 out.writeInt(1);
1522                 counterArray.writeSummaryToParcelLocked(out);
1523             } else {
1524                 out.writeInt(0);
1525             }
1526         }
1527 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)1528         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
1529                 TimeBase timeBase) {
1530             if (in.readInt() != 0) {
1531                 final LongSamplingCounterArray counterArray
1532                         = new LongSamplingCounterArray(timeBase);
1533                 counterArray.readSummaryFromParcelLocked(in);
1534                 return counterArray;
1535             } else {
1536                 return null;
1537             }
1538         }
1539 
fillArray(long[] a, long val)1540         private static void fillArray(long[] a, long val) {
1541             if (a != null) {
1542                 Arrays.fill(a, val);
1543             }
1544         }
1545 
subtract(@onNull long[] val, long[] toSubtract)1546         private static void subtract(@NonNull long[] val, long[] toSubtract) {
1547             if (toSubtract == null) {
1548                 return;
1549             }
1550             for (int i = 0; i < val.length; i++) {
1551                 val[i] -= toSubtract[i];
1552             }
1553         }
1554 
copyArray(long[] src, long[] dest)1555         private static long[] copyArray(long[] src, long[] dest) {
1556             if (src == null) {
1557                 return null;
1558             } else {
1559                 if (dest == null) {
1560                     dest = new long[src.length];
1561                 }
1562                 System.arraycopy(src, 0, dest, 0, src.length);
1563                 return dest;
1564             }
1565         }
1566     }
1567 
1568     @VisibleForTesting
1569     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
1570         final TimeBase mTimeBase;
1571         public long mCount;
1572         public long mCurrentCount;
1573         public long mLoadedCount;
1574         public long mUnpluggedCount;
1575 
LongSamplingCounter(TimeBase timeBase, Parcel in)1576         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
1577             mTimeBase = timeBase;
1578             mCount = in.readLong();
1579             mCurrentCount = in.readLong();
1580             mLoadedCount = in.readLong();
1581             mUnpluggedCount = in.readLong();
1582             timeBase.add(this);
1583         }
1584 
LongSamplingCounter(TimeBase timeBase)1585         public LongSamplingCounter(TimeBase timeBase) {
1586             mTimeBase = timeBase;
1587             timeBase.add(this);
1588         }
1589 
writeToParcel(Parcel out)1590         public void writeToParcel(Parcel out) {
1591             out.writeLong(mCount);
1592             out.writeLong(mCurrentCount);
1593             out.writeLong(mLoadedCount);
1594             out.writeLong(mUnpluggedCount);
1595         }
1596 
1597         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1598         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1599             mUnpluggedCount = mCount;
1600         }
1601 
1602         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1603         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1604         }
1605 
getCountLocked(int which)1606         public long getCountLocked(int which) {
1607             long val = mCount;
1608             if (which == STATS_SINCE_UNPLUGGED) {
1609                 val -= mUnpluggedCount;
1610             } else if (which != STATS_SINCE_CHARGED) {
1611                 val -= mLoadedCount;
1612             }
1613             return val;
1614         }
1615 
1616         @Override
logState(Printer pw, String prefix)1617         public void logState(Printer pw, String prefix) {
1618             pw.println(prefix + "mCount=" + mCount
1619                     + " mCurrentCount=" + mCurrentCount
1620                     + " mLoadedCount=" + mLoadedCount
1621                     + " mUnpluggedCount=" + mUnpluggedCount);
1622         }
1623 
addCountLocked(long count)1624         public void addCountLocked(long count) {
1625             update(mCurrentCount + count, mTimeBase.isRunning());
1626         }
1627 
addCountLocked(long count, boolean isRunning)1628         public void addCountLocked(long count, boolean isRunning) {
1629             update(mCurrentCount + count, isRunning);
1630         }
1631 
update(long count)1632         public void update(long count) {
1633             update(count, mTimeBase.isRunning());
1634         }
1635 
update(long count, boolean isRunning)1636         public void update(long count, boolean isRunning) {
1637             if (count < mCurrentCount) {
1638                 mCurrentCount = 0;
1639             }
1640             if (isRunning) {
1641                 mCount += count - mCurrentCount;
1642             }
1643             mCurrentCount = count;
1644         }
1645 
1646         /**
1647          * Clear state of this counter.
1648          */
reset(boolean detachIfReset)1649         public void reset(boolean detachIfReset) {
1650             mCount = 0;
1651             mLoadedCount = mUnpluggedCount = 0;
1652             if (detachIfReset) {
1653                 detach();
1654             }
1655         }
1656 
detach()1657         public void detach() {
1658             mTimeBase.remove(this);
1659         }
1660 
writeSummaryFromParcelLocked(Parcel out)1661         public void writeSummaryFromParcelLocked(Parcel out) {
1662             out.writeLong(mCount);
1663         }
1664 
readSummaryFromParcelLocked(Parcel in)1665         public void readSummaryFromParcelLocked(Parcel in) {
1666             mCount = mUnpluggedCount= mLoadedCount = in.readLong();
1667         }
1668     }
1669 
1670     /**
1671      * State for keeping track of timing information.
1672      */
1673     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
1674         protected final Clocks mClocks;
1675         protected final int mType;
1676         protected final TimeBase mTimeBase;
1677 
1678         protected int mCount;
1679         protected int mLoadedCount;
1680         protected int mLastCount;
1681         protected int mUnpluggedCount;
1682 
1683         // Times are in microseconds for better accuracy when dividing by the
1684         // lock count, and are in "battery realtime" units.
1685 
1686         /**
1687          * The total time we have accumulated since the start of the original
1688          * boot, to the last time something interesting happened in the
1689          * current run.
1690          */
1691         protected long mTotalTime;
1692 
1693         /**
1694          * The total time we loaded for the previous runs.  Subtract this from
1695          * mTotalTime to find the time for the current run of the system.
1696          */
1697         protected long mLoadedTime;
1698 
1699         /**
1700          * The run time of the last run of the system, as loaded from the
1701          * saved data.
1702          */
1703         protected long mLastTime;
1704 
1705         /**
1706          * The value of mTotalTime when unplug() was last called.  Subtract
1707          * this from mTotalTime to find the time since the last unplug from
1708          * power.
1709          */
1710         protected long mUnpluggedTime;
1711 
1712         /**
1713          * The total time this timer has been running until the latest mark has been set.
1714          * Subtract this from mTotalTime to get the time spent running since the mark was set.
1715          */
1716         protected long mTimeBeforeMark;
1717 
1718         /**
1719          * Constructs from a parcel.
1720          * @param type
1721          * @param timeBase
1722          * @param in
1723          */
Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in)1724         public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
1725             mClocks = clocks;
1726             mType = type;
1727             mTimeBase = timeBase;
1728 
1729             mCount = in.readInt();
1730             mLoadedCount = in.readInt();
1731             mLastCount = 0;
1732             mUnpluggedCount = in.readInt();
1733             mTotalTime = in.readLong();
1734             mLoadedTime = in.readLong();
1735             mLastTime = 0;
1736             mUnpluggedTime = in.readLong();
1737             mTimeBeforeMark = in.readLong();
1738             timeBase.add(this);
1739             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
1740         }
1741 
Timer(Clocks clocks, int type, TimeBase timeBase)1742         public Timer(Clocks clocks, int type, TimeBase timeBase) {
1743             mClocks = clocks;
1744             mType = type;
1745             mTimeBase = timeBase;
1746             timeBase.add(this);
1747         }
1748 
computeRunTimeLocked(long curBatteryRealtime)1749         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
1750 
computeCurrentCountLocked()1751         protected abstract int computeCurrentCountLocked();
1752 
1753         /**
1754          * Clear state of this timer.  Returns true if the timer is inactive
1755          * so can be completely dropped.
1756          */
reset(boolean detachIfReset)1757         public boolean reset(boolean detachIfReset) {
1758             mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0;
1759             mCount = mLoadedCount = mLastCount = 0;
1760             if (detachIfReset) {
1761                 detach();
1762             }
1763             return true;
1764         }
1765 
detach()1766         public void detach() {
1767             mTimeBase.remove(this);
1768         }
1769 
writeToParcel(Parcel out, long elapsedRealtimeUs)1770         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1771             if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
1772                     + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1773             out.writeInt(computeCurrentCountLocked());
1774             out.writeInt(mLoadedCount);
1775             out.writeInt(mUnpluggedCount);
1776             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1777             out.writeLong(mLoadedTime);
1778             out.writeLong(mUnpluggedTime);
1779             out.writeLong(mTimeBeforeMark);
1780         }
1781 
1782         @Override
onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime)1783         public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
1784             if (DEBUG && mType < 0) {
1785                 Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime
1786                         + " old mUnpluggedTime=" + mUnpluggedTime
1787                         + " old mUnpluggedCount=" + mUnpluggedCount);
1788             }
1789             mUnpluggedTime = computeRunTimeLocked(baseRealtime);
1790             mUnpluggedCount = computeCurrentCountLocked();
1791             if (DEBUG && mType < 0) {
1792                 Log.v(TAG, "unplug #" + mType
1793                         + ": new mUnpluggedTime=" + mUnpluggedTime
1794                         + " new mUnpluggedCount=" + mUnpluggedCount);
1795             }
1796         }
1797 
1798         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1799         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1800             if (DEBUG && mType < 0) {
1801                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
1802                         + " old mTotalTime=" + mTotalTime);
1803             }
1804             mTotalTime = computeRunTimeLocked(baseRealtime);
1805             mCount = computeCurrentCountLocked();
1806             if (DEBUG && mType < 0) {
1807                 Log.v(TAG, "plug #" + mType
1808                         + ": new mTotalTime=" + mTotalTime);
1809             }
1810         }
1811 
1812         /**
1813          * Writes a possibly null Timer to a Parcel.
1814          *
1815          * @param out the Parcel to be written to.
1816          * @param timer a Timer, or null.
1817          */
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)1818         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
1819             if (timer == null) {
1820                 out.writeInt(0); // indicates null
1821                 return;
1822             }
1823             out.writeInt(1); // indicates non-null
1824 
1825             timer.writeToParcel(out, elapsedRealtimeUs);
1826         }
1827 
1828         @Override
getTotalTimeLocked(long elapsedRealtimeUs, int which)1829         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
1830             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1831             if (which == STATS_SINCE_UNPLUGGED) {
1832                 val -= mUnpluggedTime;
1833             } else if (which != STATS_SINCE_CHARGED) {
1834                 val -= mLoadedTime;
1835             }
1836 
1837             return val;
1838         }
1839 
1840         @Override
getCountLocked(int which)1841         public int getCountLocked(int which) {
1842             int val = computeCurrentCountLocked();
1843             if (which == STATS_SINCE_UNPLUGGED) {
1844                 val -= mUnpluggedCount;
1845             } else if (which != STATS_SINCE_CHARGED) {
1846                 val -= mLoadedCount;
1847             }
1848 
1849             return val;
1850         }
1851 
1852         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)1853         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
1854             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1855             return val - mTimeBeforeMark;
1856         }
1857 
1858         @Override
logState(Printer pw, String prefix)1859         public void logState(Printer pw, String prefix) {
1860             pw.println(prefix + "mCount=" + mCount
1861                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
1862                     + " mUnpluggedCount=" + mUnpluggedCount);
1863             pw.println(prefix + "mTotalTime=" + mTotalTime
1864                     + " mLoadedTime=" + mLoadedTime);
1865             pw.println(prefix + "mLastTime=" + mLastTime
1866                     + " mUnpluggedTime=" + mUnpluggedTime);
1867         }
1868 
1869 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)1870         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1871             long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1872             out.writeLong(runTime);
1873             out.writeInt(computeCurrentCountLocked());
1874         }
1875 
readSummaryFromParcelLocked(Parcel in)1876         public void readSummaryFromParcelLocked(Parcel in) {
1877             // Multiply by 1000 for backwards compatibility
1878             mTotalTime = mLoadedTime = in.readLong();
1879             mLastTime = 0;
1880             mUnpluggedTime = mTotalTime;
1881             mCount = mLoadedCount = in.readInt();
1882             mLastCount = 0;
1883             mUnpluggedCount = mCount;
1884 
1885             // When reading the summary, we set the mark to be the latest information.
1886             mTimeBeforeMark = mTotalTime;
1887         }
1888     }
1889 
1890     /**
1891      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
1892      * method. The state of the timer according to its {@link TimeBase} will determine how much
1893      * of the value is recorded.
1894      *
1895      * If the value being recorded resets, {@link #endSample()} can be called in order to
1896      * account for the change. If the value passed in to {@link #update(long, int)} decreased
1897      * between calls, the {@link #endSample()} is automatically called and the new value is
1898      * expected to increase monotonically from that point on.
1899      */
1900     public static class SamplingTimer extends Timer {
1901 
1902         /**
1903          * The most recent reported count from /proc/wakelocks.
1904          */
1905         int mCurrentReportedCount;
1906 
1907         /**
1908          * The reported count from /proc/wakelocks when unplug() was last
1909          * called.
1910          */
1911         int mUnpluggedReportedCount;
1912 
1913         /**
1914          * The most recent reported total_time from /proc/wakelocks.
1915          */
1916         long mCurrentReportedTotalTime;
1917 
1918 
1919         /**
1920          * The reported total_time from /proc/wakelocks when unplug() was last
1921          * called.
1922          */
1923         long mUnpluggedReportedTotalTime;
1924 
1925         /**
1926          * Whether we are currently in a discharge cycle.
1927          */
1928         boolean mTimeBaseRunning;
1929 
1930         /**
1931          * Whether we are currently recording reported values.
1932          */
1933         boolean mTrackingReportedValues;
1934 
1935         /*
1936          * A sequence counter, incremented once for each update of the stats.
1937          */
1938         int mUpdateVersion;
1939 
1940         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in)1941         public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
1942             super(clocks, 0, timeBase, in);
1943             mCurrentReportedCount = in.readInt();
1944             mUnpluggedReportedCount = in.readInt();
1945             mCurrentReportedTotalTime = in.readLong();
1946             mUnpluggedReportedTotalTime = in.readLong();
1947             mTrackingReportedValues = in.readInt() == 1;
1948             mTimeBaseRunning = timeBase.isRunning();
1949         }
1950 
1951         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase)1952         public SamplingTimer(Clocks clocks, TimeBase timeBase) {
1953             super(clocks, 0, timeBase);
1954             mTrackingReportedValues = false;
1955             mTimeBaseRunning = timeBase.isRunning();
1956         }
1957 
1958         /**
1959          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
1960          * be less than the values used for a previous invocation.
1961          */
endSample()1962         public void endSample() {
1963             mTotalTime = computeRunTimeLocked(0 /* unused by us */);
1964             mCount = computeCurrentCountLocked();
1965             mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
1966             mUnpluggedReportedCount = mCurrentReportedCount = 0;
1967         }
1968 
setUpdateVersion(int version)1969         public void setUpdateVersion(int version) {
1970             mUpdateVersion = version;
1971         }
1972 
getUpdateVersion()1973         public int getUpdateVersion() {
1974             return mUpdateVersion;
1975         }
1976 
1977         /**
1978          * Updates the current recorded values. These are meant to be monotonically increasing
1979          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
1980          *
1981          * If the values being recorded have been reset, the monotonically increasing requirement
1982          * will be broken. In this case, {@link #endSample()} is automatically called and
1983          * the total value of totalTime and count are recorded, starting a new monotonically
1984          * increasing sample.
1985          *
1986          * @param totalTime total time of sample in microseconds.
1987          * @param count total number of times the event being sampled occurred.
1988          */
update(long totalTime, int count)1989         public void update(long totalTime, int count) {
1990             if (mTimeBaseRunning && !mTrackingReportedValues) {
1991                 // Updating the reported value for the first time.
1992                 mUnpluggedReportedTotalTime = totalTime;
1993                 mUnpluggedReportedCount = count;
1994             }
1995 
1996             mTrackingReportedValues = true;
1997 
1998             if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) {
1999                 endSample();
2000             }
2001 
2002             mCurrentReportedTotalTime = totalTime;
2003             mCurrentReportedCount = count;
2004         }
2005 
2006         /**
2007          * Adds deltaTime and deltaCount to the current sample.
2008          *
2009          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
2010          * @param deltaCount additional number of times the event being sampled occurred.
2011          */
add(long deltaTime, int deltaCount)2012         public void add(long deltaTime, int deltaCount) {
2013             update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount);
2014         }
2015 
2016         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)2017         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
2018             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
2019             if (mTrackingReportedValues) {
2020                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
2021                 mUnpluggedReportedCount = mCurrentReportedCount;
2022             }
2023             mTimeBaseRunning = true;
2024         }
2025 
2026         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)2027         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2028             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2029             mTimeBaseRunning = false;
2030         }
2031 
2032         @Override
logState(Printer pw, String prefix)2033         public void logState(Printer pw, String prefix) {
2034             super.logState(pw, prefix);
2035             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
2036                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
2037                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
2038                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
2039         }
2040 
2041         @Override
computeRunTimeLocked(long curBatteryRealtime)2042         protected long computeRunTimeLocked(long curBatteryRealtime) {
2043             return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
2044                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
2045         }
2046 
2047         @Override
computeCurrentCountLocked()2048         protected int computeCurrentCountLocked() {
2049             return mCount + (mTimeBaseRunning && mTrackingReportedValues
2050                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
2051         }
2052 
2053         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2054         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2055             super.writeToParcel(out, elapsedRealtimeUs);
2056             out.writeInt(mCurrentReportedCount);
2057             out.writeInt(mUnpluggedReportedCount);
2058             out.writeLong(mCurrentReportedTotalTime);
2059             out.writeLong(mUnpluggedReportedTotalTime);
2060             out.writeInt(mTrackingReportedValues ? 1 : 0);
2061         }
2062 
2063         @Override
reset(boolean detachIfReset)2064         public boolean reset(boolean detachIfReset) {
2065             super.reset(detachIfReset);
2066             mTrackingReportedValues = false;
2067             mUnpluggedReportedTotalTime = 0;
2068             mUnpluggedReportedCount = 0;
2069             return true;
2070         }
2071     }
2072 
2073     /**
2074      * A timer that increments in batches.  It does not run for durations, but just jumps
2075      * for a pre-determined amount.
2076      */
2077     public static class BatchTimer extends Timer {
2078         final Uid mUid;
2079 
2080         /**
2081          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
2082          */
2083         long mLastAddedTime;
2084 
2085         /**
2086          * The last duration that we added to the timer.  This is in microseconds.
2087          */
2088         long mLastAddedDuration;
2089 
2090         /**
2091          * Whether we are currently in a discharge cycle.
2092          */
2093         boolean mInDischarge;
2094 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in)2095         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
2096             super(clocks, type, timeBase, in);
2097             mUid = uid;
2098             mLastAddedTime = in.readLong();
2099             mLastAddedDuration = in.readLong();
2100             mInDischarge = timeBase.isRunning();
2101         }
2102 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase)2103         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
2104             super(clocks, type, timeBase);
2105             mUid = uid;
2106             mInDischarge = timeBase.isRunning();
2107         }
2108 
2109         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2110         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2111             super.writeToParcel(out, elapsedRealtimeUs);
2112             out.writeLong(mLastAddedTime);
2113             out.writeLong(mLastAddedDuration);
2114         }
2115 
2116         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)2117         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2118             recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
2119             mInDischarge = false;
2120             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2121         }
2122 
2123         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)2124         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
2125             recomputeLastDuration(elapsedRealtime, false);
2126             mInDischarge = true;
2127             // If we are still within the last added duration, then re-added whatever remains.
2128             if (mLastAddedTime == elapsedRealtime) {
2129                 mTotalTime += mLastAddedDuration;
2130             }
2131             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
2132         }
2133 
2134         @Override
logState(Printer pw, String prefix)2135         public void logState(Printer pw, String prefix) {
2136             super.logState(pw, prefix);
2137             pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
2138                     + " mLastAddedDuration=" + mLastAddedDuration);
2139         }
2140 
computeOverage(long curTime)2141         private long computeOverage(long curTime) {
2142             if (mLastAddedTime > 0) {
2143                 return mLastTime + mLastAddedDuration - curTime;
2144             }
2145             return 0;
2146         }
2147 
recomputeLastDuration(long curTime, boolean abort)2148         private void recomputeLastDuration(long curTime, boolean abort) {
2149             final long overage = computeOverage(curTime);
2150             if (overage > 0) {
2151                 // Aborting before the duration ran out -- roll back the remaining
2152                 // duration.  Only do this if currently discharging; otherwise we didn't
2153                 // actually add the time.
2154                 if (mInDischarge) {
2155                     mTotalTime -= overage;
2156                 }
2157                 if (abort) {
2158                     mLastAddedTime = 0;
2159                 } else {
2160                     mLastAddedTime = curTime;
2161                     mLastAddedDuration -= overage;
2162                 }
2163             }
2164         }
2165 
addDuration(BatteryStatsImpl stats, long durationMillis)2166         public void addDuration(BatteryStatsImpl stats, long durationMillis) {
2167             final long now = mClocks.elapsedRealtime() * 1000;
2168             recomputeLastDuration(now, true);
2169             mLastAddedTime = now;
2170             mLastAddedDuration = durationMillis * 1000;
2171             if (mInDischarge) {
2172                 mTotalTime += mLastAddedDuration;
2173                 mCount++;
2174             }
2175         }
2176 
abortLastDuration(BatteryStatsImpl stats)2177         public void abortLastDuration(BatteryStatsImpl stats) {
2178             final long now = mClocks.elapsedRealtime() * 1000;
2179             recomputeLastDuration(now, true);
2180         }
2181 
2182         @Override
computeCurrentCountLocked()2183         protected int computeCurrentCountLocked() {
2184             return mCount;
2185         }
2186 
2187         @Override
computeRunTimeLocked(long curBatteryRealtime)2188         protected long computeRunTimeLocked(long curBatteryRealtime) {
2189             final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
2190             if (overage > 0) {
2191                 return mTotalTime = overage;
2192             }
2193             return mTotalTime;
2194         }
2195 
2196         @Override
reset(boolean detachIfReset)2197         public boolean reset(boolean detachIfReset) {
2198             final long now = mClocks.elapsedRealtime() * 1000;
2199             recomputeLastDuration(now, true);
2200             boolean stillActive = mLastAddedTime == now;
2201             super.reset(!stillActive && detachIfReset);
2202             return !stillActive;
2203         }
2204     }
2205 
2206 
2207     /**
2208      * A StopwatchTimer that also tracks the total and max individual
2209      * time spent active according to the given timebase.  Whereas
2210      * StopwatchTimer apportions the time amongst all in the pool,
2211      * the total and max durations are not apportioned.
2212      */
2213     public static class DurationTimer extends StopwatchTimer {
2214         /**
2215          * The time (in ms) that the timer was last acquired or the time base
2216          * last (re-)started. Increasing the nesting depth does not reset this time.
2217          *
2218          * -1 if the timer is currently not running or the time base is not running.
2219          *
2220          * If written to a parcel, the start time is reset, as is mNesting in the base class
2221          * StopwatchTimer.
2222          */
2223         long mStartTimeMs = -1;
2224 
2225         /**
2226          * The longest time period (in ms) that the timer has been active. Not pooled.
2227          */
2228         long mMaxDurationMs;
2229 
2230         /**
2231          * The time (in ms) that that the timer has been active since most recent
2232          * stopRunningLocked() or reset(). Not pooled.
2233          */
2234         long mCurrentDurationMs;
2235 
2236         /**
2237          * The total time (in ms) that that the timer has been active since most recent reset()
2238          * prior to the current startRunningLocked. This is the sum of all past currentDurations
2239          * (but not including the present currentDuration) since reset. Not pooled.
2240          */
2241         long mTotalDurationMs;
2242 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2243         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2244                 TimeBase timeBase, Parcel in) {
2245             super(clocks, uid, type, timerPool, timeBase, in);
2246             mMaxDurationMs = in.readLong();
2247             mTotalDurationMs = in.readLong();
2248             mCurrentDurationMs = in.readLong();
2249         }
2250 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2251         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2252                 TimeBase timeBase) {
2253             super(clocks, uid, type, timerPool, timeBase);
2254         }
2255 
2256         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2257         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2258             super.writeToParcel(out, elapsedRealtimeUs);
2259             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2260             out.writeLong(mTotalDurationMs);
2261             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
2262         }
2263 
2264         /**
2265          * Write the summary to the parcel.
2266          *
2267          * Since the time base is probably meaningless after we come back, reading
2268          * from this will have the effect of stopping the timer. So here all we write
2269          * is the max and total durations.
2270          */
2271         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2272         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2273             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2274             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2275             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
2276         }
2277 
2278         /**
2279          * Read the summary parcel.
2280          *
2281          * Has the side effect of stopping the timer.
2282          */
2283         @Override
readSummaryFromParcelLocked(Parcel in)2284         public void readSummaryFromParcelLocked(Parcel in) {
2285             super.readSummaryFromParcelLocked(in);
2286             mMaxDurationMs = in.readLong();
2287             mTotalDurationMs = in.readLong();
2288             mStartTimeMs = -1;
2289             mCurrentDurationMs = 0;
2290         }
2291 
2292         /**
2293          * The TimeBase time started (again).
2294          *
2295          * If the timer is also running, store the start time.
2296          */
onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime)2297         public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
2298             super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
2299             if (mNesting > 0) {
2300                 mStartTimeMs = baseRealtime / 1000;
2301             }
2302         }
2303 
2304         /**
2305          * The TimeBase stopped running.
2306          *
2307          * If the timer is running, add the duration into mCurrentDurationMs.
2308          */
2309         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs)2310         public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) {
2311             super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs);
2312             if (mNesting > 0) {
2313                 // baseRealtimeUs has already been converted to the timebase's realtime.
2314                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
2315             }
2316             mStartTimeMs = -1;
2317         }
2318 
2319         @Override
logState(Printer pw, String prefix)2320         public void logState(Printer pw, String prefix) {
2321             super.logState(pw, prefix);
2322         }
2323 
2324         @Override
startRunningLocked(long elapsedRealtimeMs)2325         public void startRunningLocked(long elapsedRealtimeMs) {
2326             super.startRunningLocked(elapsedRealtimeMs);
2327             if (mNesting == 1 && mTimeBase.isRunning()) {
2328                 // Just started
2329                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
2330             }
2331         }
2332 
2333         /**
2334          * Decrements the mNesting ref-count on this timer.
2335          *
2336          * If it actually stopped (mNesting went to 0), then possibly update
2337          * mMaxDuration if the current duration was the longest ever.
2338          */
2339         @Override
stopRunningLocked(long elapsedRealtimeMs)2340         public void stopRunningLocked(long elapsedRealtimeMs) {
2341             if (mNesting == 1) {
2342                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2343                 mTotalDurationMs += durationMs;
2344                 if (durationMs > mMaxDurationMs) {
2345                     mMaxDurationMs = durationMs;
2346                 }
2347                 mStartTimeMs = -1;
2348                 mCurrentDurationMs = 0;
2349             }
2350             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
2351             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
2352             super.stopRunningLocked(elapsedRealtimeMs);
2353         }
2354 
2355         @Override
reset(boolean detachIfReset)2356         public boolean reset(boolean detachIfReset) {
2357             boolean result = super.reset(detachIfReset);
2358             mMaxDurationMs = 0;
2359             mTotalDurationMs = 0;
2360             mCurrentDurationMs = 0;
2361             if (mNesting > 0) {
2362                 mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
2363             } else {
2364                 mStartTimeMs = -1;
2365             }
2366             return result;
2367         }
2368 
2369         /**
2370          * Returns the max duration that this timer has ever seen.
2371          *
2372          * Note that this time is NOT split between the timers in the timer group that
2373          * this timer is attached to.  It is the TOTAL time.
2374          */
2375         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)2376         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
2377             if (mNesting > 0) {
2378                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2379                 if (durationMs > mMaxDurationMs) {
2380                     return durationMs;
2381                 }
2382             }
2383             return mMaxDurationMs;
2384         }
2385 
2386         /**
2387          * Returns the time since the timer was started.
2388          * Returns 0 if the timer is not currently running.
2389          *
2390          * Note that this time is NOT split between the timers in the timer group that
2391          * this timer is attached to.  It is the TOTAL time.
2392          *
2393          * Note that if running timer is parceled and unparceled, this method will return
2394          * current duration value at the time of parceling even though timer may not be
2395          * currently running.
2396          */
2397         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)2398         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
2399             long durationMs = mCurrentDurationMs;
2400             if (mNesting > 0 && mTimeBase.isRunning()) {
2401                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000)
2402                         - mStartTimeMs;
2403             }
2404             return durationMs;
2405         }
2406 
2407         /**
2408          * Returns the total cumulative duration that this timer has been on since reset().
2409          * If mTimerPool == null, this should be the same
2410          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
2411          *
2412          * Note that this time is NOT split between the timers in the timer group that
2413          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
2414          * the result will not be equivalent to getTotalTimeLocked.
2415          */
2416         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)2417         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
2418             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
2419         }
2420     }
2421 
2422     /**
2423      * State for keeping track of timing information.
2424      */
2425     public static class StopwatchTimer extends Timer {
2426         final Uid mUid;
2427         final ArrayList<StopwatchTimer> mTimerPool;
2428 
2429         int mNesting;
2430 
2431         /**
2432          * The last time at which we updated the timer.  If mNesting is > 0,
2433          * subtract this from the current battery time to find the amount of
2434          * time we have been running since we last computed an update.
2435          */
2436         long mUpdateTime;
2437 
2438         /**
2439          * The total time at which the timer was acquired, to determine if it
2440          * was actually held for an interesting duration. If time base was not running when timer
2441          * was acquired, will be -1.
2442          */
2443         long mAcquireTime = -1;
2444 
2445         long mTimeout;
2446 
2447         /**
2448          * For partial wake locks, keep track of whether we are in the list
2449          * to consume CPU cycles.
2450          */
2451         @VisibleForTesting
2452         public boolean mInList;
2453 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2454         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2455                 TimeBase timeBase, Parcel in) {
2456             super(clocks, type, timeBase, in);
2457             mUid = uid;
2458             mTimerPool = timerPool;
2459             mUpdateTime = in.readLong();
2460         }
2461 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2462         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2463                 TimeBase timeBase) {
2464             super(clocks, type, timeBase);
2465             mUid = uid;
2466             mTimerPool = timerPool;
2467         }
2468 
setTimeout(long timeout)2469         public void setTimeout(long timeout) {
2470             mTimeout = timeout;
2471         }
2472 
writeToParcel(Parcel out, long elapsedRealtimeUs)2473         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2474             super.writeToParcel(out, elapsedRealtimeUs);
2475             out.writeLong(mUpdateTime);
2476         }
2477 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)2478         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2479             if (mNesting > 0) {
2480                 if (DEBUG && mType < 0) {
2481                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
2482                 }
2483                 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2484                 mUpdateTime = baseRealtime;
2485                 if (DEBUG && mType < 0) {
2486                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
2487                 }
2488             }
2489         }
2490 
logState(Printer pw, String prefix)2491         public void logState(Printer pw, String prefix) {
2492             super.logState(pw, prefix);
2493             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
2494                     + " mAcquireTime=" + mAcquireTime);
2495         }
2496 
startRunningLocked(long elapsedRealtimeMs)2497         public void startRunningLocked(long elapsedRealtimeMs) {
2498             if (mNesting++ == 0) {
2499                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2500                 mUpdateTime = batteryRealtime;
2501                 if (mTimerPool != null) {
2502                     // Accumulate time to all currently active timers before adding
2503                     // this new one to the pool.
2504                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
2505                     // Add this timer to the active pool
2506                     mTimerPool.add(this);
2507                 }
2508                 if (mTimeBase.isRunning()) {
2509                     // Increment the count
2510                     mCount++;
2511                     mAcquireTime = mTotalTime;
2512                 } else {
2513                     mAcquireTime = -1;
2514                 }
2515                 if (DEBUG && mType < 0) {
2516                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
2517                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2518                             + " mAcquireTime=" + mAcquireTime);
2519                 }
2520             }
2521         }
2522 
isRunningLocked()2523         public boolean isRunningLocked() {
2524             return mNesting > 0;
2525         }
2526 
stopRunningLocked(long elapsedRealtimeMs)2527         public void stopRunningLocked(long elapsedRealtimeMs) {
2528             // Ignore attempt to stop a timer that isn't running
2529             if (mNesting == 0) {
2530                 return;
2531             }
2532             if (--mNesting == 0) {
2533                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2534                 if (mTimerPool != null) {
2535                     // Accumulate time to all active counters, scaled by the total
2536                     // active in the pool, before taking this one out of the pool.
2537                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
2538                     // Remove this timer from the active pool
2539                     mTimerPool.remove(this);
2540                 } else {
2541                     mNesting = 1;
2542                     mTotalTime = computeRunTimeLocked(batteryRealtime);
2543                     mNesting = 0;
2544                 }
2545 
2546                 if (DEBUG && mType < 0) {
2547                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
2548                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2549                             + " mAcquireTime=" + mAcquireTime);
2550                 }
2551 
2552                 if (mAcquireTime >= 0 && mTotalTime == mAcquireTime) {
2553                     // If there was no change in the time, then discard this
2554                     // count.  A somewhat cheezy strategy, but hey.
2555                     mCount--;
2556                 }
2557             }
2558         }
2559 
stopAllRunningLocked(long elapsedRealtimeMs)2560         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2561             if (mNesting > 0) {
2562                 mNesting = 1;
2563                 stopRunningLocked(elapsedRealtimeMs);
2564             }
2565         }
2566 
2567         // Update the total time for all other running Timers with the same type as this Timer
2568         // due to a change in timer count
refreshTimersLocked(long batteryRealtime, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)2569         private static long refreshTimersLocked(long batteryRealtime,
2570                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
2571             long selfTime = 0;
2572             final int N = pool.size();
2573             for (int i=N-1; i>= 0; i--) {
2574                 final StopwatchTimer t = pool.get(i);
2575                 long heldTime = batteryRealtime - t.mUpdateTime;
2576                 if (heldTime > 0) {
2577                     final long myTime = heldTime / N;
2578                     if (t == self) {
2579                         selfTime = myTime;
2580                     }
2581                     t.mTotalTime += myTime;
2582                 }
2583                 t.mUpdateTime = batteryRealtime;
2584             }
2585             return selfTime;
2586         }
2587 
2588         @Override
computeRunTimeLocked(long curBatteryRealtime)2589         protected long computeRunTimeLocked(long curBatteryRealtime) {
2590             if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
2591                 curBatteryRealtime = mUpdateTime + mTimeout;
2592             }
2593             return mTotalTime + (mNesting > 0
2594                     ? (curBatteryRealtime - mUpdateTime)
2595                             / (mTimerPool != null ? mTimerPool.size() : 1)
2596                     : 0);
2597         }
2598 
2599         @Override
computeCurrentCountLocked()2600         protected int computeCurrentCountLocked() {
2601             return mCount;
2602         }
2603 
2604         @Override
reset(boolean detachIfReset)2605         public boolean reset(boolean detachIfReset) {
2606             boolean canDetach = mNesting <= 0;
2607             super.reset(canDetach && detachIfReset);
2608             if (mNesting > 0) {
2609                 mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
2610             }
2611             mAcquireTime = -1; // to ensure mCount isn't decreased to -1 if timer is stopped later.
2612             return canDetach;
2613         }
2614 
2615         @Override
detach()2616         public void detach() {
2617             super.detach();
2618             if (mTimerPool != null) {
2619                 mTimerPool.remove(this);
2620             }
2621         }
2622 
2623         @Override
readSummaryFromParcelLocked(Parcel in)2624         public void readSummaryFromParcelLocked(Parcel in) {
2625             super.readSummaryFromParcelLocked(in);
2626             mNesting = 0;
2627         }
2628 
2629         /**
2630          * Set the mark so that we can query later for the total time the timer has
2631          * accumulated since this point. The timer can be running or not.
2632          *
2633          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
2634          */
setMark(long elapsedRealtimeMs)2635         public void setMark(long elapsedRealtimeMs) {
2636             final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2637             if (mNesting > 0) {
2638                 // We are running.
2639                 if (mTimerPool != null) {
2640                     refreshTimersLocked(batteryRealtime, mTimerPool, this);
2641                 } else {
2642                     mTotalTime += batteryRealtime - mUpdateTime;
2643                     mUpdateTime = batteryRealtime;
2644                 }
2645             }
2646             mTimeBeforeMark = mTotalTime;
2647         }
2648     }
2649 
2650     /**
2651      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
2652      * TimeBase is effectively a subset of the other.
2653      */
2654     public static class DualTimer extends DurationTimer {
2655         // This class both is a DurationTimer and also holds a second DurationTimer.
2656         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
2657         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
2658         // STATS_SINCE_CHARGED).
2659         // mSubTimer typically tracks only part of the total time, such as background time, as
2660         // determined by a subTimeBase. It is NOT pooled.
2661         private final DurationTimer mSubTimer;
2662 
2663         /**
2664          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2665          * The main timer (this) is based on the given timeBase and timerPool.
2666          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2667          * the main timer is.
2668          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)2669         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2670                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
2671             super(clocks, uid, type, timerPool, timeBase, in);
2672             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase, in);
2673         }
2674 
2675         /**
2676          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2677          * The main timer (this) is based on the given timeBase and timerPool.
2678          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2679          * the main timer is.
2680          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)2681         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2682                 TimeBase timeBase, TimeBase subTimeBase) {
2683             super(clocks, uid, type, timerPool, timeBase);
2684             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase);
2685         }
2686 
2687         /** Get the secondary timer. */
2688         @Override
getSubTimer()2689         public DurationTimer getSubTimer() {
2690             return mSubTimer;
2691         }
2692 
2693         @Override
startRunningLocked(long elapsedRealtimeMs)2694         public void startRunningLocked(long elapsedRealtimeMs) {
2695             super.startRunningLocked(elapsedRealtimeMs);
2696             mSubTimer.startRunningLocked(elapsedRealtimeMs);
2697         }
2698 
2699         @Override
stopRunningLocked(long elapsedRealtimeMs)2700         public void stopRunningLocked(long elapsedRealtimeMs) {
2701             super.stopRunningLocked(elapsedRealtimeMs);
2702             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
2703         }
2704 
2705         @Override
stopAllRunningLocked(long elapsedRealtimeMs)2706         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2707             super.stopAllRunningLocked(elapsedRealtimeMs);
2708             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
2709         }
2710 
2711         @Override
reset(boolean detachIfReset)2712         public boolean reset(boolean detachIfReset) {
2713             boolean active = false;
2714             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
2715             active |= !mSubTimer.reset(false);
2716             active |= !super.reset(detachIfReset);
2717             return !active;
2718         }
2719 
2720         @Override
detach()2721         public void detach() {
2722             mSubTimer.detach();
2723             super.detach();
2724         }
2725 
2726         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2727         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2728             super.writeToParcel(out, elapsedRealtimeUs);
2729             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
2730         }
2731 
2732         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2733         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2734             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2735             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2736         }
2737 
2738         @Override
readSummaryFromParcelLocked(Parcel in)2739         public void readSummaryFromParcelLocked(Parcel in) {
2740             super.readSummaryFromParcelLocked(in);
2741             mSubTimer.readSummaryFromParcelLocked(in);
2742         }
2743     }
2744 
2745 
2746     public abstract class OverflowArrayMap<T> {
2747         private static final String OVERFLOW_NAME = "*overflow*";
2748 
2749         final int mUid;
2750         final ArrayMap<String, T> mMap = new ArrayMap<>();
2751         T mCurOverflow;
2752         ArrayMap<String, MutableInt> mActiveOverflow;
2753         long mLastOverflowTime;
2754         long mLastOverflowFinishTime;
2755         long mLastClearTime;
2756         long mLastCleanupTime;
2757 
OverflowArrayMap(int uid)2758         public OverflowArrayMap(int uid) {
2759             mUid = uid;
2760         }
2761 
getMap()2762         public ArrayMap<String, T> getMap() {
2763             return mMap;
2764         }
2765 
clear()2766         public void clear() {
2767             mLastClearTime = SystemClock.elapsedRealtime();
2768             mMap.clear();
2769             mCurOverflow = null;
2770             mActiveOverflow = null;
2771         }
2772 
add(String name, T obj)2773         public void add(String name, T obj) {
2774             if (name == null) {
2775                 name = "";
2776             }
2777             mMap.put(name, obj);
2778             if (OVERFLOW_NAME.equals(name)) {
2779                 mCurOverflow = obj;
2780             }
2781         }
2782 
cleanup()2783         public void cleanup() {
2784             mLastCleanupTime = SystemClock.elapsedRealtime();
2785             if (mActiveOverflow != null) {
2786                 if (mActiveOverflow.size() == 0) {
2787                     mActiveOverflow = null;
2788                 }
2789             }
2790             if (mActiveOverflow == null) {
2791                 // There is no currently active overflow, so we should no longer have
2792                 // an overflow entry.
2793                 if (mMap.containsKey(OVERFLOW_NAME)) {
2794                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
2795                             + mMap.get(OVERFLOW_NAME));
2796                     mMap.remove(OVERFLOW_NAME);
2797                 }
2798                 mCurOverflow = null;
2799             } else {
2800                 // There is currently active overflow, so we should still have an overflow entry.
2801                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
2802                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
2803                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
2804                 }
2805             }
2806         }
2807 
startObject(String name)2808         public T startObject(String name) {
2809             if (name == null) {
2810                 name = "";
2811             }
2812             T obj = mMap.get(name);
2813             if (obj != null) {
2814                 return obj;
2815             }
2816 
2817             // No object exists for the given name, but do we currently have it
2818             // running as part of the overflow?
2819             if (mActiveOverflow != null) {
2820                 MutableInt over = mActiveOverflow.get(name);
2821                 if (over != null) {
2822                     // We are already actively counting this name in the overflow object.
2823                     obj = mCurOverflow;
2824                     if (obj == null) {
2825                         // Shouldn't be here, but we'll try to recover.
2826                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
2827                         obj = mCurOverflow = instantiateObject();
2828                         mMap.put(OVERFLOW_NAME, obj);
2829                     }
2830                     over.value++;
2831                     return obj;
2832                 }
2833             }
2834 
2835             // No object exists for given name nor in the overflow; we need to make
2836             // a new one.
2837             final int N = mMap.size();
2838             if (N >= MAX_WAKELOCKS_PER_UID) {
2839                 // Went over the limit on number of objects to track; this one goes
2840                 // in to the overflow.
2841                 obj = mCurOverflow;
2842                 if (obj == null) {
2843                     // Need to start overflow now...
2844                     obj = mCurOverflow = instantiateObject();
2845                     mMap.put(OVERFLOW_NAME, obj);
2846                 }
2847                 if (mActiveOverflow == null) {
2848                     mActiveOverflow = new ArrayMap<>();
2849                 }
2850                 mActiveOverflow.put(name, new MutableInt(1));
2851                 mLastOverflowTime = SystemClock.elapsedRealtime();
2852                 return obj;
2853             }
2854 
2855             // Normal case where we just need to make a new object.
2856             obj = instantiateObject();
2857             mMap.put(name, obj);
2858             return obj;
2859         }
2860 
stopObject(String name)2861         public T stopObject(String name) {
2862             if (name == null) {
2863                 name = "";
2864             }
2865             T obj = mMap.get(name);
2866             if (obj != null) {
2867                 return obj;
2868             }
2869 
2870             // No object exists for the given name, but do we currently have it
2871             // running as part of the overflow?
2872             if (mActiveOverflow != null) {
2873                 MutableInt over = mActiveOverflow.get(name);
2874                 if (over != null) {
2875                     // We are already actively counting this name in the overflow object.
2876                     obj = mCurOverflow;
2877                     if (obj != null) {
2878                         over.value--;
2879                         if (over.value <= 0) {
2880                             mActiveOverflow.remove(name);
2881                             mLastOverflowFinishTime = SystemClock.elapsedRealtime();
2882                         }
2883                         return obj;
2884                     }
2885                 }
2886             }
2887 
2888             // Huh, they are stopping an active operation but we can't find one!
2889             // That's not good.
2890             StringBuilder sb = new StringBuilder();
2891             sb.append("Unable to find object for ");
2892             sb.append(name);
2893             sb.append(" in uid ");
2894             sb.append(mUid);
2895             sb.append(" mapsize=");
2896             sb.append(mMap.size());
2897             sb.append(" activeoverflow=");
2898             sb.append(mActiveOverflow);
2899             sb.append(" curoverflow=");
2900             sb.append(mCurOverflow);
2901             long now = SystemClock.elapsedRealtime();
2902             if (mLastOverflowTime != 0) {
2903                 sb.append(" lastOverflowTime=");
2904                 TimeUtils.formatDuration(mLastOverflowTime-now, sb);
2905             }
2906             if (mLastOverflowFinishTime != 0) {
2907                 sb.append(" lastOverflowFinishTime=");
2908                 TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb);
2909             }
2910             if (mLastClearTime != 0) {
2911                 sb.append(" lastClearTime=");
2912                 TimeUtils.formatDuration(mLastClearTime-now, sb);
2913             }
2914             if (mLastCleanupTime != 0) {
2915                 sb.append(" lastCleanupTime=");
2916                 TimeUtils.formatDuration(mLastCleanupTime-now, sb);
2917             }
2918             Slog.wtf(TAG, sb.toString());
2919             return null;
2920         }
2921 
instantiateObject()2922         public abstract T instantiateObject();
2923     }
2924 
2925     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
2926             implements Parcelable {
2927         private final LongSamplingCounter mIdleTimeMillis;
2928         private final LongSamplingCounter mScanTimeMillis;
2929         private final LongSamplingCounter mSleepTimeMillis;
2930         private final LongSamplingCounter mRxTimeMillis;
2931         private final LongSamplingCounter[] mTxTimeMillis;
2932         private final LongSamplingCounter mPowerDrainMaMs;
2933 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates)2934         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
2935             mIdleTimeMillis = new LongSamplingCounter(timeBase);
2936             mScanTimeMillis = new LongSamplingCounter(timeBase);
2937             mSleepTimeMillis = new LongSamplingCounter(timeBase);
2938             mRxTimeMillis = new LongSamplingCounter(timeBase);
2939             mTxTimeMillis = new LongSamplingCounter[numTxStates];
2940             for (int i = 0; i < numTxStates; i++) {
2941                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
2942             }
2943             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
2944         }
2945 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in)2946         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
2947             mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
2948             mScanTimeMillis = new LongSamplingCounter(timeBase, in);
2949             mSleepTimeMillis = new LongSamplingCounter(timeBase, in);
2950             mRxTimeMillis = new LongSamplingCounter(timeBase, in);
2951             final int recordedTxStates = in.readInt();
2952             if (recordedTxStates != numTxStates) {
2953                 throw new ParcelFormatException("inconsistent tx state lengths");
2954             }
2955 
2956             mTxTimeMillis = new LongSamplingCounter[numTxStates];
2957             for (int i = 0; i < numTxStates; i++) {
2958                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
2959             }
2960             mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
2961         }
2962 
readSummaryFromParcel(Parcel in)2963         public void readSummaryFromParcel(Parcel in) {
2964             mIdleTimeMillis.readSummaryFromParcelLocked(in);
2965             mScanTimeMillis.readSummaryFromParcelLocked(in);
2966             mSleepTimeMillis.readSummaryFromParcelLocked(in);
2967             mRxTimeMillis.readSummaryFromParcelLocked(in);
2968             final int recordedTxStates = in.readInt();
2969             if (recordedTxStates != mTxTimeMillis.length) {
2970                 throw new ParcelFormatException("inconsistent tx state lengths");
2971             }
2972             for (LongSamplingCounter counter : mTxTimeMillis) {
2973                 counter.readSummaryFromParcelLocked(in);
2974             }
2975             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
2976         }
2977 
2978         @Override
describeContents()2979         public int describeContents() {
2980             return 0;
2981         }
2982 
writeSummaryToParcel(Parcel dest)2983         public void writeSummaryToParcel(Parcel dest) {
2984             mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
2985             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
2986             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
2987             mRxTimeMillis.writeSummaryFromParcelLocked(dest);
2988             dest.writeInt(mTxTimeMillis.length);
2989             for (LongSamplingCounter counter : mTxTimeMillis) {
2990                 counter.writeSummaryFromParcelLocked(dest);
2991             }
2992             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
2993         }
2994 
2995         @Override
writeToParcel(Parcel dest, int flags)2996         public void writeToParcel(Parcel dest, int flags) {
2997             mIdleTimeMillis.writeToParcel(dest);
2998             mScanTimeMillis.writeToParcel(dest);
2999             mSleepTimeMillis.writeToParcel(dest);
3000             mRxTimeMillis.writeToParcel(dest);
3001             dest.writeInt(mTxTimeMillis.length);
3002             for (LongSamplingCounter counter : mTxTimeMillis) {
3003                 counter.writeToParcel(dest);
3004             }
3005             mPowerDrainMaMs.writeToParcel(dest);
3006         }
3007 
reset(boolean detachIfReset)3008         public void reset(boolean detachIfReset) {
3009             mIdleTimeMillis.reset(detachIfReset);
3010             mScanTimeMillis.reset(detachIfReset);
3011             mSleepTimeMillis.reset(detachIfReset);
3012             mRxTimeMillis.reset(detachIfReset);
3013             for (LongSamplingCounter counter : mTxTimeMillis) {
3014                 counter.reset(detachIfReset);
3015             }
3016             mPowerDrainMaMs.reset(detachIfReset);
3017         }
3018 
detach()3019         public void detach() {
3020             mIdleTimeMillis.detach();
3021             mScanTimeMillis.detach();
3022             mSleepTimeMillis.detach();
3023             mRxTimeMillis.detach();
3024             for (LongSamplingCounter counter : mTxTimeMillis) {
3025                 counter.detach();
3026             }
3027             mPowerDrainMaMs.detach();
3028         }
3029 
3030         /**
3031          * @return a LongSamplingCounter, measuring time spent in the idle state in
3032          * milliseconds.
3033          */
3034         @Override
getIdleTimeCounter()3035         public LongSamplingCounter getIdleTimeCounter() {
3036             return mIdleTimeMillis;
3037         }
3038 
3039         /**
3040          * @return a LongSamplingCounter, measuring time spent in the scan state in
3041          * milliseconds.
3042          */
3043         @Override
getScanTimeCounter()3044         public LongSamplingCounter getScanTimeCounter() {
3045             return mScanTimeMillis;
3046         }
3047 
3048         /**
3049          * @return a LongSamplingCounter, measuring time spent in the sleep state in
3050          * milliseconds.
3051          */
3052         @Override
getSleepTimeCounter()3053         public LongSamplingCounter getSleepTimeCounter() {
3054             return mSleepTimeMillis;
3055         }
3056 
3057         /**
3058          * @return a LongSamplingCounter, measuring time spent in the receive state in
3059          * milliseconds.
3060          */
3061         @Override
getRxTimeCounter()3062         public LongSamplingCounter getRxTimeCounter() {
3063             return mRxTimeMillis;
3064         }
3065 
3066         /**
3067          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
3068          * milliseconds.
3069          */
3070         @Override
getTxTimeCounters()3071         public LongSamplingCounter[] getTxTimeCounters() {
3072             return mTxTimeMillis;
3073         }
3074 
3075         /**
3076          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
3077          */
3078         @Override
getPowerCounter()3079         public LongSamplingCounter getPowerCounter() {
3080             return mPowerDrainMaMs;
3081         }
3082     }
3083 
3084     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)3085     public SamplingTimer getRpmTimerLocked(String name) {
3086         SamplingTimer rpmt = mRpmStats.get(name);
3087         if (rpmt == null) {
3088             rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3089             mRpmStats.put(name, rpmt);
3090         }
3091         return rpmt;
3092     }
3093 
3094     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)3095     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
3096         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
3097         if (rpmt == null) {
3098             rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3099             mScreenOffRpmStats.put(name, rpmt);
3100         }
3101         return rpmt;
3102     }
3103 
3104     /*
3105      * Get the wakeup reason counter, and create a new one if one
3106      * doesn't already exist.
3107      */
getWakeupReasonTimerLocked(String name)3108     public SamplingTimer getWakeupReasonTimerLocked(String name) {
3109         SamplingTimer timer = mWakeupReasonStats.get(name);
3110         if (timer == null) {
3111             timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3112             mWakeupReasonStats.put(name, timer);
3113         }
3114         return timer;
3115     }
3116 
3117     /*
3118      * Get the KernelWakelockTimer associated with name, and create a new one if one
3119      * doesn't already exist.
3120      */
getKernelWakelockTimerLocked(String name)3121     public SamplingTimer getKernelWakelockTimerLocked(String name) {
3122         SamplingTimer kwlt = mKernelWakelockStats.get(name);
3123         if (kwlt == null) {
3124             kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3125             mKernelWakelockStats.put(name, kwlt);
3126         }
3127         return kwlt;
3128     }
3129 
getKernelMemoryTimerLocked(long bucket)3130     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
3131         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
3132         if (kmt == null) {
3133             kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3134             mKernelMemoryStats.put(bucket, kmt);
3135         }
3136         return kmt;
3137     }
3138 
writeHistoryTag(HistoryTag tag)3139     private int writeHistoryTag(HistoryTag tag) {
3140         Integer idxObj = mHistoryTagPool.get(tag);
3141         int idx;
3142         if (idxObj != null) {
3143             idx = idxObj;
3144         } else {
3145             idx = mNextHistoryTagIdx;
3146             HistoryTag key = new HistoryTag();
3147             key.setTo(tag);
3148             tag.poolIdx = idx;
3149             mHistoryTagPool.put(key, idx);
3150             mNextHistoryTagIdx++;
3151             mNumHistoryTagChars += key.string.length() + 1;
3152         }
3153         return idx;
3154     }
3155 
readHistoryTag(int index, HistoryTag tag)3156     private void readHistoryTag(int index, HistoryTag tag) {
3157         tag.string = mReadHistoryStrings[index];
3158         tag.uid = mReadHistoryUids[index];
3159         tag.poolIdx = index;
3160     }
3161 
3162     /*
3163         The history delta format uses flags to denote further data in subsequent ints in the parcel.
3164 
3165         There is always the first token, which may contain the delta time, or an indicator of
3166         the length of the time (int or long) following this token.
3167 
3168         First token: always present,
3169         31              23              15               7             0
3170         █M|L|K|J|I|H|G|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█
3171 
3172         T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
3173            follows containing the time, and 0x7ffff indicates a long immediately follows with the
3174            delta time.
3175         A: battery level changed and an int follows with battery data.
3176         B: state changed and an int follows with state change data.
3177         C: state2 has changed and an int follows with state2 change data.
3178         D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
3179         E: event data has changed and an event struct follows.
3180         F: battery charge in coulombs has changed and an int with the charge follows.
3181         G: state flag denoting that the mobile radio was active.
3182         H: state flag denoting that the wifi radio was active.
3183         I: state flag denoting that a wifi scan occurred.
3184         J: state flag denoting that a wifi full lock was held.
3185         K: state flag denoting that the gps was on.
3186         L: state flag denoting that a wakelock was held.
3187         M: state flag denoting that the cpu was running.
3188 
3189         Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
3190         with the time delta.
3191 
3192         Battery level int: if A in the first token is set,
3193         31              23              15               7             0
3194         █L|L|L|L|L|L|L|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█
3195 
3196         D: indicates that extra history details follow.
3197         V: the battery voltage.
3198         T: the battery temperature.
3199         L: the battery level (out of 100).
3200 
3201         State change int: if B in the first token is set,
3202         31              23              15               7             0
3203         █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
3204 
3205         A: wifi multicast was on.
3206         B: battery was plugged in.
3207         C: screen was on.
3208         D: phone was scanning for signal.
3209         E: audio was on.
3210         F: a sensor was active.
3211 
3212         State2 change int: if C in the first token is set,
3213         31              23              15               7             0
3214         █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
3215 
3216         A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
3217         B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
3218         C: a bluetooth scan was active.
3219         D: the camera was active.
3220         E: bluetooth was on.
3221         F: a phone call was active.
3222         G: the device was charging.
3223         H: 2 bits indicating the device-idle (doze) state: off, light, full
3224         I: the flashlight was on.
3225         J: wifi was on.
3226         K: wifi was running.
3227         L: video was playing.
3228         M: power save mode was on.
3229 
3230         Wakelock/wakereason struct: if D in the first token is set,
3231         TODO(adamlesinski): describe wakelock/wakereason struct.
3232 
3233         Event struct: if E in the first token is set,
3234         TODO(adamlesinski): describe the event struct.
3235 
3236         History step details struct: if D in the battery level int is set,
3237         TODO(adamlesinski): describe the history step details struct.
3238 
3239         Battery charge int: if F in the first token is set, an int representing the battery charge
3240         in coulombs follows.
3241      */
3242 
3243     // Part of initial delta int that specifies the time delta.
3244     static final int DELTA_TIME_MASK = 0x7ffff;
3245     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
3246     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
3247     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
3248     // Flag in delta int: a new battery level int follows.
3249     static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
3250     // Flag in delta int: a new full state and battery status int follows.
3251     static final int DELTA_STATE_FLAG                       = 0x00100000;
3252     // Flag in delta int: a new full state2 int follows.
3253     static final int DELTA_STATE2_FLAG                      = 0x00200000;
3254     // Flag in delta int: contains a wakelock or wakeReason tag.
3255     static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
3256     // Flag in delta int: contains an event description.
3257     static final int DELTA_EVENT_FLAG                       = 0x00800000;
3258     // Flag in delta int: contains the battery charge count in uAh.
3259     static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
3260     // These upper bits are the frequently changing state bits.
3261     static final int DELTA_STATE_MASK                       = 0xfe000000;
3262 
3263     // These are the pieces of battery state that are packed in to the upper bits of
3264     // the state int that have been packed in to the first delta int.  They must fit
3265     // in STATE_BATTERY_MASK.
3266     static final int STATE_BATTERY_MASK         = 0xff000000;
3267     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
3268     static final int STATE_BATTERY_STATUS_SHIFT = 29;
3269     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
3270     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
3271     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
3272     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
3273 
3274     // We use the low bit of the battery state int to indicate that we have full details
3275     // from a battery level change.
3276     static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
3277 
writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last)3278     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
3279         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
3280             dest.writeInt(DELTA_TIME_ABS);
3281             cur.writeToParcel(dest, 0);
3282             return;
3283         }
3284 
3285         final long deltaTime = cur.time - last.time;
3286         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
3287         final int lastStateInt = buildStateInt(last);
3288 
3289         int deltaTimeToken;
3290         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
3291             deltaTimeToken = DELTA_TIME_LONG;
3292         } else if (deltaTime >= DELTA_TIME_ABS) {
3293             deltaTimeToken = DELTA_TIME_INT;
3294         } else {
3295             deltaTimeToken = (int)deltaTime;
3296         }
3297         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
3298         final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
3299                 ? BATTERY_DELTA_LEVEL_FLAG : 0;
3300         final boolean computeStepDetails = includeStepDetails != 0
3301                 || mLastHistoryStepDetails == null;
3302         final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
3303         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
3304         if (batteryLevelIntChanged) {
3305             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
3306         }
3307         final int stateInt = buildStateInt(cur);
3308         final boolean stateIntChanged = stateInt != lastStateInt;
3309         if (stateIntChanged) {
3310             firstToken |= DELTA_STATE_FLAG;
3311         }
3312         final boolean state2IntChanged = cur.states2 != last.states2;
3313         if (state2IntChanged) {
3314             firstToken |= DELTA_STATE2_FLAG;
3315         }
3316         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3317             firstToken |= DELTA_WAKELOCK_FLAG;
3318         }
3319         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3320             firstToken |= DELTA_EVENT_FLAG;
3321         }
3322 
3323         final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
3324         if (batteryChargeChanged) {
3325             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
3326         }
3327         dest.writeInt(firstToken);
3328         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3329                 + " deltaTime=" + deltaTime);
3330 
3331         if (deltaTimeToken >= DELTA_TIME_INT) {
3332             if (deltaTimeToken == DELTA_TIME_INT) {
3333                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
3334                 dest.writeInt((int)deltaTime);
3335             } else {
3336                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
3337                 dest.writeLong(deltaTime);
3338             }
3339         }
3340         if (batteryLevelIntChanged) {
3341             dest.writeInt(batteryLevelInt);
3342             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
3343                     + Integer.toHexString(batteryLevelInt)
3344                     + " batteryLevel=" + cur.batteryLevel
3345                     + " batteryTemp=" + cur.batteryTemperature
3346                     + " batteryVolt=" + (int)cur.batteryVoltage);
3347         }
3348         if (stateIntChanged) {
3349             dest.writeInt(stateInt);
3350             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
3351                     + Integer.toHexString(stateInt)
3352                     + " batteryStatus=" + cur.batteryStatus
3353                     + " batteryHealth=" + cur.batteryHealth
3354                     + " batteryPlugType=" + cur.batteryPlugType
3355                     + " states=0x" + Integer.toHexString(cur.states));
3356         }
3357         if (state2IntChanged) {
3358             dest.writeInt(cur.states2);
3359             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
3360                     + Integer.toHexString(cur.states2));
3361         }
3362         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3363             int wakeLockIndex;
3364             int wakeReasonIndex;
3365             if (cur.wakelockTag != null) {
3366                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
3367                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3368                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3369             } else {
3370                 wakeLockIndex = 0xffff;
3371             }
3372             if (cur.wakeReasonTag != null) {
3373                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
3374                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3375                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3376             } else {
3377                 wakeReasonIndex = 0xffff;
3378             }
3379             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
3380         }
3381         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3382             int index = writeHistoryTag(cur.eventTag);
3383             int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
3384             dest.writeInt(codeAndIndex);
3385             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
3386                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3387                     + cur.eventTag.string);
3388         }
3389         if (computeStepDetails) {
3390             if (mPlatformIdleStateCallback != null) {
3391                 mCurHistoryStepDetails.statPlatformIdleState =
3392                         mPlatformIdleStateCallback.getPlatformLowPowerStats();
3393                 if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
3394                         mCurHistoryStepDetails.statPlatformIdleState);
3395 
3396                 mCurHistoryStepDetails.statSubsystemPowerState =
3397                         mPlatformIdleStateCallback.getSubsystemLowPowerStats();
3398                 if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
3399                         mCurHistoryStepDetails.statSubsystemPowerState);
3400 
3401             }
3402             computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
3403             if (includeStepDetails != 0) {
3404                 mCurHistoryStepDetails.writeToParcel(dest);
3405             }
3406             cur.stepDetails = mCurHistoryStepDetails;
3407             mLastHistoryStepDetails = mCurHistoryStepDetails;
3408         } else {
3409             cur.stepDetails = null;
3410         }
3411         if (mLastHistoryStepLevel < cur.batteryLevel) {
3412             mLastHistoryStepDetails = null;
3413         }
3414         mLastHistoryStepLevel = cur.batteryLevel;
3415 
3416         if (batteryChargeChanged) {
3417             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
3418             dest.writeInt(cur.batteryChargeUAh);
3419         }
3420     }
3421 
buildBatteryLevelInt(HistoryItem h)3422     private int buildBatteryLevelInt(HistoryItem h) {
3423         return ((((int)h.batteryLevel)<<25)&0xfe000000)
3424                 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
3425                 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
3426     }
3427 
readBatteryLevelInt(int batteryLevelInt, HistoryItem out)3428     private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
3429         out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
3430         out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
3431         out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
3432     }
3433 
buildStateInt(HistoryItem h)3434     private int buildStateInt(HistoryItem h) {
3435         int plugType = 0;
3436         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
3437             plugType = 1;
3438         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
3439             plugType = 2;
3440         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
3441             plugType = 3;
3442         }
3443         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
3444                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
3445                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
3446                 | (h.states&(~STATE_BATTERY_MASK));
3447     }
3448 
computeHistoryStepDetails(final HistoryStepDetails out, final HistoryStepDetails last)3449     private void computeHistoryStepDetails(final HistoryStepDetails out,
3450             final HistoryStepDetails last) {
3451         final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
3452 
3453         // Perform a CPU update right after we do this collection, so we have started
3454         // collecting good data for the next step.
3455         requestImmediateCpuUpdate();
3456 
3457         if (last == null) {
3458             // We are not generating a delta, so all we need to do is reset the stats
3459             // we will later be doing a delta from.
3460             final int NU = mUidStats.size();
3461             for (int i=0; i<NU; i++) {
3462                 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3463                 uid.mLastStepUserTime = uid.mCurStepUserTime;
3464                 uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3465             }
3466             mLastStepCpuUserTime = mCurStepCpuUserTime;
3467             mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3468             mLastStepStatUserTime = mCurStepStatUserTime;
3469             mLastStepStatSystemTime = mCurStepStatSystemTime;
3470             mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3471             mLastStepStatIrqTime = mCurStepStatIrqTime;
3472             mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3473             mLastStepStatIdleTime = mCurStepStatIdleTime;
3474             tmp.clear();
3475             return;
3476         }
3477         if (DEBUG) {
3478             Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
3479                     + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
3480                     + " irq=" + mLastStepStatIrqTime + " sirq="
3481                     + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
3482             Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
3483                     + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
3484                     + " irq=" + mCurStepStatIrqTime + " sirq="
3485                     + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
3486         }
3487         out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
3488         out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
3489         out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
3490         out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
3491         out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
3492         out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
3493         out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
3494         out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
3495         out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
3496         out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
3497         out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
3498         final int NU = mUidStats.size();
3499         for (int i=0; i<NU; i++) {
3500             final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3501             final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
3502             final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
3503             final int totalTime = totalUTime + totalSTime;
3504             uid.mLastStepUserTime = uid.mCurStepUserTime;
3505             uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3506             if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
3507                 continue;
3508             }
3509             if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
3510                 out.appCpuUid3 = uid.mUid;
3511                 out.appCpuUTime3 = totalUTime;
3512                 out.appCpuSTime3 = totalSTime;
3513             } else {
3514                 out.appCpuUid3 = out.appCpuUid2;
3515                 out.appCpuUTime3 = out.appCpuUTime2;
3516                 out.appCpuSTime3 = out.appCpuSTime2;
3517                 if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
3518                     out.appCpuUid2 = uid.mUid;
3519                     out.appCpuUTime2 = totalUTime;
3520                     out.appCpuSTime2 = totalSTime;
3521                 } else {
3522                     out.appCpuUid2 = out.appCpuUid1;
3523                     out.appCpuUTime2 = out.appCpuUTime1;
3524                     out.appCpuSTime2 = out.appCpuSTime1;
3525                     out.appCpuUid1 = uid.mUid;
3526                     out.appCpuUTime1 = totalUTime;
3527                     out.appCpuSTime1 = totalSTime;
3528                 }
3529             }
3530         }
3531         mLastStepCpuUserTime = mCurStepCpuUserTime;
3532         mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3533         mLastStepStatUserTime = mCurStepStatUserTime;
3534         mLastStepStatSystemTime = mCurStepStatSystemTime;
3535         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3536         mLastStepStatIrqTime = mCurStepStatIrqTime;
3537         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3538         mLastStepStatIdleTime = mCurStepStatIdleTime;
3539     }
3540 
readHistoryDelta(Parcel src, HistoryItem cur)3541     public void readHistoryDelta(Parcel src, HistoryItem cur) {
3542         int firstToken = src.readInt();
3543         int deltaTimeToken = firstToken&DELTA_TIME_MASK;
3544         cur.cmd = HistoryItem.CMD_UPDATE;
3545         cur.numReadInts = 1;
3546         if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3547                 + " deltaTimeToken=" + deltaTimeToken);
3548 
3549         if (deltaTimeToken < DELTA_TIME_ABS) {
3550             cur.time += deltaTimeToken;
3551         } else if (deltaTimeToken == DELTA_TIME_ABS) {
3552             cur.time = src.readLong();
3553             cur.numReadInts += 2;
3554             if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
3555             cur.readFromParcel(src);
3556             return;
3557         } else if (deltaTimeToken == DELTA_TIME_INT) {
3558             int delta = src.readInt();
3559             cur.time += delta;
3560             cur.numReadInts += 1;
3561             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3562         } else {
3563             long delta = src.readLong();
3564             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3565             cur.time += delta;
3566             cur.numReadInts += 2;
3567         }
3568 
3569         final int batteryLevelInt;
3570         if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
3571             batteryLevelInt = src.readInt();
3572             readBatteryLevelInt(batteryLevelInt, cur);
3573             cur.numReadInts += 1;
3574             if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
3575                     + Integer.toHexString(batteryLevelInt)
3576                     + " batteryLevel=" + cur.batteryLevel
3577                     + " batteryTemp=" + cur.batteryTemperature
3578                     + " batteryVolt=" + (int)cur.batteryVoltage);
3579         } else {
3580             batteryLevelInt = 0;
3581         }
3582 
3583         if ((firstToken&DELTA_STATE_FLAG) != 0) {
3584             int stateInt = src.readInt();
3585             cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
3586             cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
3587                     & STATE_BATTERY_STATUS_MASK);
3588             cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
3589                     & STATE_BATTERY_HEALTH_MASK);
3590             cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
3591                     & STATE_BATTERY_PLUG_MASK);
3592             switch (cur.batteryPlugType) {
3593                 case 1:
3594                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
3595                     break;
3596                 case 2:
3597                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
3598                     break;
3599                 case 3:
3600                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
3601                     break;
3602             }
3603             cur.numReadInts += 1;
3604             if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
3605                     + Integer.toHexString(stateInt)
3606                     + " batteryStatus=" + cur.batteryStatus
3607                     + " batteryHealth=" + cur.batteryHealth
3608                     + " batteryPlugType=" + cur.batteryPlugType
3609                     + " states=0x" + Integer.toHexString(cur.states));
3610         } else {
3611             cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
3612         }
3613 
3614         if ((firstToken&DELTA_STATE2_FLAG) != 0) {
3615             cur.states2 = src.readInt();
3616             if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
3617                     + Integer.toHexString(cur.states2));
3618         }
3619 
3620         if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
3621             int indexes = src.readInt();
3622             int wakeLockIndex = indexes&0xffff;
3623             int wakeReasonIndex = (indexes>>16)&0xffff;
3624             if (wakeLockIndex != 0xffff) {
3625                 cur.wakelockTag = cur.localWakelockTag;
3626                 readHistoryTag(wakeLockIndex, cur.wakelockTag);
3627                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3628                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3629             } else {
3630                 cur.wakelockTag = null;
3631             }
3632             if (wakeReasonIndex != 0xffff) {
3633                 cur.wakeReasonTag = cur.localWakeReasonTag;
3634                 readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
3635                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3636                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3637             } else {
3638                 cur.wakeReasonTag = null;
3639             }
3640             cur.numReadInts += 1;
3641         } else {
3642             cur.wakelockTag = null;
3643             cur.wakeReasonTag = null;
3644         }
3645 
3646         if ((firstToken&DELTA_EVENT_FLAG) != 0) {
3647             cur.eventTag = cur.localEventTag;
3648             final int codeAndIndex = src.readInt();
3649             cur.eventCode = (codeAndIndex&0xffff);
3650             final int index = ((codeAndIndex>>16)&0xffff);
3651             readHistoryTag(index, cur.eventTag);
3652             cur.numReadInts += 1;
3653             if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
3654                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3655                     + cur.eventTag.string);
3656         } else {
3657             cur.eventCode = HistoryItem.EVENT_NONE;
3658         }
3659 
3660         if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
3661             cur.stepDetails = mReadHistoryStepDetails;
3662             cur.stepDetails.readFromParcel(src);
3663         } else {
3664             cur.stepDetails = null;
3665         }
3666 
3667         if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
3668             cur.batteryChargeUAh = src.readInt();
3669         }
3670     }
3671 
3672     @Override
commitCurrentHistoryBatchLocked()3673     public void commitCurrentHistoryBatchLocked() {
3674         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
3675     }
3676 
addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur)3677     void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) {
3678         if (!mHaveBatteryLevel || !mRecordingHistory) {
3679             return;
3680         }
3681 
3682         final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
3683         final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
3684         final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
3685         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
3686         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
3687         if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
3688                 + Integer.toHexString(diffStates) + " lastDiff="
3689                 + Integer.toHexString(lastDiffStates) + " diff2="
3690                 + Integer.toHexString(diffStates2) + " lastDiff2="
3691                 + Integer.toHexString(lastDiffStates2));
3692         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
3693                 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
3694                 && (diffStates2&lastDiffStates2) == 0
3695                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
3696                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
3697                 && mHistoryLastWritten.stepDetails == null
3698                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
3699                         || cur.eventCode == HistoryItem.EVENT_NONE)
3700                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
3701                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
3702                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
3703                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
3704                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
3705                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
3706             // We can merge this new change in with the last one.  Merging is
3707             // allowed as long as only the states have changed, and within those states
3708             // as long as no bit has changed both between now and the last entry, as
3709             // well as the last entry and the one before it (so we capture any toggles).
3710             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
3711             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
3712             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
3713             mHistoryBufferLastPos = -1;
3714             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
3715             // If the last written history had a wakelock tag, we need to retain it.
3716             // Note that the condition above made sure that we aren't in a case where
3717             // both it and the current history item have a wakelock tag.
3718             if (mHistoryLastWritten.wakelockTag != null) {
3719                 cur.wakelockTag = cur.localWakelockTag;
3720                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
3721             }
3722             // If the last written history had a wake reason tag, we need to retain it.
3723             // Note that the condition above made sure that we aren't in a case where
3724             // both it and the current history item have a wakelock tag.
3725             if (mHistoryLastWritten.wakeReasonTag != null) {
3726                 cur.wakeReasonTag = cur.localWakeReasonTag;
3727                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
3728             }
3729             // If the last written history had an event, we need to retain it.
3730             // Note that the condition above made sure that we aren't in a case where
3731             // both it and the current history item have an event.
3732             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
3733                 cur.eventCode = mHistoryLastWritten.eventCode;
3734                 cur.eventTag = cur.localEventTag;
3735                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
3736             }
3737             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
3738         }
3739 
3740         boolean recordResetDueToOverflow = false;
3741         final int dataSize = mHistoryBuffer.dataSize();
3742         if (dataSize >= MAX_MAX_HISTORY_BUFFER*3) {
3743             // Clients can't deal with history buffers this large. This only
3744             // really happens when the device is on charger and interacted with
3745             // for long periods of time, like in retail mode. Since the device is
3746             // most likely charged, when unplugged, stats would have reset anyways.
3747             // Reset the stats and mark that we overflowed.
3748             // b/32540341
3749             resetAllStatsLocked();
3750 
3751             // Mark that we want to set *OVERFLOW* event and the RESET:START
3752             // events.
3753             recordResetDueToOverflow = true;
3754 
3755         } else if (dataSize >= MAX_HISTORY_BUFFER) {
3756             if (!mHistoryOverflow) {
3757                 mHistoryOverflow = true;
3758                 addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3759                 addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
3760                 return;
3761             }
3762 
3763             // After overflow, we allow various bit-wise states to settle to 0.
3764             boolean writeAnyway = false;
3765             final int curStates = cur.states & HistoryItem.SETTLE_TO_ZERO_STATES
3766                     & mActiveHistoryStates;
3767             if (mHistoryLastWritten.states != curStates) {
3768                 // mActiveHistoryStates keeps track of which bits in .states are now being
3769                 // forced to 0.
3770                 int old = mActiveHistoryStates;
3771                 mActiveHistoryStates &= curStates | ~HistoryItem.SETTLE_TO_ZERO_STATES;
3772                 writeAnyway |= old != mActiveHistoryStates;
3773             }
3774             final int curStates2 = cur.states2 & HistoryItem.SETTLE_TO_ZERO_STATES2
3775                     & mActiveHistoryStates2;
3776             if (mHistoryLastWritten.states2 != curStates2) {
3777                 // mActiveHistoryStates2 keeps track of which bits in .states2 are now being
3778                 // forced to 0.
3779                 int old = mActiveHistoryStates2;
3780                 mActiveHistoryStates2 &= curStates2 | ~HistoryItem.SETTLE_TO_ZERO_STATES2;
3781                 writeAnyway |= old != mActiveHistoryStates2;
3782             }
3783 
3784             // Once we've reached the maximum number of items, we only
3785             // record changes to the battery level and the most interesting states.
3786             // Once we've reached the maximum maximum number of items, we only
3787             // record changes to the battery level.
3788             if (!writeAnyway && mHistoryLastWritten.batteryLevel == cur.batteryLevel &&
3789                     (dataSize >= MAX_MAX_HISTORY_BUFFER
3790                             || ((mHistoryLastWritten.states^cur.states)
3791                                     & HistoryItem.MOST_INTERESTING_STATES) == 0
3792                             || ((mHistoryLastWritten.states2^cur.states2)
3793                                     & HistoryItem.MOST_INTERESTING_STATES2) == 0)) {
3794                 return;
3795             }
3796 
3797             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3798             return;
3799         }
3800 
3801         if (dataSize == 0 || recordResetDueToOverflow) {
3802             // The history is currently empty; we need it to start with a time stamp.
3803             cur.currentTime = System.currentTimeMillis();
3804             if (recordResetDueToOverflow) {
3805                 addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
3806             }
3807             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
3808         }
3809         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3810     }
3811 
addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur)3812     private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
3813         if (mIteratingHistory) {
3814             throw new IllegalStateException("Can't do this while iterating history!");
3815         }
3816         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
3817         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
3818         mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3819         mHistoryLastWritten.states &= mActiveHistoryStates;
3820         mHistoryLastWritten.states2 &= mActiveHistoryStates2;
3821         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
3822         mLastHistoryElapsedRealtime = elapsedRealtimeMs;
3823         cur.wakelockTag = null;
3824         cur.wakeReasonTag = null;
3825         cur.eventCode = HistoryItem.EVENT_NONE;
3826         cur.eventTag = null;
3827         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
3828                 + " now " + mHistoryBuffer.dataPosition()
3829                 + " size is now " + mHistoryBuffer.dataSize());
3830     }
3831 
3832     int mChangedStates = 0;
3833     int mChangedStates2 = 0;
3834 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs)3835     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
3836         if (mTrackRunningHistoryElapsedRealtime != 0) {
3837             final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
3838             final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
3839             if (diffUptime < (diffElapsed-20)) {
3840                 final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
3841                 mHistoryAddTmp.setTo(mHistoryLastWritten);
3842                 mHistoryAddTmp.wakelockTag = null;
3843                 mHistoryAddTmp.wakeReasonTag = null;
3844                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
3845                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
3846                 addHistoryRecordInnerLocked(wakeElapsedTime, mHistoryAddTmp);
3847             }
3848         }
3849         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
3850         mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
3851         mTrackRunningHistoryUptime = uptimeMs;
3852         addHistoryRecordInnerLocked(elapsedRealtimeMs, mHistoryCur);
3853     }
3854 
addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur)3855     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur) {
3856         addHistoryBufferLocked(elapsedRealtimeMs, cur);
3857 
3858         if (!USE_OLD_HISTORY) {
3859             return;
3860         }
3861 
3862         if (!mHaveBatteryLevel || !mRecordingHistory) {
3863             return;
3864         }
3865 
3866         // If the current time is basically the same as the last time,
3867         // and no states have since the last recorded entry changed and
3868         // are now resetting back to their original value, then just collapse
3869         // into one record.
3870         if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
3871                 && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
3872                 && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
3873                 && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
3874             // If the current is the same as the one before, then we no
3875             // longer need the entry.
3876             if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
3877                     && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
3878                     && mHistoryLastEnd.sameNonEvent(cur)) {
3879                 mHistoryLastEnd.next = null;
3880                 mHistoryEnd.next = mHistoryCache;
3881                 mHistoryCache = mHistoryEnd;
3882                 mHistoryEnd = mHistoryLastEnd;
3883                 mHistoryLastEnd = null;
3884             } else {
3885                 mChangedStates |= mHistoryEnd.states^(cur.states&mActiveHistoryStates);
3886                 mChangedStates2 |= mHistoryEnd.states^(cur.states2&mActiveHistoryStates2);
3887                 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
3888             }
3889             return;
3890         }
3891 
3892         mChangedStates = 0;
3893         mChangedStates2 = 0;
3894 
3895         if (mNumHistoryItems == MAX_HISTORY_ITEMS
3896                 || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
3897             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
3898         }
3899 
3900         if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
3901             // Once we've reached the maximum number of items, we only
3902             // record changes to the battery level and the most interesting states.
3903             // Once we've reached the maximum maximum number of items, we only
3904             // record changes to the battery level.
3905             if (mHistoryEnd != null && mHistoryEnd.batteryLevel
3906                     == cur.batteryLevel &&
3907                     (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
3908                             || ((mHistoryEnd.states^(cur.states&mActiveHistoryStates))
3909                                     & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
3910                 return;
3911             }
3912         }
3913 
3914         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3915     }
3916 
addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)3917     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
3918             String name, int uid) {
3919         mHistoryCur.eventCode = code;
3920         mHistoryCur.eventTag = mHistoryCur.localEventTag;
3921         mHistoryCur.eventTag.string = name;
3922         mHistoryCur.eventTag.uid = uid;
3923         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
3924     }
3925 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur)3926     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
3927         HistoryItem rec = mHistoryCache;
3928         if (rec != null) {
3929             mHistoryCache = rec.next;
3930         } else {
3931             rec = new HistoryItem();
3932         }
3933         rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3934 
3935         addHistoryRecordLocked(rec);
3936     }
3937 
addHistoryRecordLocked(HistoryItem rec)3938     void addHistoryRecordLocked(HistoryItem rec) {
3939         mNumHistoryItems++;
3940         rec.next = null;
3941         mHistoryLastEnd = mHistoryEnd;
3942         if (mHistoryEnd != null) {
3943             mHistoryEnd.next = rec;
3944             mHistoryEnd = rec;
3945         } else {
3946             mHistory = mHistoryEnd = rec;
3947         }
3948     }
3949 
clearHistoryLocked()3950     void clearHistoryLocked() {
3951         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
3952         if (USE_OLD_HISTORY) {
3953             if (mHistory != null) {
3954                 mHistoryEnd.next = mHistoryCache;
3955                 mHistoryCache = mHistory;
3956                 mHistory = mHistoryLastEnd = mHistoryEnd = null;
3957             }
3958             mNumHistoryItems = 0;
3959         }
3960 
3961         mHistoryBaseTime = 0;
3962         mLastHistoryElapsedRealtime = 0;
3963         mTrackRunningHistoryElapsedRealtime = 0;
3964         mTrackRunningHistoryUptime = 0;
3965 
3966         mHistoryBuffer.setDataSize(0);
3967         mHistoryBuffer.setDataPosition(0);
3968         mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER / 2);
3969         mHistoryLastLastWritten.clear();
3970         mHistoryLastWritten.clear();
3971         mHistoryTagPool.clear();
3972         mNextHistoryTagIdx = 0;
3973         mNumHistoryTagChars = 0;
3974         mHistoryBufferLastPos = -1;
3975         mHistoryOverflow = false;
3976         mActiveHistoryStates = 0xffffffff;
3977         mActiveHistoryStates2 = 0xffffffff;
3978     }
3979 
3980     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptime, long realtime)3981     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
3982             long realtime) {
3983         final boolean screenOff = !isScreenOn(screenState);
3984         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
3985         final boolean updateOnBatteryScreenOffTimeBase =
3986                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
3987 
3988         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
3989             if (updateOnBatteryScreenOffTimeBase) {
3990                 updateKernelWakelocksLocked();
3991                 updateBatteryPropertiesLocked();
3992             }
3993             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
3994             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
3995             // improved, remove the surrounding if{}.
3996             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
3997                 updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes.
3998             }
3999             if (DEBUG_ENERGY_CPU) {
4000                 Slog.d(TAG, "Updating cpu time because screen is now "
4001                         + Display.stateToString(screenState)
4002                         + " and battery is " + (unplugged ? "on" : "off"));
4003             }
4004 
4005             mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
4006             if (updateOnBatteryTimeBase) {
4007                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4008                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime);
4009                 }
4010             }
4011             if (updateOnBatteryScreenOffTimeBase) {
4012                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, uptime, realtime);
4013                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4014                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime);
4015                 }
4016             }
4017         }
4018     }
4019 
updateBatteryPropertiesLocked()4020     private void updateBatteryPropertiesLocked() {
4021         try {
4022             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
4023                     ServiceManager.getService("batteryproperties"));
4024             registrar.scheduleUpdate();
4025         } catch (RemoteException e) {
4026             // Ignore.
4027         }
4028     }
4029 
addIsolatedUidLocked(int isolatedUid, int appUid)4030     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
4031         mIsolatedUids.put(isolatedUid, appUid);
4032         StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, appUid, isolatedUid,
4033                 StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
4034         final Uid u = getUidStatsLocked(appUid);
4035         u.addIsolatedUid(isolatedUid);
4036     }
4037 
4038     /**
4039      * Schedules a read of the latest cpu times before removing the isolated UID.
4040      * @see #removeIsolatedUidLocked(int)
4041      */
scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid)4042     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
4043         int curUid = mIsolatedUids.get(isolatedUid, -1);
4044         if (curUid == appUid) {
4045             if (mExternalSync != null) {
4046                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
4047             }
4048         }
4049     }
4050 
4051     /**
4052      * This should only be called after the cpu times have been read.
4053      * @see #scheduleRemoveIsolatedUidLocked(int, int)
4054      */
4055     @GuardedBy("this")
removeIsolatedUidLocked(int isolatedUid)4056     public void removeIsolatedUidLocked(int isolatedUid) {
4057         StatsLog.write(
4058                 StatsLog.ISOLATED_UID_CHANGED, mIsolatedUids.get(isolatedUid, -1),
4059                 isolatedUid, StatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED);
4060         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
4061         if (idx >= 0) {
4062             final int ownerUid = mIsolatedUids.valueAt(idx);
4063             final Uid u = getUidStatsLocked(ownerUid);
4064             u.removeIsolatedUid(isolatedUid);
4065             mIsolatedUids.removeAt(idx);
4066         }
4067         mPendingRemovedUids.add(new UidToRemove(isolatedUid, mClocks.elapsedRealtime()));
4068     }
4069 
mapUid(int uid)4070     public int mapUid(int uid) {
4071         int isolated = mIsolatedUids.get(uid, -1);
4072         return isolated > 0 ? isolated : uid;
4073     }
4074 
noteEventLocked(int code, String name, int uid)4075     public void noteEventLocked(int code, String name, int uid) {
4076         uid = mapUid(uid);
4077         if (!mActiveEvents.updateState(code, name, uid, 0)) {
4078             return;
4079         }
4080         final long elapsedRealtime = mClocks.elapsedRealtime();
4081         final long uptime = mClocks.uptimeMillis();
4082         addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
4083     }
4084 
ensureStartClockTime(final long currentTime)4085     boolean ensureStartClockTime(final long currentTime) {
4086         final long ABOUT_ONE_YEAR = 365*24*60*60*1000L;
4087         if ((currentTime > ABOUT_ONE_YEAR && mStartClockTime < (currentTime-ABOUT_ONE_YEAR))
4088                 || (mStartClockTime > currentTime)) {
4089             // If the start clock time has changed by more than a year, then presumably
4090             // the previous time was completely bogus.  So we are going to figure out a
4091             // new time based on how much time has elapsed since we started counting.
4092             mStartClockTime = currentTime - (mClocks.elapsedRealtime()-(mRealtimeStart/1000));
4093             return true;
4094         }
4095         return false;
4096     }
4097 
noteCurrentTimeChangedLocked()4098     public void noteCurrentTimeChangedLocked() {
4099         final long currentTime = System.currentTimeMillis();
4100         final long elapsedRealtime = mClocks.elapsedRealtime();
4101         final long uptime = mClocks.uptimeMillis();
4102         recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
4103         ensureStartClockTime(currentTime);
4104     }
4105 
noteProcessStartLocked(String name, int uid)4106     public void noteProcessStartLocked(String name, int uid) {
4107         uid = mapUid(uid);
4108         if (isOnBattery()) {
4109             Uid u = getUidStatsLocked(uid);
4110             u.getProcessStatsLocked(name).incStartsLocked();
4111         }
4112         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
4113             return;
4114         }
4115         if (!mRecordAllHistory) {
4116             return;
4117         }
4118         final long elapsedRealtime = mClocks.elapsedRealtime();
4119         final long uptime = mClocks.uptimeMillis();
4120         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
4121     }
4122 
noteProcessCrashLocked(String name, int uid)4123     public void noteProcessCrashLocked(String name, int uid) {
4124         uid = mapUid(uid);
4125         if (isOnBattery()) {
4126             Uid u = getUidStatsLocked(uid);
4127             u.getProcessStatsLocked(name).incNumCrashesLocked();
4128         }
4129     }
4130 
noteProcessAnrLocked(String name, int uid)4131     public void noteProcessAnrLocked(String name, int uid) {
4132         uid = mapUid(uid);
4133         if (isOnBattery()) {
4134             Uid u = getUidStatsLocked(uid);
4135             u.getProcessStatsLocked(name).incNumAnrsLocked();
4136         }
4137     }
4138 
noteUidProcessStateLocked(int uid, int state)4139     public void noteUidProcessStateLocked(int uid, int state) {
4140         int parentUid = mapUid(uid);
4141         if (uid != parentUid) {
4142             // Isolated UIDs process state is already rolled up into parent, so no need to track
4143             // Otherwise the parent's process state will get downgraded incorrectly
4144             return;
4145         }
4146         getUidStatsLocked(uid).updateUidProcessStateLocked(state);
4147     }
4148 
noteProcessFinishLocked(String name, int uid)4149     public void noteProcessFinishLocked(String name, int uid) {
4150         uid = mapUid(uid);
4151         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4152             return;
4153         }
4154         if (!mRecordAllHistory) {
4155             return;
4156         }
4157         final long elapsedRealtime = mClocks.elapsedRealtime();
4158         final long uptime = mClocks.uptimeMillis();
4159         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
4160     }
4161 
noteSyncStartLocked(String name, int uid)4162     public void noteSyncStartLocked(String name, int uid) {
4163         uid = mapUid(uid);
4164         final long elapsedRealtime = mClocks.elapsedRealtime();
4165         final long uptime = mClocks.uptimeMillis();
4166         getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
4167         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4168             return;
4169         }
4170         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
4171     }
4172 
noteSyncFinishLocked(String name, int uid)4173     public void noteSyncFinishLocked(String name, int uid) {
4174         uid = mapUid(uid);
4175         final long elapsedRealtime = mClocks.elapsedRealtime();
4176         final long uptime = mClocks.uptimeMillis();
4177         getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
4178         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4179             return;
4180         }
4181         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
4182     }
4183 
noteJobStartLocked(String name, int uid)4184     public void noteJobStartLocked(String name, int uid) {
4185         uid = mapUid(uid);
4186         final long elapsedRealtime = mClocks.elapsedRealtime();
4187         final long uptime = mClocks.uptimeMillis();
4188         getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
4189         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4190             return;
4191         }
4192         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
4193     }
4194 
noteJobFinishLocked(String name, int uid, int stopReason)4195     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4196         uid = mapUid(uid);
4197         final long elapsedRealtime = mClocks.elapsedRealtime();
4198         final long uptime = mClocks.uptimeMillis();
4199         getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason);
4200         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4201             return;
4202         }
4203         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
4204     }
4205 
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast)4206     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
4207         uid = mapUid(uid);
4208         getUidStatsLocked(uid).noteJobsDeferredLocked(numDeferred, sinceLast);
4209     }
4210 
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4211     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4212         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid);
4213     }
4214 
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)4215     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4216         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid);
4217     }
4218 
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid)4219     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4220             int uid) {
4221         if (!mRecordAllHistory) {
4222             return;
4223         }
4224 
4225         final long elapsedRealtime = mClocks.elapsedRealtime();
4226         final long uptime = mClocks.uptimeMillis();
4227 
4228         if (workSource != null) {
4229             for (int i = 0; i < workSource.size(); ++i) {
4230                 uid = mapUid(workSource.get(i));
4231                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4232                     addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4233                 }
4234             }
4235 
4236             List<WorkChain> workChains = workSource.getWorkChains();
4237             if (workChains != null) {
4238                 for (int i = 0; i < workChains.size(); ++i) {
4239                     uid = mapUid(workChains.get(i).getAttributionUid());
4240                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4241                         addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4242                     }
4243                 }
4244             }
4245         } else {
4246             uid = mapUid(uid);
4247 
4248             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4249                 addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4250             }
4251         }
4252     }
4253 
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)4254     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4255             String tag) {
4256         if (workSource != null) {
4257             for (int i = 0; i < workSource.size(); ++i) {
4258                 uid = workSource.get(i);
4259                 final String workSourceName = workSource.getName(i);
4260 
4261                 if (isOnBattery()) {
4262                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4263                             workSourceName != null ? workSourceName : packageName);
4264                     pkg.noteWakeupAlarmLocked(tag);
4265                 }
4266                 StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, workSource.get(i),
4267                         workSource.getName(i), tag);
4268             }
4269 
4270             ArrayList<WorkChain> workChains = workSource.getWorkChains();
4271             if (workChains != null) {
4272                 for (int i = 0; i < workChains.size(); ++i) {
4273                     final WorkChain wc = workChains.get(i);
4274                     uid = wc.getAttributionUid();
4275 
4276                     if (isOnBattery()) {
4277                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4278                         pkg.noteWakeupAlarmLocked(tag);
4279                     }
4280                     StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, wc.getUids(), wc.getTags(), tag);
4281                 }
4282             }
4283         } else {
4284             if (isOnBattery()) {
4285                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4286                 pkg.noteWakeupAlarmLocked(tag);
4287             }
4288             StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, uid, null, tag);
4289         }
4290     }
4291 
requestWakelockCpuUpdate()4292     private void requestWakelockCpuUpdate() {
4293         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4294     }
4295 
requestImmediateCpuUpdate()4296     private void requestImmediateCpuUpdate() {
4297         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4298     }
4299 
setRecordAllHistoryLocked(boolean enabled)4300     public void setRecordAllHistoryLocked(boolean enabled) {
4301         mRecordAllHistory = enabled;
4302         if (!enabled) {
4303             // Clear out any existing state.
4304             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4305             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4306             // Record the currently running processes as stopping, now that we are no
4307             // longer tracking them.
4308             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4309                     HistoryItem.EVENT_PROC);
4310             if (active != null) {
4311                 long mSecRealtime = mClocks.elapsedRealtime();
4312                 final long mSecUptime = mClocks.uptimeMillis();
4313                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4314                     SparseIntArray uids = ent.getValue();
4315                     for (int j=0; j<uids.size(); j++) {
4316                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4317                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4318                     }
4319                 }
4320             }
4321         } else {
4322             // Record the currently running processes as starting, now that we are tracking them.
4323             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4324                     HistoryItem.EVENT_PROC);
4325             if (active != null) {
4326                 long mSecRealtime = mClocks.elapsedRealtime();
4327                 final long mSecUptime = mClocks.uptimeMillis();
4328                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4329                     SparseIntArray uids = ent.getValue();
4330                     for (int j=0; j<uids.size(); j++) {
4331                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4332                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
4333                     }
4334                 }
4335             }
4336         }
4337     }
4338 
setNoAutoReset(boolean enabled)4339     public void setNoAutoReset(boolean enabled) {
4340         mNoAutoReset = enabled;
4341     }
4342 
setPretendScreenOff(boolean pretendScreenOff)4343     public void setPretendScreenOff(boolean pretendScreenOff) {
4344         if (mPretendScreenOff != pretendScreenOff) {
4345             mPretendScreenOff = pretendScreenOff;
4346             noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON);
4347         }
4348     }
4349 
4350     private String mInitialAcquireWakeName;
4351     private int mInitialAcquireWakeUid = -1;
4352 
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtime, long uptime)4353     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4354         int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) {
4355         uid = mapUid(uid);
4356         if (type == WAKE_TYPE_PARTIAL) {
4357             // Only care about partial wake locks, since full wake locks
4358             // will be canceled when the user puts the screen to sleep.
4359             aggregateLastWakeupUptimeLocked(uptime);
4360             if (historyName == null) {
4361                 historyName = name;
4362             }
4363             if (mRecordAllHistory) {
4364                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
4365                         uid, 0)) {
4366                     addHistoryEventLocked(elapsedRealtime, uptime,
4367                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
4368                 }
4369             }
4370             if (mWakeLockNesting == 0) {
4371                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
4372                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
4373                         + Integer.toHexString(mHistoryCur.states));
4374                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4375                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4376                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4377                 mWakeLockImportant = !unimportantForLogging;
4378                 addHistoryRecordLocked(elapsedRealtime, uptime);
4379             } else if (!mWakeLockImportant && !unimportantForLogging
4380                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
4381                 if (mHistoryLastWritten.wakelockTag != null) {
4382                     // We'll try to update the last tag.
4383                     mHistoryLastWritten.wakelockTag = null;
4384                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4385                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4386                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4387                     addHistoryRecordLocked(elapsedRealtime, uptime);
4388                 }
4389                 mWakeLockImportant = true;
4390             }
4391             mWakeLockNesting++;
4392         }
4393         if (uid >= 0) {
4394             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4395                 // We only update the cpu time when a wake lock is acquired if the screen is off.
4396                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
4397                 if (DEBUG_ENERGY_CPU) {
4398                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
4399                 }
4400                 requestWakelockCpuUpdate();
4401             }
4402 
4403             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
4404 
4405             if (wc != null) {
4406                 StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
4407                         getPowerManagerWakeLockLevel(type), name,
4408                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4409             } else {
4410                 StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
4411                         getPowerManagerWakeLockLevel(type), name,
4412                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4413             }
4414         }
4415     }
4416 
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtime, long uptime)4417     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4418             int type, long elapsedRealtime, long uptime) {
4419         uid = mapUid(uid);
4420         if (type == WAKE_TYPE_PARTIAL) {
4421             mWakeLockNesting--;
4422             if (mRecordAllHistory) {
4423                 if (historyName == null) {
4424                     historyName = name;
4425                 }
4426                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
4427                         uid, 0)) {
4428                     addHistoryEventLocked(elapsedRealtime, uptime,
4429                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
4430                 }
4431             }
4432             if (mWakeLockNesting == 0) {
4433                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
4434                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
4435                         + Integer.toHexString(mHistoryCur.states));
4436                 mInitialAcquireWakeName = null;
4437                 mInitialAcquireWakeUid = -1;
4438                 addHistoryRecordLocked(elapsedRealtime, uptime);
4439             }
4440         }
4441         if (uid >= 0) {
4442             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4443                 if (DEBUG_ENERGY_CPU) {
4444                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
4445                 }
4446                 requestWakelockCpuUpdate();
4447             }
4448 
4449             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
4450             if (wc != null) {
4451                 StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
4452                         getPowerManagerWakeLockLevel(type), name,
4453                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4454             } else {
4455                 StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
4456                         getPowerManagerWakeLockLevel(type), name,
4457                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4458             }
4459         }
4460     }
4461 
4462     /**
4463      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
4464      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
4465      * These are estimations, since batterystats loses some of the original data.
4466      * TODO: Delete this. Instead, StatsLog.write should be called from PowerManager's Notifier.
4467      */
getPowerManagerWakeLockLevel(int battertStatsWakelockType)4468     private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
4469         switch (battertStatsWakelockType) {
4470             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
4471             case BatteryStats.WAKE_TYPE_PARTIAL:
4472                 return PowerManager.PARTIAL_WAKE_LOCK;
4473 
4474             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
4475             case BatteryStats.WAKE_TYPE_FULL:
4476                 return PowerManager.FULL_WAKE_LOCK;
4477 
4478             case BatteryStats.WAKE_TYPE_DRAW:
4479                 return PowerManager.DRAW_WAKE_LOCK;
4480 
4481             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
4482             case BatteryStats.WAKE_TYPE_WINDOW:
4483                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
4484                 return -1;
4485 
4486             default:
4487                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
4488                 return -1;
4489         }
4490     }
4491 
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging)4492     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4493             String historyName, int type, boolean unimportantForLogging) {
4494         final long elapsedRealtime = mClocks.elapsedRealtime();
4495         final long uptime = mClocks.uptimeMillis();
4496         final int N = ws.size();
4497         for (int i=0; i<N; i++) {
4498             noteStartWakeLocked(ws.get(i), pid, null, name, historyName, type,
4499                     unimportantForLogging, elapsedRealtime, uptime);
4500         }
4501 
4502         List<WorkChain> wcs = ws.getWorkChains();
4503         if (wcs != null) {
4504             for (int i = 0; i < wcs.size(); ++i) {
4505                 final WorkChain wc = wcs.get(i);
4506                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4507                         unimportantForLogging, elapsedRealtime, uptime);
4508             }
4509         }
4510     }
4511 
noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging)4512     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4513             String historyName, int type, WorkSource newWs, int newPid, String newName,
4514             String newHistoryName, int newType, boolean newUnimportantForLogging) {
4515         final long elapsedRealtime = mClocks.elapsedRealtime();
4516         final long uptime = mClocks.uptimeMillis();
4517 
4518         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
4519 
4520         // For correct semantics, we start the need worksources first, so that we won't
4521         // make inappropriate history items as if all wake locks went away and new ones
4522         // appeared.  This is okay because tracking of wake locks allows nesting.
4523         //
4524         // First the starts :
4525         final int NN = newWs.size();
4526         for (int i=0; i<NN; i++) {
4527             noteStartWakeLocked(newWs.get(i), newPid, null, newName, newHistoryName, newType,
4528                     newUnimportantForLogging, elapsedRealtime, uptime);
4529         }
4530         if (wcs != null) {
4531             List<WorkChain> newChains = wcs[0];
4532             if (newChains != null) {
4533                 for (int i = 0; i < newChains.size(); ++i) {
4534                     final WorkChain newChain = newChains.get(i);
4535                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
4536                         newHistoryName, newType, newUnimportantForLogging, elapsedRealtime,
4537                         uptime);
4538                 }
4539             }
4540         }
4541 
4542         // Then the stops :
4543         final int NO = ws.size();
4544         for (int i=0; i<NO; i++) {
4545             noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
4546                     uptime);
4547         }
4548         if (wcs != null) {
4549             List<WorkChain> goneChains = wcs[1];
4550             if (goneChains != null) {
4551                 for (int i = 0; i < goneChains.size(); ++i) {
4552                     final WorkChain goneChain = goneChains.get(i);
4553                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
4554                             historyName, type, elapsedRealtime, uptime);
4555                 }
4556             }
4557         }
4558     }
4559 
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type)4560     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4561             String historyName, int type) {
4562         final long elapsedRealtime = mClocks.elapsedRealtime();
4563         final long uptime = mClocks.uptimeMillis();
4564         final int N = ws.size();
4565         for (int i=0; i<N; i++) {
4566             noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
4567                     uptime);
4568         }
4569 
4570         List<WorkChain> wcs = ws.getWorkChains();
4571         if (wcs != null) {
4572             for (int i = 0; i < wcs.size(); ++i) {
4573                 final WorkChain wc = wcs.get(i);
4574                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4575                         elapsedRealtime, uptime);
4576             }
4577         }
4578     }
4579 
noteLongPartialWakelockStart(String name, String historyName, int uid)4580     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
4581         StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4582                 uid, null, name, historyName,
4583                 StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
4584 
4585         uid = mapUid(uid);
4586         noteLongPartialWakeLockStartInternal(name, historyName, uid);
4587     }
4588 
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource)4589     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4590             WorkSource workSource) {
4591         final int N = workSource.size();
4592         for (int i = 0; i < N; ++i) {
4593             final int uid = mapUid(workSource.get(i));
4594             noteLongPartialWakeLockStartInternal(name, historyName, uid);
4595             StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4596                     workSource.get(i), workSource.getName(i), name, historyName,
4597                     StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
4598         }
4599 
4600         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
4601         if (workChains != null) {
4602             for (int i = 0; i < workChains.size(); ++i) {
4603                 final WorkChain workChain = workChains.get(i);
4604                 final int uid = workChain.getAttributionUid();
4605                 noteLongPartialWakeLockStartInternal(name, historyName, uid);
4606 
4607                 StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4608                         workChain.getUids(), workChain.getTags(), name, historyName,
4609                         StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
4610             }
4611         }
4612     }
4613 
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid)4614     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid) {
4615         final long elapsedRealtime = mClocks.elapsedRealtime();
4616         final long uptime = mClocks.uptimeMillis();
4617         if (historyName == null) {
4618             historyName = name;
4619         }
4620         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
4621                 0)) {
4622             return;
4623         }
4624         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
4625                 historyName, uid);
4626     }
4627 
noteLongPartialWakelockFinish(String name, String historyName, int uid)4628     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
4629         StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, null,
4630                 name, historyName, StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
4631 
4632         uid = mapUid(uid);
4633         noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4634     }
4635 
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource)4636     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
4637             WorkSource workSource) {
4638         final int N = workSource.size();
4639         for (int i = 0; i < N; ++i) {
4640             final int uid = mapUid(workSource.get(i));
4641             noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4642             StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4643                     workSource.get(i), workSource.getName(i), name, historyName,
4644                     StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
4645         }
4646 
4647         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
4648         if (workChains != null) {
4649             for (int i = 0; i < workChains.size(); ++i) {
4650                 final WorkChain workChain = workChains.get(i);
4651                 final int uid = workChain.getAttributionUid();
4652                 noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4653                 StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4654                         workChain.getUids(), workChain.getTags(), name, historyName,
4655                         StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
4656             }
4657         }
4658     }
4659 
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid)4660     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid) {
4661         final long elapsedRealtime = mClocks.elapsedRealtime();
4662         final long uptime = mClocks.uptimeMillis();
4663         if (historyName == null) {
4664             historyName = name;
4665         }
4666         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
4667                 0)) {
4668             return;
4669         }
4670         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
4671                 historyName, uid);
4672     }
4673 
aggregateLastWakeupUptimeLocked(long uptimeMs)4674     void aggregateLastWakeupUptimeLocked(long uptimeMs) {
4675         if (mLastWakeupReason != null) {
4676             long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
4677             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
4678             timer.add(deltaUptime * 1000, 1); // time in in microseconds
4679             StatsLog.write(StatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
4680                     /* duration_usec */ deltaUptime * 1000);
4681             mLastWakeupReason = null;
4682         }
4683     }
4684 
noteWakeupReasonLocked(String reason)4685     public void noteWakeupReasonLocked(String reason) {
4686         final long elapsedRealtime = mClocks.elapsedRealtime();
4687         final long uptime = mClocks.uptimeMillis();
4688         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
4689                 + Integer.toHexString(mHistoryCur.states));
4690         aggregateLastWakeupUptimeLocked(uptime);
4691         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
4692         mHistoryCur.wakeReasonTag.string = reason;
4693         mHistoryCur.wakeReasonTag.uid = 0;
4694         mLastWakeupReason = reason;
4695         mLastWakeupUptimeMs = uptime;
4696         addHistoryRecordLocked(elapsedRealtime, uptime);
4697     }
4698 
startAddingCpuLocked()4699     public boolean startAddingCpuLocked() {
4700         mExternalSync.cancelCpuSyncDueToWakelockChange();
4701         return mOnBatteryInternal;
4702     }
4703 
finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime, int statSystemTime, int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime)4704     public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
4705                                       int statSystemTime, int statIOWaitTime, int statIrqTime,
4706                                       int statSoftIrqTime, int statIdleTime) {
4707         if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
4708                 + " user=" + statUserTime + " sys=" + statSystemTime
4709                 + " io=" + statIOWaitTime + " irq=" + statIrqTime
4710                 + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
4711         mCurStepCpuUserTime += totalUTime;
4712         mCurStepCpuSystemTime += totalSTime;
4713         mCurStepStatUserTime += statUserTime;
4714         mCurStepStatSystemTime += statSystemTime;
4715         mCurStepStatIOWaitTime += statIOWaitTime;
4716         mCurStepStatIrqTime += statIrqTime;
4717         mCurStepStatSoftIrqTime += statSoftIrqTime;
4718         mCurStepStatIdleTime += statIdleTime;
4719     }
4720 
noteProcessDiedLocked(int uid, int pid)4721     public void noteProcessDiedLocked(int uid, int pid) {
4722         uid = mapUid(uid);
4723         Uid u = mUidStats.get(uid);
4724         if (u != null) {
4725             u.mPids.remove(pid);
4726         }
4727     }
4728 
getProcessWakeTime(int uid, int pid, long realtime)4729     public long getProcessWakeTime(int uid, int pid, long realtime) {
4730         uid = mapUid(uid);
4731         Uid u = mUidStats.get(uid);
4732         if (u != null) {
4733             Uid.Pid p = u.mPids.get(pid);
4734             if (p != null) {
4735                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
4736             }
4737         }
4738         return 0;
4739     }
4740 
reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime)4741     public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
4742         uid = mapUid(uid);
4743         Uid u = mUidStats.get(uid);
4744         if (u != null) {
4745             u.reportExcessiveCpuLocked(proc, overTime, usedTime);
4746         }
4747     }
4748 
4749     int mSensorNesting;
4750 
noteStartSensorLocked(int uid, int sensor)4751     public void noteStartSensorLocked(int uid, int sensor) {
4752         uid = mapUid(uid);
4753         final long elapsedRealtime = mClocks.elapsedRealtime();
4754         final long uptime = mClocks.uptimeMillis();
4755         if (mSensorNesting == 0) {
4756             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
4757             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
4758                     + Integer.toHexString(mHistoryCur.states));
4759             addHistoryRecordLocked(elapsedRealtime, uptime);
4760         }
4761         mSensorNesting++;
4762         getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
4763     }
4764 
noteStopSensorLocked(int uid, int sensor)4765     public void noteStopSensorLocked(int uid, int sensor) {
4766         uid = mapUid(uid);
4767         final long elapsedRealtime = mClocks.elapsedRealtime();
4768         final long uptime = mClocks.uptimeMillis();
4769         mSensorNesting--;
4770         if (mSensorNesting == 0) {
4771             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
4772             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
4773                     + Integer.toHexString(mHistoryCur.states));
4774             addHistoryRecordLocked(elapsedRealtime, uptime);
4775         }
4776         getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
4777     }
4778 
4779     int mGpsNesting;
4780 
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)4781     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
4782         for (int i = 0; i < newWs.size(); ++i) {
4783             noteStartGpsLocked(newWs.get(i), null);
4784         }
4785 
4786         for (int i = 0; i < oldWs.size(); ++i) {
4787             noteStopGpsLocked((oldWs.get(i)), null);
4788         }
4789 
4790         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
4791         if (wcs != null) {
4792             if (wcs[0] != null) {
4793                 final List<WorkChain> newChains = wcs[0];
4794                 for (int i = 0; i < newChains.size(); ++i) {
4795                     noteStartGpsLocked(-1, newChains.get(i));
4796                 }
4797             }
4798 
4799             if (wcs[1] != null) {
4800                 final List<WorkChain> goneChains = wcs[1];
4801                 for (int i = 0; i < goneChains.size(); ++i) {
4802                     noteStopGpsLocked(-1, goneChains.get(i));
4803                 }
4804             }
4805         }
4806     }
4807 
noteStartGpsLocked(int uid, WorkChain workChain)4808     private void noteStartGpsLocked(int uid, WorkChain workChain) {
4809         uid = getAttributionUid(uid, workChain);
4810         final long elapsedRealtime = mClocks.elapsedRealtime();
4811         final long uptime = mClocks.uptimeMillis();
4812         if (mGpsNesting == 0) {
4813             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
4814             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
4815                     + Integer.toHexString(mHistoryCur.states));
4816             addHistoryRecordLocked(elapsedRealtime, uptime);
4817         }
4818         mGpsNesting++;
4819 
4820         if (workChain == null) {
4821             StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4822                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4823         } else {
4824             StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED,
4825                     workChain.getUids(), workChain.getTags(),
4826                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4827         }
4828 
4829         getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
4830     }
4831 
noteStopGpsLocked(int uid, WorkChain workChain)4832     private void noteStopGpsLocked(int uid, WorkChain workChain) {
4833         uid = getAttributionUid(uid, workChain);
4834         final long elapsedRealtime = mClocks.elapsedRealtime();
4835         final long uptime = mClocks.uptimeMillis();
4836         mGpsNesting--;
4837         if (mGpsNesting == 0) {
4838             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
4839             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
4840                     + Integer.toHexString(mHistoryCur.states));
4841             addHistoryRecordLocked(elapsedRealtime, uptime);
4842             stopAllGpsSignalQualityTimersLocked(-1);
4843             mGpsSignalQualityBin = -1;
4844         }
4845 
4846         if (workChain == null) {
4847             StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4848                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4849         } else {
4850             StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
4851                     workChain.getTags(), StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4852         }
4853 
4854         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
4855     }
4856 
noteGpsSignalQualityLocked(int signalLevel)4857     public void noteGpsSignalQualityLocked(int signalLevel) {
4858         if (mGpsNesting == 0) {
4859             return;
4860         }
4861         if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
4862             stopAllGpsSignalQualityTimersLocked(-1);
4863             return;
4864         }
4865         final long elapsedRealtime = mClocks.elapsedRealtime();
4866         final long uptime = mClocks.uptimeMillis();
4867         if (mGpsSignalQualityBin != signalLevel) {
4868             if (mGpsSignalQualityBin >= 0) {
4869                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
4870             }
4871             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
4872                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
4873             }
4874             mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
4875                     | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
4876             addHistoryRecordLocked(elapsedRealtime, uptime);
4877             mGpsSignalQualityBin = signalLevel;
4878         }
4879         return;
4880     }
4881 
4882     @GuardedBy("this")
noteScreenStateLocked(int state)4883     public void noteScreenStateLocked(int state) {
4884         state = mPretendScreenOff ? Display.STATE_OFF : state;
4885 
4886         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
4887         // original 4 are mapped to one of the originals.
4888         if (state > MAX_TRACKED_SCREEN_STATE) {
4889             switch (state) {
4890                 case Display.STATE_VR:
4891                     state = Display.STATE_ON;
4892                     break;
4893                 default:
4894                     Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
4895                     break;
4896             }
4897         }
4898 
4899         if (mScreenState != state) {
4900             recordDailyStatsIfNeededLocked(true);
4901             final int oldState = mScreenState;
4902             mScreenState = state;
4903             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
4904                     + ", newState=" + Display.stateToString(state));
4905 
4906             if (state != Display.STATE_UNKNOWN) {
4907                 int stepState = state-1;
4908                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
4909                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
4910                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
4911                 } else {
4912                     Slog.wtf(TAG, "Unexpected screen state: " + state);
4913                 }
4914             }
4915 
4916             final long elapsedRealtime = mClocks.elapsedRealtime();
4917             final long uptime = mClocks.uptimeMillis();
4918 
4919             boolean updateHistory = false;
4920             if (isScreenDoze(state)) {
4921                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
4922                 mScreenDozeTimer.startRunningLocked(elapsedRealtime);
4923                 updateHistory = true;
4924             } else if (isScreenDoze(oldState)) {
4925                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
4926                 mScreenDozeTimer.stopRunningLocked(elapsedRealtime);
4927                 updateHistory = true;
4928             }
4929             if (isScreenOn(state)) {
4930                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
4931                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
4932                         + Integer.toHexString(mHistoryCur.states));
4933                 mScreenOnTimer.startRunningLocked(elapsedRealtime);
4934                 if (mScreenBrightnessBin >= 0) {
4935                     mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
4936                 }
4937                 updateHistory = true;
4938             } else if (isScreenOn(oldState)) {
4939                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
4940                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
4941                         + Integer.toHexString(mHistoryCur.states));
4942                 mScreenOnTimer.stopRunningLocked(elapsedRealtime);
4943                 if (mScreenBrightnessBin >= 0) {
4944                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4945                 }
4946                 updateHistory = true;
4947             }
4948             if (updateHistory) {
4949                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
4950                         + Display.stateToString(state));
4951                 addHistoryRecordLocked(elapsedRealtime, uptime);
4952             }
4953             mExternalSync.scheduleCpuSyncDueToScreenStateChange(
4954                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
4955             if (isScreenOn(state)) {
4956                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4957                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4958                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
4959                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
4960                         elapsedRealtime, uptime);
4961             } else if (isScreenOn(oldState)) {
4962                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
4963                         elapsedRealtime, uptime);
4964                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4965                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4966             }
4967             // Update discharge amounts.
4968             if (mOnBatteryInternal) {
4969                 updateDischargeScreenLevelsLocked(oldState, state);
4970             }
4971         }
4972     }
4973 
noteScreenBrightnessLocked(int brightness)4974     public void noteScreenBrightnessLocked(int brightness) {
4975         // Bin the brightness.
4976         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
4977         if (bin < 0) bin = 0;
4978         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
4979         if (mScreenBrightnessBin != bin) {
4980             final long elapsedRealtime = mClocks.elapsedRealtime();
4981             final long uptime = mClocks.uptimeMillis();
4982             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
4983                     | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
4984             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
4985                     + Integer.toHexString(mHistoryCur.states));
4986             addHistoryRecordLocked(elapsedRealtime, uptime);
4987             if (mScreenState == Display.STATE_ON) {
4988                 if (mScreenBrightnessBin >= 0) {
4989                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4990                 }
4991                 mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
4992             }
4993             mScreenBrightnessBin = bin;
4994         }
4995     }
4996 
noteUserActivityLocked(int uid, int event)4997     public void noteUserActivityLocked(int uid, int event) {
4998         if (mOnBatteryInternal) {
4999             uid = mapUid(uid);
5000             getUidStatsLocked(uid).noteUserActivityLocked(event);
5001         }
5002     }
5003 
noteWakeUpLocked(String reason, int reasonUid)5004     public void noteWakeUpLocked(String reason, int reasonUid) {
5005         final long elapsedRealtime = mClocks.elapsedRealtime();
5006         final long uptime = mClocks.uptimeMillis();
5007         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
5008                 reason, reasonUid);
5009     }
5010 
noteInteractiveLocked(boolean interactive)5011     public void noteInteractiveLocked(boolean interactive) {
5012         if (mInteractive != interactive) {
5013             final long elapsedRealtime = mClocks.elapsedRealtime();
5014             mInteractive = interactive;
5015             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
5016             if (interactive) {
5017                 mInteractiveTimer.startRunningLocked(elapsedRealtime);
5018             } else {
5019                 mInteractiveTimer.stopRunningLocked(elapsedRealtime);
5020             }
5021         }
5022     }
5023 
noteConnectivityChangedLocked(int type, String extra)5024     public void noteConnectivityChangedLocked(int type, String extra) {
5025         final long elapsedRealtime = mClocks.elapsedRealtime();
5026         final long uptime = mClocks.uptimeMillis();
5027         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
5028                 extra, type);
5029         mNumConnectivityChange++;
5030     }
5031 
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5032     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
5033             final long uptimeMillis, int uid) {
5034         uid = mapUid(uid);
5035         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5036                 uid);
5037         getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
5038     }
5039 
5040     /**
5041      * Updates the radio power state and returns true if an external stats collection should occur.
5042      */
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)5043     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
5044         final long elapsedRealtime = mClocks.elapsedRealtime();
5045         final long uptime = mClocks.uptimeMillis();
5046         if (mMobileRadioPowerState != powerState) {
5047             long realElapsedRealtimeMs;
5048             final boolean active =
5049                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5050                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5051             if (active) {
5052                 if (uid > 0) {
5053                     noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid);
5054                 }
5055 
5056                 mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
5057                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
5058             } else {
5059                 realElapsedRealtimeMs = timestampNs / (1000*1000);
5060                 long lastUpdateTimeMs = mMobileRadioActiveStartTime;
5061                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
5062                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
5063                             + " is before start time " + lastUpdateTimeMs);
5064                     realElapsedRealtimeMs = elapsedRealtime;
5065                 } else if (realElapsedRealtimeMs < elapsedRealtime) {
5066                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
5067                             - realElapsedRealtimeMs);
5068                 }
5069                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
5070             }
5071             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
5072                     + Integer.toHexString(mHistoryCur.states));
5073             addHistoryRecordLocked(elapsedRealtime, uptime);
5074             mMobileRadioPowerState = powerState;
5075             StatsLog.write_non_chained(StatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null,
5076                     powerState);
5077             if (active) {
5078                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
5079                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
5080             } else {
5081                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
5082                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
5083                 // Tell the caller to collect radio network/power stats.
5084                 return true;
5085             }
5086         }
5087         return false;
5088     }
5089 
notePowerSaveModeLocked(boolean enabled)5090     public void notePowerSaveModeLocked(boolean enabled) {
5091         if (mPowerSaveModeEnabled != enabled) {
5092             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
5093             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
5094             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
5095             final long elapsedRealtime = mClocks.elapsedRealtime();
5096             final long uptime = mClocks.uptimeMillis();
5097             mPowerSaveModeEnabled = enabled;
5098             if (enabled) {
5099                 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
5100                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
5101                         + Integer.toHexString(mHistoryCur.states2));
5102                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
5103             } else {
5104                 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
5105                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
5106                         + Integer.toHexString(mHistoryCur.states2));
5107                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
5108             }
5109             addHistoryRecordLocked(elapsedRealtime, uptime);
5110             StatsLog.write(StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ?
5111                     StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON :
5112                     StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
5113         }
5114     }
5115 
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid)5116     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
5117         final long elapsedRealtime = mClocks.elapsedRealtime();
5118         final long uptime = mClocks.uptimeMillis();
5119         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
5120         if (mDeviceIdling && !nowIdling && activeReason == null) {
5121             // We don't go out of general idling mode until explicitly taken out of
5122             // device idle through going active or significant motion.
5123             nowIdling = true;
5124         }
5125         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
5126         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
5127             // We don't go out of general light idling mode until explicitly taken out of
5128             // device idle through going active or significant motion.
5129             nowLightIdling = true;
5130         }
5131         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
5132             addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
5133                     activeReason, activeUid);
5134         }
5135         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
5136             int statsmode;
5137             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
5138             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
5139             else                     statsmode = DEVICE_IDLE_MODE_OFF;
5140             StatsLog.write(StatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
5141         }
5142         if (mDeviceIdling != nowIdling) {
5143             mDeviceIdling = nowIdling;
5144             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
5145             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
5146             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
5147             if (nowIdling) {
5148                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
5149             } else {
5150                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
5151             }
5152         }
5153         if (mDeviceLightIdling != nowLightIdling) {
5154             mDeviceLightIdling = nowLightIdling;
5155             if (nowLightIdling) {
5156                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
5157             } else {
5158                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
5159             }
5160         }
5161         if (mDeviceIdleMode != mode) {
5162             mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
5163                     | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
5164             if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
5165                     + Integer.toHexString(mHistoryCur.states2));
5166             addHistoryRecordLocked(elapsedRealtime, uptime);
5167             long lastDuration = elapsedRealtime - mLastIdleTimeStart;
5168             mLastIdleTimeStart = elapsedRealtime;
5169             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
5170                 if (lastDuration > mLongestLightIdleTime) {
5171                     mLongestLightIdleTime = lastDuration;
5172                 }
5173                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
5174             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
5175                 if (lastDuration > mLongestFullIdleTime) {
5176                     mLongestFullIdleTime = lastDuration;
5177                 }
5178                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
5179             }
5180             if (mode == DEVICE_IDLE_MODE_LIGHT) {
5181                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
5182             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
5183                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
5184             }
5185             mDeviceIdleMode = mode;
5186             StatsLog.write(StatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
5187         }
5188     }
5189 
notePackageInstalledLocked(String pkgName, long versionCode)5190     public void notePackageInstalledLocked(String pkgName, long versionCode) {
5191         final long elapsedRealtime = mClocks.elapsedRealtime();
5192         final long uptime = mClocks.uptimeMillis();
5193         // XXX need to figure out what to do with long version codes.
5194         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
5195                 pkgName, (int)versionCode);
5196         PackageChange pc = new PackageChange();
5197         pc.mPackageName = pkgName;
5198         pc.mUpdate = true;
5199         pc.mVersionCode = versionCode;
5200         addPackageChange(pc);
5201     }
5202 
notePackageUninstalledLocked(String pkgName)5203     public void notePackageUninstalledLocked(String pkgName) {
5204         final long elapsedRealtime = mClocks.elapsedRealtime();
5205         final long uptime = mClocks.uptimeMillis();
5206         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
5207                 pkgName, 0);
5208         PackageChange pc = new PackageChange();
5209         pc.mPackageName = pkgName;
5210         pc.mUpdate = true;
5211         addPackageChange(pc);
5212     }
5213 
addPackageChange(PackageChange pc)5214     private void addPackageChange(PackageChange pc) {
5215         if (mDailyPackageChanges == null) {
5216             mDailyPackageChanges = new ArrayList<>();
5217         }
5218         mDailyPackageChanges.add(pc);
5219     }
5220 
stopAllGpsSignalQualityTimersLocked(int except)5221     void stopAllGpsSignalQualityTimersLocked(int except) {
5222         final long elapsedRealtime = mClocks.elapsedRealtime();
5223         for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
5224             if (i == except) {
5225                 continue;
5226             }
5227             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
5228                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
5229             }
5230         }
5231     }
5232 
notePhoneOnLocked()5233     public void notePhoneOnLocked() {
5234         if (!mPhoneOn) {
5235             final long elapsedRealtime = mClocks.elapsedRealtime();
5236             final long uptime = mClocks.uptimeMillis();
5237             mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5238             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
5239                     + Integer.toHexString(mHistoryCur.states));
5240             addHistoryRecordLocked(elapsedRealtime, uptime);
5241             mPhoneOn = true;
5242             mPhoneOnTimer.startRunningLocked(elapsedRealtime);
5243         }
5244     }
5245 
notePhoneOffLocked()5246     public void notePhoneOffLocked() {
5247         if (mPhoneOn) {
5248             final long elapsedRealtime = mClocks.elapsedRealtime();
5249             final long uptime = mClocks.uptimeMillis();
5250             mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5251             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
5252                     + Integer.toHexString(mHistoryCur.states));
5253             addHistoryRecordLocked(elapsedRealtime, uptime);
5254             mPhoneOn = false;
5255             mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
5256         }
5257     }
5258 
registerUsbStateReceiver(Context context)5259     private void registerUsbStateReceiver(Context context) {
5260         final IntentFilter usbStateFilter = new IntentFilter();
5261         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
5262         context.registerReceiver(new BroadcastReceiver() {
5263             @Override
5264             public void onReceive(Context context, Intent intent) {
5265                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
5266                 synchronized (BatteryStatsImpl.this) {
5267                     noteUsbConnectionStateLocked(state);
5268                 }
5269             }
5270         }, usbStateFilter);
5271         synchronized (this) {
5272             if (mUsbDataState == USB_DATA_UNKNOWN) {
5273                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
5274                 final boolean initState = usbState != null && usbState.getBooleanExtra(
5275                         UsbManager.USB_CONNECTED, false);
5276                 noteUsbConnectionStateLocked(initState);
5277             }
5278         }
5279     }
5280 
noteUsbConnectionStateLocked(boolean connected)5281     private void noteUsbConnectionStateLocked(boolean connected) {
5282         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
5283         if (mUsbDataState != newState) {
5284             mUsbDataState = newState;
5285             if (connected) {
5286                 mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5287             } else {
5288                 mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5289             }
5290             addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5291         }
5292     }
5293 
stopAllPhoneSignalStrengthTimersLocked(int except)5294     void stopAllPhoneSignalStrengthTimersLocked(int except) {
5295         final long elapsedRealtime = mClocks.elapsedRealtime();
5296         for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
5297             if (i == except) {
5298                 continue;
5299             }
5300             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
5301                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5302             }
5303         }
5304     }
5305 
fixPhoneServiceState(int state, int signalBin)5306     private int fixPhoneServiceState(int state, int signalBin) {
5307         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
5308             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5309             // to infer that we are scanning from other data.
5310             if (state == ServiceState.STATE_OUT_OF_SERVICE
5311                     && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5312                 state = ServiceState.STATE_IN_SERVICE;
5313             }
5314         }
5315 
5316         return state;
5317     }
5318 
updateAllPhoneStateLocked(int state, int simState, int strengthBin)5319     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
5320         boolean scanning = false;
5321         boolean newHistory = false;
5322 
5323         mPhoneServiceStateRaw = state;
5324         mPhoneSimStateRaw = simState;
5325         mPhoneSignalStrengthBinRaw = strengthBin;
5326 
5327         final long elapsedRealtime = mClocks.elapsedRealtime();
5328         final long uptime = mClocks.uptimeMillis();
5329 
5330         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
5331             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5332             // to infer that we are scanning from other data.
5333             if (state == ServiceState.STATE_OUT_OF_SERVICE
5334                     && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5335                 state = ServiceState.STATE_IN_SERVICE;
5336             }
5337         }
5338 
5339         // If the phone is powered off, stop all timers.
5340         if (state == ServiceState.STATE_POWER_OFF) {
5341             strengthBin = -1;
5342 
5343         // If we are in service, make sure the correct signal string timer is running.
5344         } else if (state == ServiceState.STATE_IN_SERVICE) {
5345             // Bin will be changed below.
5346 
5347         // If we're out of service, we are in the lowest signal strength
5348         // bin and have the scanning bit set.
5349         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
5350             scanning = true;
5351             strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
5352             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
5353                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
5354                 newHistory = true;
5355                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
5356                         + Integer.toHexString(mHistoryCur.states));
5357                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
5358             }
5359         }
5360 
5361         if (!scanning) {
5362             // If we are no longer scanning, then stop the scanning timer.
5363             if (mPhoneSignalScanningTimer.isRunningLocked()) {
5364                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
5365                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
5366                         + Integer.toHexString(mHistoryCur.states));
5367                 newHistory = true;
5368                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
5369             }
5370         }
5371 
5372         if (mPhoneServiceState != state) {
5373             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
5374                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
5375             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
5376                     + Integer.toHexString(mHistoryCur.states));
5377             newHistory = true;
5378             mPhoneServiceState = state;
5379         }
5380 
5381         if (mPhoneSignalStrengthBin != strengthBin) {
5382             if (mPhoneSignalStrengthBin >= 0) {
5383                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
5384                         elapsedRealtime);
5385             }
5386             if (strengthBin >= 0) {
5387                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5388                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5389                 }
5390                 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
5391                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
5392                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
5393                         + Integer.toHexString(mHistoryCur.states));
5394                 newHistory = true;
5395                 StatsLog.write(StatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
5396             } else {
5397                 stopAllPhoneSignalStrengthTimersLocked(-1);
5398             }
5399             mPhoneSignalStrengthBin = strengthBin;
5400         }
5401 
5402         if (newHistory) {
5403             addHistoryRecordLocked(elapsedRealtime, uptime);
5404         }
5405     }
5406 
5407     /**
5408      * Telephony stack updates the phone state.
5409      * @param state phone state from ServiceState.getState()
5410      */
notePhoneStateLocked(int state, int simState)5411     public void notePhoneStateLocked(int state, int simState) {
5412         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
5413     }
5414 
notePhoneSignalStrengthLocked(SignalStrength signalStrength)5415     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
5416         // Bin the strength.
5417         int bin = signalStrength.getLevel();
5418         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
5419     }
5420 
notePhoneDataConnectionStateLocked(int dataType, boolean hasData)5421     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
5422         // BatteryStats uses 0 to represent no network type.
5423         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
5424         // Unknown is included in DATA_CONNECTION_OTHER.
5425         int bin = DATA_CONNECTION_NONE;
5426         if (hasData) {
5427             if (dataType > 0 && dataType <= TelephonyManager.MAX_NETWORK_TYPE) {
5428                 bin = dataType;
5429             } else {
5430                 bin = DATA_CONNECTION_OTHER;
5431             }
5432         }
5433         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
5434         if (mPhoneDataConnectionType != bin) {
5435             final long elapsedRealtime = mClocks.elapsedRealtime();
5436             final long uptime = mClocks.uptimeMillis();
5437             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
5438                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
5439             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
5440                     + Integer.toHexString(mHistoryCur.states));
5441             addHistoryRecordLocked(elapsedRealtime, uptime);
5442             if (mPhoneDataConnectionType >= 0) {
5443                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
5444                         elapsedRealtime);
5445             }
5446             mPhoneDataConnectionType = bin;
5447             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
5448         }
5449     }
5450 
noteWifiOnLocked()5451     public void noteWifiOnLocked() {
5452         if (!mWifiOn) {
5453             final long elapsedRealtime = mClocks.elapsedRealtime();
5454             final long uptime = mClocks.uptimeMillis();
5455             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
5456             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
5457                     + Integer.toHexString(mHistoryCur.states));
5458             addHistoryRecordLocked(elapsedRealtime, uptime);
5459             mWifiOn = true;
5460             mWifiOnTimer.startRunningLocked(elapsedRealtime);
5461             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
5462         }
5463     }
5464 
noteWifiOffLocked()5465     public void noteWifiOffLocked() {
5466         final long elapsedRealtime = mClocks.elapsedRealtime();
5467         final long uptime = mClocks.uptimeMillis();
5468         if (mWifiOn) {
5469             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
5470             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
5471                     + Integer.toHexString(mHistoryCur.states));
5472             addHistoryRecordLocked(elapsedRealtime, uptime);
5473             mWifiOn = false;
5474             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
5475             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
5476         }
5477     }
5478 
noteAudioOnLocked(int uid)5479     public void noteAudioOnLocked(int uid) {
5480         uid = mapUid(uid);
5481         final long elapsedRealtime = mClocks.elapsedRealtime();
5482         final long uptime = mClocks.uptimeMillis();
5483         if (mAudioOnNesting == 0) {
5484             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
5485             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
5486                     + Integer.toHexString(mHistoryCur.states));
5487             addHistoryRecordLocked(elapsedRealtime, uptime);
5488             mAudioOnTimer.startRunningLocked(elapsedRealtime);
5489         }
5490         mAudioOnNesting++;
5491         getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
5492     }
5493 
noteAudioOffLocked(int uid)5494     public void noteAudioOffLocked(int uid) {
5495         if (mAudioOnNesting == 0) {
5496             return;
5497         }
5498         uid = mapUid(uid);
5499         final long elapsedRealtime = mClocks.elapsedRealtime();
5500         final long uptime = mClocks.uptimeMillis();
5501         if (--mAudioOnNesting == 0) {
5502             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5503             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5504                     + Integer.toHexString(mHistoryCur.states));
5505             addHistoryRecordLocked(elapsedRealtime, uptime);
5506             mAudioOnTimer.stopRunningLocked(elapsedRealtime);
5507         }
5508         getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
5509     }
5510 
noteVideoOnLocked(int uid)5511     public void noteVideoOnLocked(int uid) {
5512         uid = mapUid(uid);
5513         final long elapsedRealtime = mClocks.elapsedRealtime();
5514         final long uptime = mClocks.uptimeMillis();
5515         if (mVideoOnNesting == 0) {
5516             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
5517             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
5518                     + Integer.toHexString(mHistoryCur.states));
5519             addHistoryRecordLocked(elapsedRealtime, uptime);
5520             mVideoOnTimer.startRunningLocked(elapsedRealtime);
5521         }
5522         mVideoOnNesting++;
5523         getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
5524     }
5525 
noteVideoOffLocked(int uid)5526     public void noteVideoOffLocked(int uid) {
5527         if (mVideoOnNesting == 0) {
5528             return;
5529         }
5530         uid = mapUid(uid);
5531         final long elapsedRealtime = mClocks.elapsedRealtime();
5532         final long uptime = mClocks.uptimeMillis();
5533         if (--mVideoOnNesting == 0) {
5534             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5535             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5536                     + Integer.toHexString(mHistoryCur.states));
5537             addHistoryRecordLocked(elapsedRealtime, uptime);
5538             mVideoOnTimer.stopRunningLocked(elapsedRealtime);
5539         }
5540         getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
5541     }
5542 
noteResetAudioLocked()5543     public void noteResetAudioLocked() {
5544         if (mAudioOnNesting > 0) {
5545             final long elapsedRealtime = mClocks.elapsedRealtime();
5546             final long uptime = mClocks.uptimeMillis();
5547             mAudioOnNesting = 0;
5548             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5549             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5550                     + Integer.toHexString(mHistoryCur.states));
5551             addHistoryRecordLocked(elapsedRealtime, uptime);
5552             mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
5553             for (int i=0; i<mUidStats.size(); i++) {
5554                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5555                 uid.noteResetAudioLocked(elapsedRealtime);
5556             }
5557         }
5558     }
5559 
noteResetVideoLocked()5560     public void noteResetVideoLocked() {
5561         if (mVideoOnNesting > 0) {
5562             final long elapsedRealtime = mClocks.elapsedRealtime();
5563             final long uptime = mClocks.uptimeMillis();
5564             mAudioOnNesting = 0;
5565             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5566             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5567                     + Integer.toHexString(mHistoryCur.states));
5568             addHistoryRecordLocked(elapsedRealtime, uptime);
5569             mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
5570             for (int i=0; i<mUidStats.size(); i++) {
5571                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5572                 uid.noteResetVideoLocked(elapsedRealtime);
5573             }
5574         }
5575     }
5576 
noteActivityResumedLocked(int uid)5577     public void noteActivityResumedLocked(int uid) {
5578         uid = mapUid(uid);
5579         getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
5580     }
5581 
noteActivityPausedLocked(int uid)5582     public void noteActivityPausedLocked(int uid) {
5583         uid = mapUid(uid);
5584         getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
5585     }
5586 
noteVibratorOnLocked(int uid, long durationMillis)5587     public void noteVibratorOnLocked(int uid, long durationMillis) {
5588         uid = mapUid(uid);
5589         getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
5590     }
5591 
noteVibratorOffLocked(int uid)5592     public void noteVibratorOffLocked(int uid) {
5593         uid = mapUid(uid);
5594         getUidStatsLocked(uid).noteVibratorOffLocked();
5595     }
5596 
noteFlashlightOnLocked(int uid)5597     public void noteFlashlightOnLocked(int uid) {
5598         uid = mapUid(uid);
5599         final long elapsedRealtime = mClocks.elapsedRealtime();
5600         final long uptime = mClocks.uptimeMillis();
5601         if (mFlashlightOnNesting++ == 0) {
5602             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
5603             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
5604                     + Integer.toHexString(mHistoryCur.states2));
5605             addHistoryRecordLocked(elapsedRealtime, uptime);
5606             mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
5607         }
5608         getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
5609     }
5610 
noteFlashlightOffLocked(int uid)5611     public void noteFlashlightOffLocked(int uid) {
5612         if (mFlashlightOnNesting == 0) {
5613             return;
5614         }
5615         uid = mapUid(uid);
5616         final long elapsedRealtime = mClocks.elapsedRealtime();
5617         final long uptime = mClocks.uptimeMillis();
5618         if (--mFlashlightOnNesting == 0) {
5619             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5620             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5621                     + Integer.toHexString(mHistoryCur.states2));
5622             addHistoryRecordLocked(elapsedRealtime, uptime);
5623             mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
5624         }
5625         getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
5626     }
5627 
noteCameraOnLocked(int uid)5628     public void noteCameraOnLocked(int uid) {
5629         uid = mapUid(uid);
5630         final long elapsedRealtime = mClocks.elapsedRealtime();
5631         final long uptime = mClocks.uptimeMillis();
5632         if (mCameraOnNesting++ == 0) {
5633             mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
5634             if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
5635                     + Integer.toHexString(mHistoryCur.states2));
5636             addHistoryRecordLocked(elapsedRealtime, uptime);
5637             mCameraOnTimer.startRunningLocked(elapsedRealtime);
5638         }
5639         getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
5640     }
5641 
noteCameraOffLocked(int uid)5642     public void noteCameraOffLocked(int uid) {
5643         if (mCameraOnNesting == 0) {
5644             return;
5645         }
5646         uid = mapUid(uid);
5647         final long elapsedRealtime = mClocks.elapsedRealtime();
5648         final long uptime = mClocks.uptimeMillis();
5649         if (--mCameraOnNesting == 0) {
5650             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5651             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5652                     + Integer.toHexString(mHistoryCur.states2));
5653             addHistoryRecordLocked(elapsedRealtime, uptime);
5654             mCameraOnTimer.stopRunningLocked(elapsedRealtime);
5655         }
5656         getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
5657     }
5658 
noteResetCameraLocked()5659     public void noteResetCameraLocked() {
5660         if (mCameraOnNesting > 0) {
5661             final long elapsedRealtime = mClocks.elapsedRealtime();
5662             final long uptime = mClocks.uptimeMillis();
5663             mCameraOnNesting = 0;
5664             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5665             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5666                     + Integer.toHexString(mHistoryCur.states2));
5667             addHistoryRecordLocked(elapsedRealtime, uptime);
5668             mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
5669             for (int i=0; i<mUidStats.size(); i++) {
5670                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5671                 uid.noteResetCameraLocked(elapsedRealtime);
5672             }
5673         }
5674     }
5675 
noteResetFlashlightLocked()5676     public void noteResetFlashlightLocked() {
5677         if (mFlashlightOnNesting > 0) {
5678             final long elapsedRealtime = mClocks.elapsedRealtime();
5679             final long uptime = mClocks.uptimeMillis();
5680             mFlashlightOnNesting = 0;
5681             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5682             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5683                     + Integer.toHexString(mHistoryCur.states2));
5684             addHistoryRecordLocked(elapsedRealtime, uptime);
5685             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
5686             for (int i=0; i<mUidStats.size(); i++) {
5687                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5688                 uid.noteResetFlashlightLocked(elapsedRealtime);
5689             }
5690         }
5691     }
5692 
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized)5693     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
5694             boolean isUnoptimized) {
5695         uid = getAttributionUid(uid, workChain);
5696         final long elapsedRealtime = mClocks.elapsedRealtime();
5697         final long uptime = mClocks.uptimeMillis();
5698         if (mBluetoothScanNesting == 0) {
5699             mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5700             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
5701                     + Integer.toHexString(mHistoryCur.states2));
5702             addHistoryRecordLocked(elapsedRealtime, uptime);
5703             mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
5704         }
5705         mBluetoothScanNesting++;
5706         getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized);
5707     }
5708 
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)5709     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5710         final int N = ws.size();
5711         for (int i = 0; i < N; i++) {
5712             noteBluetoothScanStartedLocked(null, ws.get(i), isUnoptimized);
5713         }
5714 
5715         final List<WorkChain> workChains = ws.getWorkChains();
5716         if (workChains != null) {
5717             for (int i = 0; i < workChains.size(); ++i) {
5718                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized);
5719             }
5720         }
5721     }
5722 
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized)5723     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
5724             boolean isUnoptimized) {
5725         uid = getAttributionUid(uid, workChain);
5726         final long elapsedRealtime = mClocks.elapsedRealtime();
5727         final long uptime = mClocks.uptimeMillis();
5728         mBluetoothScanNesting--;
5729         if (mBluetoothScanNesting == 0) {
5730             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5731             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
5732                     + Integer.toHexString(mHistoryCur.states2));
5733             addHistoryRecordLocked(elapsedRealtime, uptime);
5734             mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
5735         }
5736         getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime, isUnoptimized);
5737     }
5738 
getAttributionUid(int uid, WorkChain workChain)5739     private int getAttributionUid(int uid, WorkChain workChain) {
5740         if (workChain != null) {
5741             return mapUid(workChain.getAttributionUid());
5742         }
5743 
5744         return mapUid(uid);
5745     }
5746 
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)5747     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5748         final int N = ws.size();
5749         for (int i = 0; i < N; i++) {
5750             noteBluetoothScanStoppedLocked(null, ws.get(i), isUnoptimized);
5751         }
5752 
5753         final List<WorkChain> workChains = ws.getWorkChains();
5754         if (workChains != null) {
5755             for (int i = 0; i < workChains.size(); ++i) {
5756                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized);
5757             }
5758         }
5759     }
5760 
noteResetBluetoothScanLocked()5761     public void noteResetBluetoothScanLocked() {
5762         if (mBluetoothScanNesting > 0) {
5763             final long elapsedRealtime = mClocks.elapsedRealtime();
5764             final long uptime = mClocks.uptimeMillis();
5765             mBluetoothScanNesting = 0;
5766             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5767             if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
5768                     + Integer.toHexString(mHistoryCur.states2));
5769             addHistoryRecordLocked(elapsedRealtime, uptime);
5770             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
5771             for (int i=0; i<mUidStats.size(); i++) {
5772                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5773                 uid.noteResetBluetoothScanLocked(elapsedRealtime);
5774             }
5775         }
5776     }
5777 
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)5778     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
5779         final int N = ws.size();
5780         for (int i = 0; i < N; i++) {
5781             int uid = mapUid(ws.get(i));
5782             getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5783             StatsLog.write_non_chained(StatsLog.BLE_SCAN_RESULT_RECEIVED, ws.get(i), ws.getName(i),
5784                     numNewResults);
5785         }
5786 
5787         final List<WorkChain> workChains = ws.getWorkChains();
5788         if (workChains != null) {
5789             for (int i = 0; i < workChains.size(); ++i) {
5790                 final WorkChain wc = workChains.get(i);
5791                 int uid = mapUid(wc.getAttributionUid());
5792                 getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5793                 StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED,
5794                         wc.getUids(), wc.getTags(), numNewResults);
5795             }
5796         }
5797     }
5798 
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5799     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
5800             final long uptimeMillis, int uid) {
5801         uid = mapUid(uid);
5802         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5803                 uid);
5804         getUidStatsLocked(uid).noteWifiRadioApWakeupLocked();
5805     }
5806 
noteWifiRadioPowerState(int powerState, long timestampNs, int uid)5807     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
5808         final long elapsedRealtime = mClocks.elapsedRealtime();
5809         final long uptime = mClocks.uptimeMillis();
5810         if (mWifiRadioPowerState != powerState) {
5811             final boolean active =
5812                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5813                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5814             if (active) {
5815                 if (uid > 0) {
5816                     noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid);
5817                 }
5818                 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5819                 mWifiActiveTimer.startRunningLocked(elapsedRealtime);
5820             } else {
5821                 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5822                 mWifiActiveTimer.stopRunningLocked(
5823                     timestampNs / (1000 * 1000));
5824             }
5825             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
5826                     + Integer.toHexString(mHistoryCur.states));
5827             addHistoryRecordLocked(elapsedRealtime, uptime);
5828             mWifiRadioPowerState = powerState;
5829             StatsLog.write_non_chained(StatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null,
5830                     powerState);
5831         }
5832     }
5833 
noteWifiRunningLocked(WorkSource ws)5834     public void noteWifiRunningLocked(WorkSource ws) {
5835         if (!mGlobalWifiRunning) {
5836             final long elapsedRealtime = mClocks.elapsedRealtime();
5837             final long uptime = mClocks.uptimeMillis();
5838             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5839             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
5840                     + Integer.toHexString(mHistoryCur.states));
5841             addHistoryRecordLocked(elapsedRealtime, uptime);
5842             mGlobalWifiRunning = true;
5843             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
5844             int N = ws.size();
5845             for (int i=0; i<N; i++) {
5846                 int uid = mapUid(ws.get(i));
5847                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5848             }
5849 
5850             List<WorkChain> workChains = ws.getWorkChains();
5851             if (workChains != null) {
5852                 for (int i = 0; i < workChains.size(); ++i) {
5853                     int uid = mapUid(workChains.get(i).getAttributionUid());
5854                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5855                 }
5856             }
5857 
5858             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
5859         } else {
5860             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
5861         }
5862     }
5863 
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs)5864     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
5865         if (mGlobalWifiRunning) {
5866             final long elapsedRealtime = mClocks.elapsedRealtime();
5867             int N = oldWs.size();
5868             for (int i=0; i<N; i++) {
5869                 int uid = mapUid(oldWs.get(i));
5870                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5871             }
5872 
5873             List<WorkChain> workChains = oldWs.getWorkChains();
5874             if (workChains != null) {
5875                 for (int i = 0; i < workChains.size(); ++i) {
5876                     int uid = mapUid(workChains.get(i).getAttributionUid());
5877                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5878                 }
5879             }
5880 
5881             N = newWs.size();
5882             for (int i=0; i<N; i++) {
5883                 int uid = mapUid(newWs.get(i));
5884                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5885             }
5886 
5887             workChains = newWs.getWorkChains();
5888             if (workChains != null) {
5889                 for (int i = 0; i < workChains.size(); ++i) {
5890                     int uid = mapUid(workChains.get(i).getAttributionUid());
5891                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5892                 }
5893             }
5894         } else {
5895             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
5896         }
5897     }
5898 
noteWifiStoppedLocked(WorkSource ws)5899     public void noteWifiStoppedLocked(WorkSource ws) {
5900         if (mGlobalWifiRunning) {
5901             final long elapsedRealtime = mClocks.elapsedRealtime();
5902             final long uptime = mClocks.uptimeMillis();
5903             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5904             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
5905                     + Integer.toHexString(mHistoryCur.states));
5906             addHistoryRecordLocked(elapsedRealtime, uptime);
5907             mGlobalWifiRunning = false;
5908             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
5909             int N = ws.size();
5910             for (int i=0; i<N; i++) {
5911                 int uid = mapUid(ws.get(i));
5912                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5913             }
5914 
5915             List<WorkChain> workChains = ws.getWorkChains();
5916             if (workChains != null) {
5917                 for (int i = 0; i < workChains.size(); ++i) {
5918                     int uid = mapUid(workChains.get(i).getAttributionUid());
5919                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5920                 }
5921             }
5922 
5923             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
5924         } else {
5925             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
5926         }
5927     }
5928 
noteWifiStateLocked(int wifiState, String accessPoint)5929     public void noteWifiStateLocked(int wifiState, String accessPoint) {
5930         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
5931         if (mWifiState != wifiState) {
5932             final long elapsedRealtime = mClocks.elapsedRealtime();
5933             if (mWifiState >= 0) {
5934                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
5935             }
5936             mWifiState = wifiState;
5937             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
5938             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
5939         }
5940     }
5941 
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth)5942     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
5943         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
5944         if (mWifiSupplState != supplState) {
5945             final long elapsedRealtime = mClocks.elapsedRealtime();
5946             final long uptime = mClocks.uptimeMillis();
5947             if (mWifiSupplState >= 0) {
5948                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
5949             }
5950             mWifiSupplState = supplState;
5951             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
5952             mHistoryCur.states2 =
5953                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
5954                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
5955             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
5956                     + Integer.toHexString(mHistoryCur.states2));
5957             addHistoryRecordLocked(elapsedRealtime, uptime);
5958         }
5959     }
5960 
stopAllWifiSignalStrengthTimersLocked(int except)5961     void stopAllWifiSignalStrengthTimersLocked(int except) {
5962         final long elapsedRealtime = mClocks.elapsedRealtime();
5963         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
5964             if (i == except) {
5965                 continue;
5966             }
5967             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
5968                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5969             }
5970         }
5971     }
5972 
noteWifiRssiChangedLocked(int newRssi)5973     public void noteWifiRssiChangedLocked(int newRssi) {
5974         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
5975         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
5976         if (mWifiSignalStrengthBin != strengthBin) {
5977             final long elapsedRealtime = mClocks.elapsedRealtime();
5978             final long uptime = mClocks.uptimeMillis();
5979             if (mWifiSignalStrengthBin >= 0) {
5980                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
5981                         elapsedRealtime);
5982             }
5983             if (strengthBin >= 0) {
5984                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5985                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5986                 }
5987                 mHistoryCur.states2 =
5988                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
5989                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
5990                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
5991                         + Integer.toHexString(mHistoryCur.states2));
5992                 addHistoryRecordLocked(elapsedRealtime, uptime);
5993             } else {
5994                 stopAllWifiSignalStrengthTimersLocked(-1);
5995             }
5996             StatsLog.write(StatsLog.WIFI_SIGNAL_STRENGTH_CHANGED, strengthBin);
5997             mWifiSignalStrengthBin = strengthBin;
5998         }
5999     }
6000 
6001     int mWifiFullLockNesting = 0;
6002 
noteFullWifiLockAcquiredLocked(int uid)6003     public void noteFullWifiLockAcquiredLocked(int uid) {
6004         final long elapsedRealtime = mClocks.elapsedRealtime();
6005         final long uptime = mClocks.uptimeMillis();
6006         if (mWifiFullLockNesting == 0) {
6007             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
6008             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
6009                     + Integer.toHexString(mHistoryCur.states));
6010             addHistoryRecordLocked(elapsedRealtime, uptime);
6011         }
6012         mWifiFullLockNesting++;
6013         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
6014     }
6015 
noteFullWifiLockReleasedLocked(int uid)6016     public void noteFullWifiLockReleasedLocked(int uid) {
6017         final long elapsedRealtime = mClocks.elapsedRealtime();
6018         final long uptime = mClocks.uptimeMillis();
6019         mWifiFullLockNesting--;
6020         if (mWifiFullLockNesting == 0) {
6021             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
6022             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
6023                     + Integer.toHexString(mHistoryCur.states));
6024             addHistoryRecordLocked(elapsedRealtime, uptime);
6025         }
6026         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
6027     }
6028 
6029     int mWifiScanNesting = 0;
6030 
noteWifiScanStartedLocked(int uid)6031     public void noteWifiScanStartedLocked(int uid) {
6032         final long elapsedRealtime = mClocks.elapsedRealtime();
6033         final long uptime = mClocks.uptimeMillis();
6034         if (mWifiScanNesting == 0) {
6035             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
6036             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
6037                     + Integer.toHexString(mHistoryCur.states));
6038             addHistoryRecordLocked(elapsedRealtime, uptime);
6039         }
6040         mWifiScanNesting++;
6041         getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
6042     }
6043 
noteWifiScanStoppedLocked(int uid)6044     public void noteWifiScanStoppedLocked(int uid) {
6045         final long elapsedRealtime = mClocks.elapsedRealtime();
6046         final long uptime = mClocks.uptimeMillis();
6047         mWifiScanNesting--;
6048         if (mWifiScanNesting == 0) {
6049             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
6050             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
6051                     + Integer.toHexString(mHistoryCur.states));
6052             addHistoryRecordLocked(elapsedRealtime, uptime);
6053         }
6054         getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
6055     }
6056 
noteWifiBatchedScanStartedLocked(int uid, int csph)6057     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
6058         uid = mapUid(uid);
6059         final long elapsedRealtime = mClocks.elapsedRealtime();
6060         getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
6061     }
6062 
noteWifiBatchedScanStoppedLocked(int uid)6063     public void noteWifiBatchedScanStoppedLocked(int uid) {
6064         uid = mapUid(uid);
6065         final long elapsedRealtime = mClocks.elapsedRealtime();
6066         getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
6067     }
6068 
6069     int mWifiMulticastNesting = 0;
6070 
noteWifiMulticastEnabledLocked(int uid)6071     public void noteWifiMulticastEnabledLocked(int uid) {
6072         uid = mapUid(uid);
6073         final long elapsedRealtime = mClocks.elapsedRealtime();
6074         final long uptime = mClocks.uptimeMillis();
6075         if (mWifiMulticastNesting == 0) {
6076             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
6077             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
6078                     + Integer.toHexString(mHistoryCur.states));
6079             addHistoryRecordLocked(elapsedRealtime, uptime);
6080 
6081             // Start Wifi Multicast overall timer
6082             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
6083                 if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
6084                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtime);
6085             }
6086         }
6087         mWifiMulticastNesting++;
6088         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
6089     }
6090 
noteWifiMulticastDisabledLocked(int uid)6091     public void noteWifiMulticastDisabledLocked(int uid) {
6092         uid = mapUid(uid);
6093         final long elapsedRealtime = mClocks.elapsedRealtime();
6094         final long uptime = mClocks.uptimeMillis();
6095         mWifiMulticastNesting--;
6096         if (mWifiMulticastNesting == 0) {
6097             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
6098             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
6099                     + Integer.toHexString(mHistoryCur.states));
6100             addHistoryRecordLocked(elapsedRealtime, uptime);
6101 
6102             // Stop Wifi Multicast overall timer
6103             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
6104                 if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
6105                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtime);
6106             }
6107         }
6108         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
6109     }
6110 
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws)6111     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
6112         int N = ws.size();
6113         for (int i=0; i<N; i++) {
6114             final int uid = mapUid(ws.get(i));
6115             noteFullWifiLockAcquiredLocked(uid);
6116             StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
6117                     StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
6118         }
6119 
6120         final List<WorkChain> workChains = ws.getWorkChains();
6121         if (workChains != null) {
6122             for (int i = 0; i < workChains.size(); ++i) {
6123                 final WorkChain workChain = workChains.get(i);
6124                 final int uid = mapUid(workChain.getAttributionUid());
6125                 noteFullWifiLockAcquiredLocked(uid);
6126                 StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
6127                         workChain.getUids(), workChain.getTags(),
6128                         StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
6129             }
6130         }
6131     }
6132 
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws)6133     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
6134         int N = ws.size();
6135         for (int i=0; i<N; i++) {
6136             final int uid = mapUid(ws.get(i));
6137             noteFullWifiLockReleasedLocked(uid);
6138             StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
6139                     StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
6140         }
6141 
6142         final List<WorkChain> workChains = ws.getWorkChains();
6143         if (workChains != null) {
6144             for (int i = 0; i < workChains.size(); ++i) {
6145                 final WorkChain workChain = workChains.get(i);
6146                 final int uid = mapUid(workChain.getAttributionUid());
6147                 noteFullWifiLockReleasedLocked(uid);
6148                 StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
6149                         workChain.getUids(), workChain.getTags(),
6150                         StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
6151             }
6152         }
6153     }
6154 
noteWifiScanStartedFromSourceLocked(WorkSource ws)6155     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
6156         int N = ws.size();
6157         for (int i=0; i<N; i++) {
6158             final int uid = mapUid(ws.get(i));
6159             noteWifiScanStartedLocked(uid);
6160             StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i),
6161                     StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON);
6162         }
6163 
6164         final List<WorkChain> workChains = ws.getWorkChains();
6165         if (workChains != null) {
6166             for (int i = 0; i < workChains.size(); ++i) {
6167                 final WorkChain workChain = workChains.get(i);
6168                 final int uid = mapUid(workChain.getAttributionUid());
6169                 noteWifiScanStartedLocked(uid);
6170                 StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED, workChain.getUids(),
6171                         workChain.getTags(), StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON);
6172             }
6173         }
6174     }
6175 
noteWifiScanStoppedFromSourceLocked(WorkSource ws)6176     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
6177         int N = ws.size();
6178         for (int i=0; i<N; i++) {
6179             final int uid = mapUid(ws.get(i));
6180             noteWifiScanStoppedLocked(uid);
6181             StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i),
6182                     StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF);
6183         }
6184 
6185         final List<WorkChain> workChains = ws.getWorkChains();
6186         if (workChains != null) {
6187             for (int i = 0; i < workChains.size(); ++i) {
6188                 final WorkChain workChain = workChains.get(i);
6189                 final int uid = mapUid(workChain.getAttributionUid());
6190                 noteWifiScanStoppedLocked(uid);
6191                 StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED,
6192                         workChain.getUids(), workChain.getTags(),
6193                         StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF);
6194             }
6195         }
6196     }
6197 
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph)6198     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
6199         int N = ws.size();
6200         for (int i=0; i<N; i++) {
6201             noteWifiBatchedScanStartedLocked(ws.get(i), csph);
6202         }
6203 
6204         final List<WorkChain> workChains = ws.getWorkChains();
6205         if (workChains != null) {
6206             for (int i = 0; i < workChains.size(); ++i) {
6207                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph);
6208             }
6209         }
6210     }
6211 
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws)6212     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
6213         int N = ws.size();
6214         for (int i=0; i<N; i++) {
6215             noteWifiBatchedScanStoppedLocked(ws.get(i));
6216         }
6217 
6218         final List<WorkChain> workChains = ws.getWorkChains();
6219         if (workChains != null) {
6220             for (int i = 0; i < workChains.size(); ++i) {
6221                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid());
6222             }
6223         }
6224     }
6225 
includeInStringArray(String[] array, String str)6226     private static String[] includeInStringArray(String[] array, String str) {
6227         if (ArrayUtils.indexOf(array, str) >= 0) {
6228             return array;
6229         }
6230         String[] newArray = new String[array.length+1];
6231         System.arraycopy(array, 0, newArray, 0, array.length);
6232         newArray[array.length] = str;
6233         return newArray;
6234     }
6235 
excludeFromStringArray(String[] array, String str)6236     private static String[] excludeFromStringArray(String[] array, String str) {
6237         int index = ArrayUtils.indexOf(array, str);
6238         if (index >= 0) {
6239             String[] newArray = new String[array.length-1];
6240             if (index > 0) {
6241                 System.arraycopy(array, 0, newArray, 0, index);
6242             }
6243             if (index < array.length-1) {
6244                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
6245             }
6246             return newArray;
6247         }
6248         return array;
6249     }
6250 
noteNetworkInterfaceTypeLocked(String iface, int networkType)6251     public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
6252         if (TextUtils.isEmpty(iface)) return;
6253 
6254         synchronized (mModemNetworkLock) {
6255             if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
6256                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
6257                 if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
6258             } else {
6259                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
6260                 if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
6261             }
6262         }
6263 
6264         synchronized (mWifiNetworkLock) {
6265             if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
6266                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
6267                 if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
6268             } else {
6269                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
6270                 if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
6271             }
6272         }
6273     }
6274 
getWifiIfaces()6275     public String[] getWifiIfaces() {
6276         synchronized (mWifiNetworkLock) {
6277             return mWifiIfaces;
6278         }
6279     }
6280 
getMobileIfaces()6281     public String[] getMobileIfaces() {
6282         synchronized (mModemNetworkLock) {
6283             return mModemIfaces;
6284         }
6285     }
6286 
getScreenOnTime(long elapsedRealtimeUs, int which)6287     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
6288         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6289     }
6290 
getScreenOnCount(int which)6291     @Override public int getScreenOnCount(int which) {
6292         return mScreenOnTimer.getCountLocked(which);
6293     }
6294 
getScreenDozeTime(long elapsedRealtimeUs, int which)6295     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
6296         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6297     }
6298 
getScreenDozeCount(int which)6299     @Override public int getScreenDozeCount(int which) {
6300         return mScreenDozeTimer.getCountLocked(which);
6301     }
6302 
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)6303     @Override public long getScreenBrightnessTime(int brightnessBin,
6304             long elapsedRealtimeUs, int which) {
6305         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
6306                 elapsedRealtimeUs, which);
6307     }
6308 
getScreenBrightnessTimer(int brightnessBin)6309     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
6310         return mScreenBrightnessTimer[brightnessBin];
6311     }
6312 
getInteractiveTime(long elapsedRealtimeUs, int which)6313     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
6314         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6315     }
6316 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)6317     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
6318         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6319     }
6320 
getPowerSaveModeEnabledCount(int which)6321     @Override public int getPowerSaveModeEnabledCount(int which) {
6322         return mPowerSaveModeEnabledTimer.getCountLocked(which);
6323     }
6324 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)6325     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
6326             int which) {
6327         switch (mode) {
6328             case DEVICE_IDLE_MODE_LIGHT:
6329                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6330             case DEVICE_IDLE_MODE_DEEP:
6331                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6332         }
6333         return 0;
6334     }
6335 
getDeviceIdleModeCount(int mode, int which)6336     @Override public int getDeviceIdleModeCount(int mode, int which) {
6337         switch (mode) {
6338             case DEVICE_IDLE_MODE_LIGHT:
6339                 return mDeviceIdleModeLightTimer.getCountLocked(which);
6340             case DEVICE_IDLE_MODE_DEEP:
6341                 return mDeviceIdleModeFullTimer.getCountLocked(which);
6342         }
6343         return 0;
6344     }
6345 
getLongestDeviceIdleModeTime(int mode)6346     @Override public long getLongestDeviceIdleModeTime(int mode) {
6347         switch (mode) {
6348             case DEVICE_IDLE_MODE_LIGHT:
6349                 return mLongestLightIdleTime;
6350             case DEVICE_IDLE_MODE_DEEP:
6351                 return mLongestFullIdleTime;
6352         }
6353         return 0;
6354     }
6355 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)6356     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
6357         switch (mode) {
6358             case DEVICE_IDLE_MODE_LIGHT:
6359                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6360             case DEVICE_IDLE_MODE_DEEP:
6361                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6362         }
6363         return 0;
6364     }
6365 
getDeviceIdlingCount(int mode, int which)6366     @Override public int getDeviceIdlingCount(int mode, int which) {
6367         switch (mode) {
6368             case DEVICE_IDLE_MODE_LIGHT:
6369                 return mDeviceLightIdlingTimer.getCountLocked(which);
6370             case DEVICE_IDLE_MODE_DEEP:
6371                 return mDeviceIdlingTimer.getCountLocked(which);
6372         }
6373         return 0;
6374     }
6375 
getNumConnectivityChange(int which)6376     @Override public int getNumConnectivityChange(int which) {
6377         int val = mNumConnectivityChange;
6378         if (which == STATS_CURRENT) {
6379             val -= mLoadedNumConnectivityChange;
6380         } else if (which == STATS_SINCE_UNPLUGGED) {
6381             val -= mUnpluggedNumConnectivityChange;
6382         }
6383         return val;
6384     }
6385 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)6386     @Override public long getGpsSignalQualityTime(int strengthBin,
6387         long elapsedRealtimeUs, int which) {
6388         if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
6389             return 0;
6390         }
6391         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
6392             elapsedRealtimeUs, which);
6393     }
6394 
getGpsBatteryDrainMaMs()6395     @Override public long getGpsBatteryDrainMaMs() {
6396         final double opVolt = mPowerProfile.getAveragePower(
6397             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
6398         if (opVolt == 0) {
6399             return 0;
6400         }
6401         double energyUsedMaMs = 0.0;
6402         final int which = STATS_SINCE_CHARGED;
6403         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
6404         for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
6405             energyUsedMaMs
6406                 += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
6407                 * (getGpsSignalQualityTime(i, rawRealtime, which) / 1000);
6408         }
6409         return (long) energyUsedMaMs;
6410     }
6411 
getPhoneOnTime(long elapsedRealtimeUs, int which)6412     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
6413         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6414     }
6415 
getPhoneOnCount(int which)6416     @Override public int getPhoneOnCount(int which) {
6417         return mPhoneOnTimer.getCountLocked(which);
6418     }
6419 
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)6420     @Override public long getPhoneSignalStrengthTime(int strengthBin,
6421             long elapsedRealtimeUs, int which) {
6422         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6423                 elapsedRealtimeUs, which);
6424     }
6425 
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)6426     @Override public long getPhoneSignalScanningTime(
6427             long elapsedRealtimeUs, int which) {
6428         return mPhoneSignalScanningTimer.getTotalTimeLocked(
6429                 elapsedRealtimeUs, which);
6430     }
6431 
getPhoneSignalScanningTimer()6432     @Override public Timer getPhoneSignalScanningTimer() {
6433         return mPhoneSignalScanningTimer;
6434     }
6435 
getPhoneSignalStrengthCount(int strengthBin, int which)6436     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
6437         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
6438     }
6439 
getPhoneSignalStrengthTimer(int strengthBin)6440     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
6441         return mPhoneSignalStrengthsTimer[strengthBin];
6442     }
6443 
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)6444     @Override public long getPhoneDataConnectionTime(int dataType,
6445             long elapsedRealtimeUs, int which) {
6446         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
6447                 elapsedRealtimeUs, which);
6448     }
6449 
getPhoneDataConnectionCount(int dataType, int which)6450     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
6451         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
6452     }
6453 
getPhoneDataConnectionTimer(int dataType)6454     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
6455         return mPhoneDataConnectionsTimer[dataType];
6456     }
6457 
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)6458     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
6459         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6460     }
6461 
getMobileRadioActiveCount(int which)6462     @Override public int getMobileRadioActiveCount(int which) {
6463         return mMobileRadioActiveTimer.getCountLocked(which);
6464     }
6465 
getMobileRadioActiveAdjustedTime(int which)6466     @Override public long getMobileRadioActiveAdjustedTime(int which) {
6467         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
6468     }
6469 
getMobileRadioActiveUnknownTime(int which)6470     @Override public long getMobileRadioActiveUnknownTime(int which) {
6471         return mMobileRadioActiveUnknownTime.getCountLocked(which);
6472     }
6473 
getMobileRadioActiveUnknownCount(int which)6474     @Override public int getMobileRadioActiveUnknownCount(int which) {
6475         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
6476     }
6477 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)6478     @Override public long getWifiMulticastWakelockTime(
6479             long elapsedRealtimeUs, int which) {
6480         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
6481                 elapsedRealtimeUs, which);
6482     }
6483 
getWifiMulticastWakelockCount(int which)6484     @Override public int getWifiMulticastWakelockCount(int which) {
6485         return mWifiMulticastWakelockTimer.getCountLocked(which);
6486     }
6487 
getWifiOnTime(long elapsedRealtimeUs, int which)6488     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
6489         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6490     }
6491 
getWifiActiveTime(long elapsedRealtimeUs, int which)6492     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
6493         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6494     }
6495 
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)6496     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
6497         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6498     }
6499 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)6500     @Override public long getWifiStateTime(int wifiState,
6501             long elapsedRealtimeUs, int which) {
6502         return mWifiStateTimer[wifiState].getTotalTimeLocked(
6503                 elapsedRealtimeUs, which);
6504     }
6505 
getWifiStateCount(int wifiState, int which)6506     @Override public int getWifiStateCount(int wifiState, int which) {
6507         return mWifiStateTimer[wifiState].getCountLocked(which);
6508     }
6509 
getWifiStateTimer(int wifiState)6510     @Override public Timer getWifiStateTimer(int wifiState) {
6511         return mWifiStateTimer[wifiState];
6512     }
6513 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)6514     @Override public long getWifiSupplStateTime(int state,
6515             long elapsedRealtimeUs, int which) {
6516         return mWifiSupplStateTimer[state].getTotalTimeLocked(
6517                 elapsedRealtimeUs, which);
6518     }
6519 
getWifiSupplStateCount(int state, int which)6520     @Override public int getWifiSupplStateCount(int state, int which) {
6521         return mWifiSupplStateTimer[state].getCountLocked(which);
6522     }
6523 
getWifiSupplStateTimer(int state)6524     @Override public Timer getWifiSupplStateTimer(int state) {
6525         return mWifiSupplStateTimer[state];
6526     }
6527 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)6528     @Override public long getWifiSignalStrengthTime(int strengthBin,
6529             long elapsedRealtimeUs, int which) {
6530         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6531                 elapsedRealtimeUs, which);
6532     }
6533 
getWifiSignalStrengthCount(int strengthBin, int which)6534     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
6535         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
6536     }
6537 
getWifiSignalStrengthTimer(int strengthBin)6538     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
6539         return mWifiSignalStrengthsTimer[strengthBin];
6540     }
6541 
6542     @Override
getBluetoothControllerActivity()6543     public ControllerActivityCounter getBluetoothControllerActivity() {
6544         return mBluetoothActivity;
6545     }
6546 
6547     @Override
getWifiControllerActivity()6548     public ControllerActivityCounter getWifiControllerActivity() {
6549         return mWifiActivity;
6550     }
6551 
6552     @Override
getModemControllerActivity()6553     public ControllerActivityCounter getModemControllerActivity() {
6554         return mModemActivity;
6555     }
6556 
6557     @Override
hasBluetoothActivityReporting()6558     public boolean hasBluetoothActivityReporting() {
6559         return mHasBluetoothReporting;
6560     }
6561 
6562     @Override
hasWifiActivityReporting()6563     public boolean hasWifiActivityReporting() {
6564         return mHasWifiReporting;
6565     }
6566 
6567     @Override
hasModemActivityReporting()6568     public boolean hasModemActivityReporting() {
6569         return mHasModemReporting;
6570     }
6571 
6572     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)6573     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
6574         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6575     }
6576 
6577     @Override
getFlashlightOnCount(int which)6578     public long getFlashlightOnCount(int which) {
6579         return mFlashlightOnTimer.getCountLocked(which);
6580     }
6581 
6582     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)6583     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
6584         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6585     }
6586 
6587     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)6588     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
6589         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6590     }
6591 
6592     @Override
getNetworkActivityBytes(int type, int which)6593     public long getNetworkActivityBytes(int type, int which) {
6594         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
6595             return mNetworkByteActivityCounters[type].getCountLocked(which);
6596         } else {
6597             return 0;
6598         }
6599     }
6600 
6601     @Override
getNetworkActivityPackets(int type, int which)6602     public long getNetworkActivityPackets(int type, int which) {
6603         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
6604             return mNetworkPacketActivityCounters[type].getCountLocked(which);
6605         } else {
6606             return 0;
6607         }
6608     }
6609 
getStartClockTime()6610     @Override public long getStartClockTime() {
6611         final long currentTime = System.currentTimeMillis();
6612         if (ensureStartClockTime(currentTime)) {
6613             recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
6614                     mClocks.uptimeMillis());
6615         }
6616         return mStartClockTime;
6617     }
6618 
getStartPlatformVersion()6619     @Override public String getStartPlatformVersion() {
6620         return mStartPlatformVersion;
6621     }
6622 
getEndPlatformVersion()6623     @Override public String getEndPlatformVersion() {
6624         return mEndPlatformVersion;
6625     }
6626 
getParcelVersion()6627     @Override public int getParcelVersion() {
6628         return VERSION;
6629     }
6630 
getIsOnBattery()6631     @Override public boolean getIsOnBattery() {
6632         return mOnBattery;
6633     }
6634 
getUidStats()6635     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
6636         return mUidStats;
6637     }
6638 
detachTimerIfNotNull(BatteryStatsImpl.Timer timer)6639     private static void detachTimerIfNotNull(BatteryStatsImpl.Timer timer) {
6640         if (timer != null) {
6641             timer.detach();
6642         }
6643     }
6644 
resetTimerIfNotNull(BatteryStatsImpl.Timer timer, boolean detachIfReset)6645     private static boolean resetTimerIfNotNull(BatteryStatsImpl.Timer timer,
6646             boolean detachIfReset) {
6647         if (timer != null) {
6648             return timer.reset(detachIfReset);
6649         }
6650         return true;
6651     }
6652 
resetTimerIfNotNull(DualTimer timer, boolean detachIfReset)6653     private static boolean resetTimerIfNotNull(DualTimer timer, boolean detachIfReset) {
6654         if (timer != null) {
6655             return timer.reset(detachIfReset);
6656         }
6657         return true;
6658     }
6659 
detachLongCounterIfNotNull(LongSamplingCounter counter)6660     private static void detachLongCounterIfNotNull(LongSamplingCounter counter) {
6661         if (counter != null) {
6662             counter.detach();
6663         }
6664     }
6665 
resetLongCounterIfNotNull(LongSamplingCounter counter, boolean detachIfReset)6666     private static void resetLongCounterIfNotNull(LongSamplingCounter counter,
6667             boolean detachIfReset) {
6668         if (counter != null) {
6669             counter.reset(detachIfReset);
6670         }
6671     }
6672 
6673     /**
6674      * The statistics associated with a particular uid.
6675      */
6676     public static class Uid extends BatteryStats.Uid {
6677         /**
6678          * BatteryStatsImpl that we are associated with.
6679          */
6680         protected BatteryStatsImpl mBsi;
6681 
6682         final int mUid;
6683 
6684         /** TimeBase for when uid is in background and device is on battery. */
6685         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6686         public final TimeBase mOnBatteryBackgroundTimeBase;
6687         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6688         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
6689 
6690         boolean mWifiRunning;
6691         StopwatchTimer mWifiRunningTimer;
6692 
6693         boolean mFullWifiLockOut;
6694         StopwatchTimer mFullWifiLockTimer;
6695 
6696         boolean mWifiScanStarted;
6697         DualTimer mWifiScanTimer;
6698 
6699         static final int NO_BATCHED_SCAN_STARTED = -1;
6700         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
6701         StopwatchTimer[] mWifiBatchedScanTimer;
6702 
6703         boolean mWifiMulticastEnabled;
6704         StopwatchTimer mWifiMulticastTimer;
6705 
6706         StopwatchTimer mAudioTurnedOnTimer;
6707         StopwatchTimer mVideoTurnedOnTimer;
6708         StopwatchTimer mFlashlightTurnedOnTimer;
6709         StopwatchTimer mCameraTurnedOnTimer;
6710         StopwatchTimer mForegroundActivityTimer;
6711         StopwatchTimer mForegroundServiceTimer;
6712         /** Total time spent by the uid holding any partial wakelocks. */
6713         DualTimer mAggregatedPartialWakelockTimer;
6714         DualTimer mBluetoothScanTimer;
6715         DualTimer mBluetoothUnoptimizedScanTimer;
6716         Counter mBluetoothScanResultCounter;
6717         Counter mBluetoothScanResultBgCounter;
6718 
6719         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
6720         StopwatchTimer[] mProcessStateTimer;
6721 
6722         boolean mInForegroundService = false;
6723 
6724         BatchTimer mVibratorOnTimer;
6725 
6726         Counter[] mUserActivityCounters;
6727 
6728         LongSamplingCounter[] mNetworkByteActivityCounters;
6729         LongSamplingCounter[] mNetworkPacketActivityCounters;
6730         LongSamplingCounter mMobileRadioActiveTime;
6731         LongSamplingCounter mMobileRadioActiveCount;
6732 
6733         /**
6734          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
6735          */
6736         private LongSamplingCounter mMobileRadioApWakeupCount;
6737 
6738         /**
6739          * How many times this UID woke up the Application Processor due to a Wifi packet.
6740          */
6741         private LongSamplingCounter mWifiRadioApWakeupCount;
6742 
6743         /**
6744          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
6745          * Can be null if the UID has had no such activity.
6746          */
6747         private ControllerActivityCounterImpl mWifiControllerActivity;
6748 
6749         /**
6750          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
6751          * Can be null if the UID has had no such activity.
6752          */
6753         private ControllerActivityCounterImpl mBluetoothControllerActivity;
6754 
6755         /**
6756          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
6757          * Can be null if the UID has had no such activity.
6758          */
6759         private ControllerActivityCounterImpl mModemControllerActivity;
6760 
6761         /**
6762          * The CPU times we had at the last history details update.
6763          */
6764         long mLastStepUserTime;
6765         long mLastStepSystemTime;
6766         long mCurStepUserTime;
6767         long mCurStepSystemTime;
6768 
6769         LongSamplingCounter mUserCpuTime;
6770         LongSamplingCounter mSystemCpuTime;
6771         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
6772         LongSamplingCounter mCpuActiveTimeMs;
6773 
6774         LongSamplingCounterArray mCpuFreqTimeMs;
6775         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
6776         LongSamplingCounterArray mCpuClusterTimesMs;
6777 
6778         LongSamplingCounterArray[] mProcStateTimeMs;
6779         LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
6780 
6781         IntArray mChildUids;
6782 
6783         /**
6784          * The statistics we have collected for this uid's wake locks.
6785          */
6786         final OverflowArrayMap<Wakelock> mWakelockStats;
6787 
6788         /**
6789          * The statistics we have collected for this uid's syncs.
6790          */
6791         final OverflowArrayMap<DualTimer> mSyncStats;
6792 
6793         /**
6794          * The statistics we have collected for this uid's jobs.
6795          */
6796         final OverflowArrayMap<DualTimer> mJobStats;
6797 
6798         /**
6799          * Count of the jobs that have completed and the reasons why they completed.
6800          */
6801         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
6802 
6803         /**
6804          * Count of app launch events that had associated deferred job counts or info about
6805          * last time a job was run.
6806          */
6807         Counter mJobsDeferredEventCount;
6808 
6809         /**
6810          * Count of deferred jobs that were pending when the app was launched or brought to
6811          * the foreground through a user interaction.
6812          */
6813         Counter mJobsDeferredCount;
6814 
6815         /**
6816          * Sum of time since the last time a job was run for this app before it was launched.
6817          */
6818         LongSamplingCounter mJobsFreshnessTimeMs;
6819 
6820         /**
6821          * Array of counts of instances where the time since the last job was run for the app
6822          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
6823          */
6824         final Counter[] mJobsFreshnessBuckets;
6825 
6826         /**
6827          * The statistics we have collected for this uid's sensor activations.
6828          */
6829         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
6830 
6831         /**
6832          * The statistics we have collected for this uid's processes.
6833          */
6834         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
6835 
6836         /**
6837          * The statistics we have collected for this uid's processes.
6838          */
6839         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
6840 
6841         /**
6842          * The transient wake stats we have collected for this uid's pids.
6843          */
6844         final SparseArray<Pid> mPids = new SparseArray<>();
6845 
Uid(BatteryStatsImpl bsi, int uid)6846         public Uid(BatteryStatsImpl bsi, int uid) {
6847             mBsi = bsi;
6848             mUid = uid;
6849 
6850             mOnBatteryBackgroundTimeBase = new TimeBase();
6851             mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6852                     mBsi.mClocks.elapsedRealtime() * 1000);
6853 
6854             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase();
6855             mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6856                     mBsi.mClocks.elapsedRealtime() * 1000);
6857 
6858             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6859             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6860             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6861             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
6862 
6863             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
6864                 @Override public Wakelock instantiateObject() {
6865                     return new Wakelock(mBsi, Uid.this);
6866                 }
6867             };
6868             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6869                 @Override public DualTimer instantiateObject() {
6870                     return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
6871                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6872                 }
6873             };
6874             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6875                 @Override public DualTimer instantiateObject() {
6876                     return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
6877                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6878                 }
6879             };
6880 
6881             mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
6882                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
6883             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
6884                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
6885             mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
6886                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6887             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
6888             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
6889                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
6890             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
6891             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
6892             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
6893             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6894             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
6895         }
6896 
6897         @VisibleForTesting
setProcessStateForTest(int procState)6898         public void setProcessStateForTest(int procState) {
6899             mProcessState = procState;
6900         }
6901 
6902         @Override
getCpuFreqTimes(int which)6903         public long[] getCpuFreqTimes(int which) {
6904             return nullIfAllZeros(mCpuFreqTimeMs, which);
6905         }
6906 
6907         @Override
getScreenOffCpuFreqTimes(int which)6908         public long[] getScreenOffCpuFreqTimes(int which) {
6909             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
6910         }
6911 
6912         @Override
getCpuActiveTime()6913         public long getCpuActiveTime() {
6914             return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
6915         }
6916 
6917         @Override
getCpuClusterTimes()6918         public long[] getCpuClusterTimes() {
6919             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
6920         }
6921 
6922 
6923         @Override
getCpuFreqTimes(int which, int procState)6924         public long[] getCpuFreqTimes(int which, int procState) {
6925             if (which < 0 || which >= NUM_PROCESS_STATE) {
6926                 return null;
6927             }
6928             if (mProcStateTimeMs == null) {
6929                 return null;
6930             }
6931             if (!mBsi.mPerProcStateCpuTimesAvailable) {
6932                 mProcStateTimeMs = null;
6933                 return null;
6934             }
6935             return nullIfAllZeros(mProcStateTimeMs[procState], which);
6936         }
6937 
6938         @Override
getScreenOffCpuFreqTimes(int which, int procState)6939         public long[] getScreenOffCpuFreqTimes(int which, int procState) {
6940             if (which < 0 || which >= NUM_PROCESS_STATE) {
6941                 return null;
6942             }
6943             if (mProcStateScreenOffTimeMs == null) {
6944                 return null;
6945             }
6946             if (!mBsi.mPerProcStateCpuTimesAvailable) {
6947                 mProcStateScreenOffTimeMs = null;
6948                 return null;
6949             }
6950             return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which);
6951         }
6952 
addIsolatedUid(int isolatedUid)6953         public void addIsolatedUid(int isolatedUid) {
6954             if (mChildUids == null) {
6955                 mChildUids = new IntArray();
6956             } else if (mChildUids.indexOf(isolatedUid) >= 0) {
6957                 return;
6958             }
6959             mChildUids.add(isolatedUid);
6960         }
6961 
removeIsolatedUid(int isolatedUid)6962         public void removeIsolatedUid(int isolatedUid) {
6963             final int idx = mChildUids == null ? -1 : mChildUids.indexOf(isolatedUid);
6964             if (idx < 0) {
6965                 return;
6966             }
6967             mChildUids.remove(idx);
6968         }
6969 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)6970         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
6971             if (cpuTimesMs == null) {
6972                 return null;
6973             }
6974             final long[] counts = cpuTimesMs.getCountsLocked(which);
6975             if (counts == null) {
6976                 return null;
6977             }
6978             // Return counts only if at least one of the elements is non-zero.
6979             for (int i = counts.length - 1; i >= 0; --i) {
6980                 if (counts[i] != 0) {
6981                     return counts;
6982                 }
6983             }
6984             return null;
6985         }
6986 
addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery)6987         private void addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery) {
6988             if (mProcStateTimeMs == null) {
6989                 mProcStateTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
6990             }
6991             if (mProcStateTimeMs[procState] == null
6992                     || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
6993                 mProcStateTimeMs[procState] = new LongSamplingCounterArray(
6994                         mBsi.mOnBatteryTimeBase);
6995             }
6996             mProcStateTimeMs[procState].addCountLocked(cpuTimesMs, onBattery);
6997         }
6998 
addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs, boolean onBatteryScreenOff)6999         private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs,
7000                 boolean onBatteryScreenOff) {
7001             if (mProcStateScreenOffTimeMs == null) {
7002                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
7003             }
7004             if (mProcStateScreenOffTimeMs[procState] == null
7005                     || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) {
7006                 mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
7007                         mBsi.mOnBatteryScreenOffTimeBase);
7008             }
7009             mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs, onBatteryScreenOff);
7010         }
7011 
7012         @Override
getAggregatedPartialWakelockTimer()7013         public Timer getAggregatedPartialWakelockTimer() {
7014             return mAggregatedPartialWakelockTimer;
7015         }
7016 
7017         @Override
getWakelockStats()7018         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
7019             return mWakelockStats.getMap();
7020         }
7021 
7022         @Override
getMulticastWakelockStats()7023         public Timer getMulticastWakelockStats() {
7024             return mWifiMulticastTimer;
7025         }
7026 
7027         @Override
getSyncStats()7028         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
7029             return mSyncStats.getMap();
7030         }
7031 
7032         @Override
getJobStats()7033         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
7034             return mJobStats.getMap();
7035         }
7036 
7037         @Override
getJobCompletionStats()7038         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
7039             return mJobCompletions;
7040         }
7041 
7042         @Override
getSensorStats()7043         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
7044             return mSensorStats;
7045         }
7046 
7047         @Override
getProcessStats()7048         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
7049             return mProcessStats;
7050         }
7051 
7052         @Override
getPackageStats()7053         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
7054             return mPackageStats;
7055         }
7056 
7057         @Override
getUid()7058         public int getUid() {
7059             return mUid;
7060         }
7061 
7062         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)7063         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
7064             if (!mWifiRunning) {
7065                 mWifiRunning = true;
7066                 if (mWifiRunningTimer == null) {
7067                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
7068                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
7069                 }
7070                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
7071             }
7072         }
7073 
7074         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)7075         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
7076             if (mWifiRunning) {
7077                 mWifiRunning = false;
7078                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
7079             }
7080         }
7081 
7082         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)7083         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
7084             if (!mFullWifiLockOut) {
7085                 mFullWifiLockOut = true;
7086                 if (mFullWifiLockTimer == null) {
7087                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
7088                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
7089                 }
7090                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
7091             }
7092         }
7093 
7094         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)7095         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
7096             if (mFullWifiLockOut) {
7097                 mFullWifiLockOut = false;
7098                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
7099             }
7100         }
7101 
7102         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)7103         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
7104             if (!mWifiScanStarted) {
7105                 mWifiScanStarted = true;
7106                 if (mWifiScanTimer == null) {
7107                     mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
7108                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
7109                             mOnBatteryBackgroundTimeBase);
7110                 }
7111                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
7112             }
7113         }
7114 
7115         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)7116         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
7117             if (mWifiScanStarted) {
7118                 mWifiScanStarted = false;
7119                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
7120             }
7121         }
7122 
7123         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)7124         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
7125             int bin = 0;
7126             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
7127                 csph = csph >> 3;
7128                 bin++;
7129             }
7130 
7131             if (mWifiBatchedScanBinStarted == bin) return;
7132 
7133             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7134                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7135                         stopRunningLocked(elapsedRealtimeMs);
7136             }
7137             mWifiBatchedScanBinStarted = bin;
7138             if (mWifiBatchedScanTimer[bin] == null) {
7139                 makeWifiBatchedScanBin(bin, null);
7140             }
7141             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
7142         }
7143 
7144         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)7145         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
7146             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7147                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7148                         stopRunningLocked(elapsedRealtimeMs);
7149                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7150             }
7151         }
7152 
7153         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)7154         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
7155             if (!mWifiMulticastEnabled) {
7156                 mWifiMulticastEnabled = true;
7157                 if (mWifiMulticastTimer == null) {
7158                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7159                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
7160                 }
7161                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
7162                 StatsLog.write_non_chained(
7163                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null,
7164                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__ON);
7165             }
7166         }
7167 
7168         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)7169         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
7170             if (mWifiMulticastEnabled) {
7171                 mWifiMulticastEnabled = false;
7172                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
7173                 StatsLog.write_non_chained(
7174                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null,
7175                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__OFF);
7176             }
7177         }
7178 
7179         @Override
getWifiControllerActivity()7180         public ControllerActivityCounter getWifiControllerActivity() {
7181             return mWifiControllerActivity;
7182         }
7183 
7184         @Override
getBluetoothControllerActivity()7185         public ControllerActivityCounter getBluetoothControllerActivity() {
7186             return mBluetoothControllerActivity;
7187         }
7188 
7189         @Override
getModemControllerActivity()7190         public ControllerActivityCounter getModemControllerActivity() {
7191             return mModemControllerActivity;
7192         }
7193 
getOrCreateWifiControllerActivityLocked()7194         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
7195             if (mWifiControllerActivity == null) {
7196                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7197                         NUM_BT_TX_LEVELS);
7198             }
7199             return mWifiControllerActivity;
7200         }
7201 
getOrCreateBluetoothControllerActivityLocked()7202         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
7203             if (mBluetoothControllerActivity == null) {
7204                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7205                         NUM_BT_TX_LEVELS);
7206             }
7207             return mBluetoothControllerActivity;
7208         }
7209 
getOrCreateModemControllerActivityLocked()7210         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
7211             if (mModemControllerActivity == null) {
7212                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7213                         ModemActivityInfo.TX_POWER_LEVELS);
7214             }
7215             return mModemControllerActivity;
7216         }
7217 
createAudioTurnedOnTimerLocked()7218         public StopwatchTimer createAudioTurnedOnTimerLocked() {
7219             if (mAudioTurnedOnTimer == null) {
7220                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
7221                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7222             }
7223             return mAudioTurnedOnTimer;
7224         }
7225 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)7226         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
7227             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7228         }
7229 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)7230         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
7231             if (mAudioTurnedOnTimer != null) {
7232                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7233             }
7234         }
7235 
noteResetAudioLocked(long elapsedRealtimeMs)7236         public void noteResetAudioLocked(long elapsedRealtimeMs) {
7237             if (mAudioTurnedOnTimer != null) {
7238                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7239             }
7240         }
7241 
createVideoTurnedOnTimerLocked()7242         public StopwatchTimer createVideoTurnedOnTimerLocked() {
7243             if (mVideoTurnedOnTimer == null) {
7244                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
7245                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7246             }
7247             return mVideoTurnedOnTimer;
7248         }
7249 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)7250         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
7251             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7252         }
7253 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)7254         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
7255             if (mVideoTurnedOnTimer != null) {
7256                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7257             }
7258         }
7259 
noteResetVideoLocked(long elapsedRealtimeMs)7260         public void noteResetVideoLocked(long elapsedRealtimeMs) {
7261             if (mVideoTurnedOnTimer != null) {
7262                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7263             }
7264         }
7265 
createFlashlightTurnedOnTimerLocked()7266         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
7267             if (mFlashlightTurnedOnTimer == null) {
7268                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7269                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7270             }
7271             return mFlashlightTurnedOnTimer;
7272         }
7273 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)7274         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
7275             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7276         }
7277 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)7278         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
7279             if (mFlashlightTurnedOnTimer != null) {
7280                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7281             }
7282         }
7283 
noteResetFlashlightLocked(long elapsedRealtimeMs)7284         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
7285             if (mFlashlightTurnedOnTimer != null) {
7286                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7287             }
7288         }
7289 
createCameraTurnedOnTimerLocked()7290         public StopwatchTimer createCameraTurnedOnTimerLocked() {
7291             if (mCameraTurnedOnTimer == null) {
7292                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
7293                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7294             }
7295             return mCameraTurnedOnTimer;
7296         }
7297 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)7298         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
7299             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7300         }
7301 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)7302         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
7303             if (mCameraTurnedOnTimer != null) {
7304                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7305             }
7306         }
7307 
noteResetCameraLocked(long elapsedRealtimeMs)7308         public void noteResetCameraLocked(long elapsedRealtimeMs) {
7309             if (mCameraTurnedOnTimer != null) {
7310                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7311             }
7312         }
7313 
createForegroundActivityTimerLocked()7314         public StopwatchTimer createForegroundActivityTimerLocked() {
7315             if (mForegroundActivityTimer == null) {
7316                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7317                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
7318             }
7319             return mForegroundActivityTimer;
7320         }
7321 
createForegroundServiceTimerLocked()7322         public StopwatchTimer createForegroundServiceTimerLocked() {
7323             if (mForegroundServiceTimer == null) {
7324                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7325                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
7326             }
7327             return mForegroundServiceTimer;
7328         }
7329 
createAggregatedPartialWakelockTimerLocked()7330         public DualTimer createAggregatedPartialWakelockTimerLocked() {
7331             if (mAggregatedPartialWakelockTimer == null) {
7332                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
7333                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
7334                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
7335             }
7336             return mAggregatedPartialWakelockTimer;
7337         }
7338 
createBluetoothScanTimerLocked()7339         public DualTimer createBluetoothScanTimerLocked() {
7340             if (mBluetoothScanTimer == null) {
7341                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
7342                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
7343                         mOnBatteryBackgroundTimeBase);
7344             }
7345             return mBluetoothScanTimer;
7346         }
7347 
createBluetoothUnoptimizedScanTimerLocked()7348         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
7349             if (mBluetoothUnoptimizedScanTimer == null) {
7350                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
7351                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
7352                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7353             }
7354             return mBluetoothUnoptimizedScanTimer;
7355         }
7356 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)7357         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
7358                 boolean isUnoptimized) {
7359             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7360             if (isUnoptimized) {
7361                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7362             }
7363         }
7364 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)7365         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
7366             if (mBluetoothScanTimer != null) {
7367                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
7368             }
7369             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
7370                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
7371             }
7372         }
7373 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)7374         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
7375             if (mBluetoothScanTimer != null) {
7376                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7377             }
7378             if (mBluetoothUnoptimizedScanTimer != null) {
7379                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7380             }
7381         }
7382 
createBluetoothScanResultCounterLocked()7383         public Counter createBluetoothScanResultCounterLocked() {
7384             if (mBluetoothScanResultCounter == null) {
7385                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
7386             }
7387             return mBluetoothScanResultCounter;
7388         }
7389 
createBluetoothScanResultBgCounterLocked()7390         public Counter createBluetoothScanResultBgCounterLocked() {
7391             if (mBluetoothScanResultBgCounter == null) {
7392                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
7393             }
7394             return mBluetoothScanResultBgCounter;
7395         }
7396 
noteBluetoothScanResultsLocked(int numNewResults)7397         public void noteBluetoothScanResultsLocked(int numNewResults) {
7398             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
7399             // Uses background timebase, so the count will only be incremented if uid in background.
7400             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
7401         }
7402 
7403         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)7404         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
7405             // We always start, since we want multiple foreground PIDs to nest
7406             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
7407         }
7408 
7409         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)7410         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
7411             if (mForegroundActivityTimer != null) {
7412                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
7413             }
7414         }
7415 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)7416         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
7417             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
7418         }
7419 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)7420         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
7421             if (mForegroundServiceTimer != null) {
7422                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
7423             }
7424         }
7425 
createVibratorOnTimerLocked()7426         public BatchTimer createVibratorOnTimerLocked() {
7427             if (mVibratorOnTimer == null) {
7428                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
7429                         mBsi.mOnBatteryTimeBase);
7430             }
7431             return mVibratorOnTimer;
7432         }
7433 
noteVibratorOnLocked(long durationMillis)7434         public void noteVibratorOnLocked(long durationMillis) {
7435             createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
7436         }
7437 
noteVibratorOffLocked()7438         public void noteVibratorOffLocked() {
7439             if (mVibratorOnTimer != null) {
7440                 mVibratorOnTimer.abortLastDuration(mBsi);
7441             }
7442         }
7443 
7444         @Override
getWifiRunningTime(long elapsedRealtimeUs, int which)7445         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
7446             if (mWifiRunningTimer == null) {
7447                 return 0;
7448             }
7449             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7450         }
7451 
7452         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)7453         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
7454             if (mFullWifiLockTimer == null) {
7455                 return 0;
7456             }
7457             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7458         }
7459 
7460         @Override
getWifiScanTime(long elapsedRealtimeUs, int which)7461         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
7462             if (mWifiScanTimer == null) {
7463                 return 0;
7464             }
7465             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7466         }
7467 
7468         @Override
getWifiScanCount(int which)7469         public int getWifiScanCount(int which) {
7470             if (mWifiScanTimer == null) {
7471                 return 0;
7472             }
7473             return mWifiScanTimer.getCountLocked(which);
7474         }
7475 
7476         @Override
getWifiScanTimer()7477         public Timer getWifiScanTimer() {
7478             return mWifiScanTimer;
7479         }
7480 
7481         @Override
getWifiScanBackgroundCount(int which)7482         public int getWifiScanBackgroundCount(int which) {
7483             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7484                 return 0;
7485             }
7486             return mWifiScanTimer.getSubTimer().getCountLocked(which);
7487         }
7488 
7489         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)7490         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
7491             if (mWifiScanTimer == null) {
7492                 return 0;
7493             }
7494             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7495             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7496         }
7497 
7498         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)7499         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
7500             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7501                 return 0;
7502             }
7503             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7504             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7505         }
7506 
7507         @Override
getWifiScanBackgroundTimer()7508         public Timer getWifiScanBackgroundTimer() {
7509             if (mWifiScanTimer == null) {
7510                 return null;
7511             }
7512             return mWifiScanTimer.getSubTimer();
7513         }
7514 
7515         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)7516         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
7517             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7518             if (mWifiBatchedScanTimer[csphBin] == null) {
7519                 return 0;
7520             }
7521             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
7522         }
7523 
7524         @Override
getWifiBatchedScanCount(int csphBin, int which)7525         public int getWifiBatchedScanCount(int csphBin, int which) {
7526             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7527             if (mWifiBatchedScanTimer[csphBin] == null) {
7528                 return 0;
7529             }
7530             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
7531         }
7532 
7533         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)7534         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
7535             if (mWifiMulticastTimer == null) {
7536                 return 0;
7537             }
7538             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7539         }
7540 
7541         @Override
getAudioTurnedOnTimer()7542         public Timer getAudioTurnedOnTimer() {
7543             return mAudioTurnedOnTimer;
7544         }
7545 
7546         @Override
getVideoTurnedOnTimer()7547         public Timer getVideoTurnedOnTimer() {
7548             return mVideoTurnedOnTimer;
7549         }
7550 
7551         @Override
getFlashlightTurnedOnTimer()7552         public Timer getFlashlightTurnedOnTimer() {
7553             return mFlashlightTurnedOnTimer;
7554         }
7555 
7556         @Override
getCameraTurnedOnTimer()7557         public Timer getCameraTurnedOnTimer() {
7558             return mCameraTurnedOnTimer;
7559         }
7560 
7561         @Override
getForegroundActivityTimer()7562         public Timer getForegroundActivityTimer() {
7563             return mForegroundActivityTimer;
7564         }
7565 
7566         @Override
getForegroundServiceTimer()7567         public Timer getForegroundServiceTimer() {
7568             return mForegroundServiceTimer;
7569         }
7570 
7571         @Override
getBluetoothScanTimer()7572         public Timer getBluetoothScanTimer() {
7573             return mBluetoothScanTimer;
7574         }
7575 
7576         @Override
getBluetoothScanBackgroundTimer()7577         public Timer getBluetoothScanBackgroundTimer() {
7578             if (mBluetoothScanTimer == null) {
7579                 return null;
7580             }
7581             return mBluetoothScanTimer.getSubTimer();
7582         }
7583 
7584         @Override
getBluetoothUnoptimizedScanTimer()7585         public Timer getBluetoothUnoptimizedScanTimer() {
7586             return mBluetoothUnoptimizedScanTimer;
7587         }
7588 
7589         @Override
getBluetoothUnoptimizedScanBackgroundTimer()7590         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
7591             if (mBluetoothUnoptimizedScanTimer == null) {
7592                 return null;
7593             }
7594             return mBluetoothUnoptimizedScanTimer.getSubTimer();
7595         }
7596 
7597         @Override
getBluetoothScanResultCounter()7598         public Counter getBluetoothScanResultCounter() {
7599             return mBluetoothScanResultCounter;
7600         }
7601 
7602         @Override
getBluetoothScanResultBgCounter()7603         public Counter getBluetoothScanResultBgCounter() {
7604             return mBluetoothScanResultBgCounter;
7605         }
7606 
makeProcessState(int i, Parcel in)7607         void makeProcessState(int i, Parcel in) {
7608             if (i < 0 || i >= NUM_PROCESS_STATE) return;
7609 
7610             if (in == null) {
7611                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7612                         mBsi.mOnBatteryTimeBase);
7613             } else {
7614                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7615                         mBsi.mOnBatteryTimeBase, in);
7616             }
7617         }
7618 
7619         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)7620         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
7621             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
7622             if (mProcessStateTimer[state] == null) {
7623                 return 0;
7624             }
7625             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
7626         }
7627 
7628         @Override
getProcessStateTimer(int state)7629         public Timer getProcessStateTimer(int state) {
7630             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
7631             return mProcessStateTimer[state];
7632         }
7633 
7634         @Override
getVibratorOnTimer()7635         public Timer getVibratorOnTimer() {
7636             return mVibratorOnTimer;
7637         }
7638 
7639         @Override
noteUserActivityLocked(int type)7640         public void noteUserActivityLocked(int type) {
7641             if (mUserActivityCounters == null) {
7642                 initUserActivityLocked();
7643             }
7644             if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
7645                 mUserActivityCounters[type].stepAtomic();
7646             } else {
7647                 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
7648                         new Throwable());
7649             }
7650         }
7651 
7652         @Override
hasUserActivity()7653         public boolean hasUserActivity() {
7654             return mUserActivityCounters != null;
7655         }
7656 
7657         @Override
getUserActivityCount(int type, int which)7658         public int getUserActivityCount(int type, int which) {
7659             if (mUserActivityCounters == null) {
7660                 return 0;
7661             }
7662             return mUserActivityCounters[type].getCountLocked(which);
7663         }
7664 
makeWifiBatchedScanBin(int i, Parcel in)7665         void makeWifiBatchedScanBin(int i, Parcel in) {
7666             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
7667 
7668             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
7669             if (collected == null) {
7670                 collected = new ArrayList<StopwatchTimer>();
7671                 mBsi.mWifiBatchedScanTimers.put(i, collected);
7672             }
7673             if (in == null) {
7674                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7675                         collected, mBsi.mOnBatteryTimeBase);
7676             } else {
7677                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7678                         collected, mBsi.mOnBatteryTimeBase, in);
7679             }
7680         }
7681 
7682 
initUserActivityLocked()7683         void initUserActivityLocked() {
7684             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
7685             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7686                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
7687             }
7688         }
7689 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)7690         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
7691             if (mNetworkByteActivityCounters == null) {
7692                 initNetworkActivityLocked();
7693             }
7694             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
7695                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
7696                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
7697             } else {
7698                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
7699                         new Throwable());
7700             }
7701         }
7702 
noteMobileRadioActiveTimeLocked(long batteryUptime)7703         void noteMobileRadioActiveTimeLocked(long batteryUptime) {
7704             if (mNetworkByteActivityCounters == null) {
7705                 initNetworkActivityLocked();
7706             }
7707             mMobileRadioActiveTime.addCountLocked(batteryUptime);
7708             mMobileRadioActiveCount.addCountLocked(1);
7709         }
7710 
7711         @Override
hasNetworkActivity()7712         public boolean hasNetworkActivity() {
7713             return mNetworkByteActivityCounters != null;
7714         }
7715 
7716         @Override
getNetworkActivityBytes(int type, int which)7717         public long getNetworkActivityBytes(int type, int which) {
7718             if (mNetworkByteActivityCounters != null && type >= 0
7719                     && type < mNetworkByteActivityCounters.length) {
7720                 return mNetworkByteActivityCounters[type].getCountLocked(which);
7721             } else {
7722                 return 0;
7723             }
7724         }
7725 
7726         @Override
getNetworkActivityPackets(int type, int which)7727         public long getNetworkActivityPackets(int type, int which) {
7728             if (mNetworkPacketActivityCounters != null && type >= 0
7729                     && type < mNetworkPacketActivityCounters.length) {
7730                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
7731             } else {
7732                 return 0;
7733             }
7734         }
7735 
7736         @Override
getMobileRadioActiveTime(int which)7737         public long getMobileRadioActiveTime(int which) {
7738             return mMobileRadioActiveTime != null
7739                     ? mMobileRadioActiveTime.getCountLocked(which) : 0;
7740         }
7741 
7742         @Override
getMobileRadioActiveCount(int which)7743         public int getMobileRadioActiveCount(int which) {
7744             return mMobileRadioActiveCount != null
7745                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
7746         }
7747 
7748         @Override
getUserCpuTimeUs(int which)7749         public long getUserCpuTimeUs(int which) {
7750             return mUserCpuTime.getCountLocked(which);
7751         }
7752 
7753         @Override
getSystemCpuTimeUs(int which)7754         public long getSystemCpuTimeUs(int which) {
7755             return mSystemCpuTime.getCountLocked(which);
7756         }
7757 
7758         @Override
getTimeAtCpuSpeed(int cluster, int step, int which)7759         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
7760             if (mCpuClusterSpeedTimesUs != null) {
7761                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
7762                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
7763                     if (cpuSpeedTimesUs != null) {
7764                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
7765                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
7766                             if (c != null) {
7767                                 return c.getCountLocked(which);
7768                             }
7769                         }
7770                     }
7771                 }
7772             }
7773             return 0;
7774         }
7775 
noteMobileRadioApWakeupLocked()7776         public void noteMobileRadioApWakeupLocked() {
7777             if (mMobileRadioApWakeupCount == null) {
7778                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7779             }
7780             mMobileRadioApWakeupCount.addCountLocked(1);
7781         }
7782 
7783         @Override
getMobileRadioApWakeupCount(int which)7784         public long getMobileRadioApWakeupCount(int which) {
7785             if (mMobileRadioApWakeupCount != null) {
7786                 return mMobileRadioApWakeupCount.getCountLocked(which);
7787             }
7788             return 0;
7789         }
7790 
noteWifiRadioApWakeupLocked()7791         public void noteWifiRadioApWakeupLocked() {
7792             if (mWifiRadioApWakeupCount == null) {
7793                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7794             }
7795             mWifiRadioApWakeupCount.addCountLocked(1);
7796         }
7797 
7798         @Override
getWifiRadioApWakeupCount(int which)7799         public long getWifiRadioApWakeupCount(int which) {
7800             if (mWifiRadioApWakeupCount != null) {
7801                 return mWifiRadioApWakeupCount.getCountLocked(which);
7802             }
7803             return 0;
7804         }
7805 
7806         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)7807         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
7808             sb.setLength(0);
7809             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7810             if (deferredEventCount == 0) {
7811                 return;
7812             }
7813             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7814             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
7815             sb.append(deferredEventCount); sb.append(',');
7816             sb.append(deferredCount); sb.append(',');
7817             sb.append(totalLatency);
7818             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7819                 if (mJobsFreshnessBuckets[i] == null) {
7820                     sb.append(",0");
7821                 } else {
7822                     sb.append(",");
7823                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7824                 }
7825             }
7826         }
7827 
7828         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)7829         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
7830             sb.setLength(0);
7831             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7832             if (deferredEventCount == 0) {
7833                 return;
7834             }
7835             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7836             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
7837             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
7838             sb.append("count="); sb.append(deferredCount); sb.append(", ");
7839             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
7840             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7841                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
7842                 if (mJobsFreshnessBuckets[i] == null) {
7843                     sb.append("0");
7844                 } else {
7845                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7846                 }
7847                 sb.append(" ");
7848             }
7849         }
7850 
initNetworkActivityLocked()7851         void initNetworkActivityLocked() {
7852             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7853             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7854             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7855                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7856                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7857             }
7858             mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7859             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7860         }
7861 
7862         /**
7863          * Clear all stats for this uid.  Returns true if the uid is completely
7864          * inactive so can be dropped.
7865          */
7866         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptime, long realtime)7867         public boolean reset(long uptime, long realtime) {
7868             boolean active = false;
7869 
7870             mOnBatteryBackgroundTimeBase.init(uptime, realtime);
7871             mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
7872 
7873             if (mWifiRunningTimer != null) {
7874                 active |= !mWifiRunningTimer.reset(false);
7875                 active |= mWifiRunning;
7876             }
7877             if (mFullWifiLockTimer != null) {
7878                 active |= !mFullWifiLockTimer.reset(false);
7879                 active |= mFullWifiLockOut;
7880             }
7881             if (mWifiScanTimer != null) {
7882                 active |= !mWifiScanTimer.reset(false);
7883                 active |= mWifiScanStarted;
7884             }
7885             if (mWifiBatchedScanTimer != null) {
7886                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7887                     if (mWifiBatchedScanTimer[i] != null) {
7888                         active |= !mWifiBatchedScanTimer[i].reset(false);
7889                     }
7890                 }
7891                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
7892             }
7893             if (mWifiMulticastTimer != null) {
7894                 active |= !mWifiMulticastTimer.reset(false);
7895                 active |= mWifiMulticastEnabled;
7896             }
7897 
7898             active |= !resetTimerIfNotNull(mAudioTurnedOnTimer, false);
7899             active |= !resetTimerIfNotNull(mVideoTurnedOnTimer, false);
7900             active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false);
7901             active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false);
7902             active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
7903             active |= !resetTimerIfNotNull(mForegroundServiceTimer, false);
7904             active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false);
7905             active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
7906             active |= !resetTimerIfNotNull(mBluetoothUnoptimizedScanTimer, false);
7907             if (mBluetoothScanResultCounter != null) {
7908                 mBluetoothScanResultCounter.reset(false);
7909             }
7910             if (mBluetoothScanResultBgCounter != null) {
7911                 mBluetoothScanResultBgCounter.reset(false);
7912             }
7913 
7914             if (mProcessStateTimer != null) {
7915                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
7916                     if (mProcessStateTimer[i] != null) {
7917                         active |= !mProcessStateTimer[i].reset(false);
7918                     }
7919                 }
7920                 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
7921             }
7922             if (mVibratorOnTimer != null) {
7923                 if (mVibratorOnTimer.reset(false)) {
7924                     mVibratorOnTimer.detach();
7925                     mVibratorOnTimer = null;
7926                 } else {
7927                     active = true;
7928                 }
7929             }
7930 
7931             if (mUserActivityCounters != null) {
7932                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7933                     mUserActivityCounters[i].reset(false);
7934                 }
7935             }
7936 
7937             if (mNetworkByteActivityCounters != null) {
7938                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7939                     mNetworkByteActivityCounters[i].reset(false);
7940                     mNetworkPacketActivityCounters[i].reset(false);
7941                 }
7942                 mMobileRadioActiveTime.reset(false);
7943                 mMobileRadioActiveCount.reset(false);
7944             }
7945 
7946             if (mWifiControllerActivity != null) {
7947                 mWifiControllerActivity.reset(false);
7948             }
7949 
7950             if (mBluetoothControllerActivity != null) {
7951                 mBluetoothControllerActivity.reset(false);
7952             }
7953 
7954             if (mModemControllerActivity != null) {
7955                 mModemControllerActivity.reset(false);
7956             }
7957 
7958             mUserCpuTime.reset(false);
7959             mSystemCpuTime.reset(false);
7960 
7961             if (mCpuClusterSpeedTimesUs != null) {
7962                 for (LongSamplingCounter[] speeds : mCpuClusterSpeedTimesUs) {
7963                     if (speeds != null) {
7964                         for (LongSamplingCounter speed : speeds) {
7965                             if (speed != null) {
7966                                 speed.reset(false);
7967                             }
7968                         }
7969                     }
7970                 }
7971             }
7972 
7973             if (mCpuFreqTimeMs != null) {
7974                 mCpuFreqTimeMs.reset(false);
7975             }
7976             if (mScreenOffCpuFreqTimeMs != null) {
7977                 mScreenOffCpuFreqTimeMs.reset(false);
7978             }
7979 
7980             mCpuActiveTimeMs.reset(false);
7981             mCpuClusterTimesMs.reset(false);
7982 
7983             if (mProcStateTimeMs != null) {
7984                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
7985                     if (counters != null) {
7986                         counters.reset(false);
7987                     }
7988                 }
7989             }
7990             if (mProcStateScreenOffTimeMs != null) {
7991                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
7992                     if (counters != null) {
7993                         counters.reset(false);
7994                     }
7995                 }
7996             }
7997 
7998             resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false);
7999             resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false);
8000 
8001             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8002             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
8003                 Wakelock wl = wakeStats.valueAt(iw);
8004                 if (wl.reset()) {
8005                     wakeStats.removeAt(iw);
8006                 } else {
8007                     active = true;
8008                 }
8009             }
8010             mWakelockStats.cleanup();
8011             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8012             for (int is=syncStats.size()-1; is>=0; is--) {
8013                 DualTimer timer = syncStats.valueAt(is);
8014                 if (timer.reset(false)) {
8015                     syncStats.removeAt(is);
8016                     timer.detach();
8017                 } else {
8018                     active = true;
8019                 }
8020             }
8021             mSyncStats.cleanup();
8022             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8023             for (int ij=jobStats.size()-1; ij>=0; ij--) {
8024                 DualTimer timer = jobStats.valueAt(ij);
8025                 if (timer.reset(false)) {
8026                     jobStats.removeAt(ij);
8027                     timer.detach();
8028                 } else {
8029                     active = true;
8030                 }
8031             }
8032             mJobStats.cleanup();
8033             mJobCompletions.clear();
8034 
8035             mJobsDeferredEventCount.reset(false);
8036             mJobsDeferredCount.reset(false);
8037             mJobsFreshnessTimeMs.reset(false);
8038             for (int ij = 0; ij < JOB_FRESHNESS_BUCKETS.length; ij++) {
8039                 if (mJobsFreshnessBuckets[ij] != null) {
8040                     mJobsFreshnessBuckets[ij].reset(false);
8041                 }
8042             }
8043 
8044             for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
8045                 Sensor s = mSensorStats.valueAt(ise);
8046                 if (s.reset()) {
8047                     mSensorStats.removeAt(ise);
8048                 } else {
8049                     active = true;
8050                 }
8051             }
8052 
8053             for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
8054                 Proc proc = mProcessStats.valueAt(ip);
8055                 proc.detach();
8056             }
8057             mProcessStats.clear();
8058             if (mPids.size() > 0) {
8059                 for (int i=mPids.size()-1; i>=0; i--) {
8060                     Pid pid = mPids.valueAt(i);
8061                     if (pid.mWakeNesting > 0) {
8062                         active = true;
8063                     } else {
8064                         mPids.removeAt(i);
8065                     }
8066                 }
8067             }
8068             if (mPackageStats.size() > 0) {
8069                 Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
8070                 while (it.hasNext()) {
8071                     Map.Entry<String, Pkg> pkgEntry = it.next();
8072                     Pkg p = pkgEntry.getValue();
8073                     p.detach();
8074                     if (p.mServiceStats.size() > 0) {
8075                         Iterator<Map.Entry<String, Pkg.Serv>> it2
8076                                 = p.mServiceStats.entrySet().iterator();
8077                         while (it2.hasNext()) {
8078                             Map.Entry<String, Pkg.Serv> servEntry = it2.next();
8079                             servEntry.getValue().detach();
8080                         }
8081                     }
8082                 }
8083                 mPackageStats.clear();
8084             }
8085 
8086             mLastStepUserTime = mLastStepSystemTime = 0;
8087             mCurStepUserTime = mCurStepSystemTime = 0;
8088 
8089             if (!active) {
8090                 if (mWifiRunningTimer != null) {
8091                     mWifiRunningTimer.detach();
8092                 }
8093                 if (mFullWifiLockTimer != null) {
8094                     mFullWifiLockTimer.detach();
8095                 }
8096                 if (mWifiScanTimer != null) {
8097                     mWifiScanTimer.detach();
8098                 }
8099                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8100                     if (mWifiBatchedScanTimer[i] != null) {
8101                         mWifiBatchedScanTimer[i].detach();
8102                     }
8103                 }
8104                 if (mWifiMulticastTimer != null) {
8105                     mWifiMulticastTimer.detach();
8106                 }
8107                 if (mAudioTurnedOnTimer != null) {
8108                     mAudioTurnedOnTimer.detach();
8109                     mAudioTurnedOnTimer = null;
8110                 }
8111                 if (mVideoTurnedOnTimer != null) {
8112                     mVideoTurnedOnTimer.detach();
8113                     mVideoTurnedOnTimer = null;
8114                 }
8115                 if (mFlashlightTurnedOnTimer != null) {
8116                     mFlashlightTurnedOnTimer.detach();
8117                     mFlashlightTurnedOnTimer = null;
8118                 }
8119                 if (mCameraTurnedOnTimer != null) {
8120                     mCameraTurnedOnTimer.detach();
8121                     mCameraTurnedOnTimer = null;
8122                 }
8123                 if (mForegroundActivityTimer != null) {
8124                     mForegroundActivityTimer.detach();
8125                     mForegroundActivityTimer = null;
8126                 }
8127                 if (mForegroundServiceTimer != null) {
8128                     mForegroundServiceTimer.detach();
8129                     mForegroundServiceTimer = null;
8130                 }
8131                 if (mAggregatedPartialWakelockTimer != null) {
8132                     mAggregatedPartialWakelockTimer.detach();
8133                     mAggregatedPartialWakelockTimer = null;
8134                 }
8135                 if (mBluetoothScanTimer != null) {
8136                     mBluetoothScanTimer.detach();
8137                     mBluetoothScanTimer = null;
8138                 }
8139                 if (mBluetoothUnoptimizedScanTimer != null) {
8140                     mBluetoothUnoptimizedScanTimer.detach();
8141                     mBluetoothUnoptimizedScanTimer = null;
8142                 }
8143                 if (mBluetoothScanResultCounter != null) {
8144                     mBluetoothScanResultCounter.detach();
8145                     mBluetoothScanResultCounter = null;
8146                 }
8147                 if (mBluetoothScanResultBgCounter != null) {
8148                     mBluetoothScanResultBgCounter.detach();
8149                     mBluetoothScanResultBgCounter = null;
8150                 }
8151                 if (mUserActivityCounters != null) {
8152                     for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8153                         mUserActivityCounters[i].detach();
8154                     }
8155                 }
8156                 if (mNetworkByteActivityCounters != null) {
8157                     for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8158                         mNetworkByteActivityCounters[i].detach();
8159                         mNetworkPacketActivityCounters[i].detach();
8160                     }
8161                 }
8162 
8163                 if (mWifiControllerActivity != null) {
8164                     mWifiControllerActivity.detach();
8165                 }
8166 
8167                 if (mBluetoothControllerActivity != null) {
8168                     mBluetoothControllerActivity.detach();
8169                 }
8170 
8171                 if (mModemControllerActivity != null) {
8172                     mModemControllerActivity.detach();
8173                 }
8174 
8175                 mPids.clear();
8176 
8177                 mUserCpuTime.detach();
8178                 mSystemCpuTime.detach();
8179 
8180                 if (mCpuClusterSpeedTimesUs != null) {
8181                     for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
8182                         if (cpuSpeeds != null) {
8183                             for (LongSamplingCounter c : cpuSpeeds) {
8184                                 if (c != null) {
8185                                     c.detach();
8186                                 }
8187                             }
8188                         }
8189                     }
8190                 }
8191 
8192                 if (mCpuFreqTimeMs != null) {
8193                     mCpuFreqTimeMs.detach();
8194                 }
8195                 if (mScreenOffCpuFreqTimeMs != null) {
8196                     mScreenOffCpuFreqTimeMs.detach();
8197                 }
8198                 mCpuActiveTimeMs.detach();
8199                 mCpuClusterTimesMs.detach();
8200 
8201                 if (mProcStateTimeMs != null) {
8202                     for (LongSamplingCounterArray counters : mProcStateTimeMs) {
8203                         if (counters != null) {
8204                             counters.detach();
8205                         }
8206                     }
8207                 }
8208                 if (mProcStateScreenOffTimeMs != null) {
8209                     for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
8210                         if (counters != null) {
8211                             counters.detach();
8212                         }
8213                     }
8214                 }
8215                 detachLongCounterIfNotNull(mMobileRadioApWakeupCount);
8216                 detachLongCounterIfNotNull(mWifiRadioApWakeupCount);
8217             }
8218 
8219             return !active;
8220         }
8221 
writeJobCompletionsToParcelLocked(Parcel out)8222         void writeJobCompletionsToParcelLocked(Parcel out) {
8223             int NJC = mJobCompletions.size();
8224             out.writeInt(NJC);
8225             for (int ijc=0; ijc<NJC; ijc++) {
8226                 out.writeString(mJobCompletions.keyAt(ijc));
8227                 SparseIntArray types = mJobCompletions.valueAt(ijc);
8228                 int NT = types.size();
8229                 out.writeInt(NT);
8230                 for (int it=0; it<NT; it++) {
8231                     out.writeInt(types.keyAt(it));
8232                     out.writeInt(types.valueAt(it));
8233                 }
8234             }
8235         }
8236 
writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs)8237         void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
8238             mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8239             mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8240 
8241             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8242             int NW = wakeStats.size();
8243             out.writeInt(NW);
8244             for (int iw=0; iw<NW; iw++) {
8245                 out.writeString(wakeStats.keyAt(iw));
8246                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
8247                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
8248             }
8249 
8250             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8251             int NS = syncStats.size();
8252             out.writeInt(NS);
8253             for (int is=0; is<NS; is++) {
8254                 out.writeString(syncStats.keyAt(is));
8255                 DualTimer timer = syncStats.valueAt(is);
8256                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8257             }
8258 
8259             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8260             int NJ = jobStats.size();
8261             out.writeInt(NJ);
8262             for (int ij=0; ij<NJ; ij++) {
8263                 out.writeString(jobStats.keyAt(ij));
8264                 DualTimer timer = jobStats.valueAt(ij);
8265                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8266             }
8267 
8268             writeJobCompletionsToParcelLocked(out);
8269 
8270             mJobsDeferredEventCount.writeToParcel(out);
8271             mJobsDeferredCount.writeToParcel(out);
8272             mJobsFreshnessTimeMs.writeToParcel(out);
8273             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8274                 Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
8275             }
8276 
8277             int NSE = mSensorStats.size();
8278             out.writeInt(NSE);
8279             for (int ise=0; ise<NSE; ise++) {
8280                 out.writeInt(mSensorStats.keyAt(ise));
8281                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
8282                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
8283             }
8284 
8285             int NP = mProcessStats.size();
8286             out.writeInt(NP);
8287             for (int ip=0; ip<NP; ip++) {
8288                 out.writeString(mProcessStats.keyAt(ip));
8289                 Uid.Proc proc = mProcessStats.valueAt(ip);
8290                 proc.writeToParcelLocked(out);
8291             }
8292 
8293             out.writeInt(mPackageStats.size());
8294             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
8295                 out.writeString(pkgEntry.getKey());
8296                 Uid.Pkg pkg = pkgEntry.getValue();
8297                 pkg.writeToParcelLocked(out);
8298             }
8299 
8300             if (mWifiRunningTimer != null) {
8301                 out.writeInt(1);
8302                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
8303             } else {
8304                 out.writeInt(0);
8305             }
8306             if (mFullWifiLockTimer != null) {
8307                 out.writeInt(1);
8308                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
8309             } else {
8310                 out.writeInt(0);
8311             }
8312             if (mWifiScanTimer != null) {
8313                 out.writeInt(1);
8314                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
8315             } else {
8316                 out.writeInt(0);
8317             }
8318             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8319                 if (mWifiBatchedScanTimer[i] != null) {
8320                     out.writeInt(1);
8321                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
8322                 } else {
8323                     out.writeInt(0);
8324                 }
8325             }
8326             if (mWifiMulticastTimer != null) {
8327                 out.writeInt(1);
8328                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
8329             } else {
8330                 out.writeInt(0);
8331             }
8332 
8333             if (mAudioTurnedOnTimer != null) {
8334                 out.writeInt(1);
8335                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8336             } else {
8337                 out.writeInt(0);
8338             }
8339             if (mVideoTurnedOnTimer != null) {
8340                 out.writeInt(1);
8341                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8342             } else {
8343                 out.writeInt(0);
8344             }
8345             if (mFlashlightTurnedOnTimer != null) {
8346                 out.writeInt(1);
8347                 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8348             } else {
8349                 out.writeInt(0);
8350             }
8351             if (mCameraTurnedOnTimer != null) {
8352                 out.writeInt(1);
8353                 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8354             } else {
8355                 out.writeInt(0);
8356             }
8357             if (mForegroundActivityTimer != null) {
8358                 out.writeInt(1);
8359                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
8360             } else {
8361                 out.writeInt(0);
8362             }
8363             if (mForegroundServiceTimer != null) {
8364                 out.writeInt(1);
8365                 mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
8366             } else {
8367                 out.writeInt(0);
8368             }
8369             if (mAggregatedPartialWakelockTimer != null) {
8370                 out.writeInt(1);
8371                 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
8372             } else {
8373                 out.writeInt(0);
8374             }
8375             if (mBluetoothScanTimer != null) {
8376                 out.writeInt(1);
8377                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
8378             } else {
8379                 out.writeInt(0);
8380             }
8381             if (mBluetoothUnoptimizedScanTimer != null) {
8382                 out.writeInt(1);
8383                 mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
8384             } else {
8385                 out.writeInt(0);
8386             }
8387             if (mBluetoothScanResultCounter != null) {
8388                 out.writeInt(1);
8389                 mBluetoothScanResultCounter.writeToParcel(out);
8390             } else {
8391                 out.writeInt(0);
8392             }
8393             if (mBluetoothScanResultBgCounter != null) {
8394                 out.writeInt(1);
8395                 mBluetoothScanResultBgCounter.writeToParcel(out);
8396             } else {
8397                 out.writeInt(0);
8398             }
8399             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8400                 if (mProcessStateTimer[i] != null) {
8401                     out.writeInt(1);
8402                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
8403                 } else {
8404                     out.writeInt(0);
8405                 }
8406             }
8407             if (mVibratorOnTimer != null) {
8408                 out.writeInt(1);
8409                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
8410             } else {
8411                 out.writeInt(0);
8412             }
8413             if (mUserActivityCounters != null) {
8414                 out.writeInt(1);
8415                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8416                     mUserActivityCounters[i].writeToParcel(out);
8417                 }
8418             } else {
8419                 out.writeInt(0);
8420             }
8421             if (mNetworkByteActivityCounters != null) {
8422                 out.writeInt(1);
8423                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8424                     mNetworkByteActivityCounters[i].writeToParcel(out);
8425                     mNetworkPacketActivityCounters[i].writeToParcel(out);
8426                 }
8427                 mMobileRadioActiveTime.writeToParcel(out);
8428                 mMobileRadioActiveCount.writeToParcel(out);
8429             } else {
8430                 out.writeInt(0);
8431             }
8432 
8433             if (mWifiControllerActivity != null) {
8434                 out.writeInt(1);
8435                 mWifiControllerActivity.writeToParcel(out, 0);
8436             } else {
8437                 out.writeInt(0);
8438             }
8439 
8440             if (mBluetoothControllerActivity != null) {
8441                 out.writeInt(1);
8442                 mBluetoothControllerActivity.writeToParcel(out, 0);
8443             } else {
8444                 out.writeInt(0);
8445             }
8446 
8447             if (mModemControllerActivity != null) {
8448                 out.writeInt(1);
8449                 mModemControllerActivity.writeToParcel(out, 0);
8450             } else {
8451                 out.writeInt(0);
8452             }
8453 
8454             mUserCpuTime.writeToParcel(out);
8455             mSystemCpuTime.writeToParcel(out);
8456 
8457             if (mCpuClusterSpeedTimesUs != null) {
8458                 out.writeInt(1);
8459                 out.writeInt(mCpuClusterSpeedTimesUs.length);
8460                 for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
8461                     if (cpuSpeeds != null) {
8462                         out.writeInt(1);
8463                         out.writeInt(cpuSpeeds.length);
8464                         for (LongSamplingCounter c : cpuSpeeds) {
8465                             if (c != null) {
8466                                 out.writeInt(1);
8467                                 c.writeToParcel(out);
8468                             } else {
8469                                 out.writeInt(0);
8470                             }
8471                         }
8472                     } else {
8473                         out.writeInt(0);
8474                     }
8475                 }
8476             } else {
8477                 out.writeInt(0);
8478             }
8479 
8480             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
8481             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
8482 
8483             mCpuActiveTimeMs.writeToParcel(out);
8484             mCpuClusterTimesMs.writeToParcel(out);
8485 
8486             if (mProcStateTimeMs != null) {
8487                 out.writeInt(mProcStateTimeMs.length);
8488                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
8489                     LongSamplingCounterArray.writeToParcel(out, counters);
8490                 }
8491             } else {
8492                 out.writeInt(0);
8493             }
8494             if (mProcStateScreenOffTimeMs != null) {
8495                 out.writeInt(mProcStateScreenOffTimeMs.length);
8496                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
8497                     LongSamplingCounterArray.writeToParcel(out, counters);
8498                 }
8499             } else {
8500                 out.writeInt(0);
8501             }
8502 
8503             if (mMobileRadioApWakeupCount != null) {
8504                 out.writeInt(1);
8505                 mMobileRadioApWakeupCount.writeToParcel(out);
8506             } else {
8507                 out.writeInt(0);
8508             }
8509 
8510             if (mWifiRadioApWakeupCount != null) {
8511                 out.writeInt(1);
8512                 mWifiRadioApWakeupCount.writeToParcel(out);
8513             } else {
8514                 out.writeInt(0);
8515             }
8516         }
8517 
readJobCompletionsFromParcelLocked(Parcel in)8518         void readJobCompletionsFromParcelLocked(Parcel in) {
8519             int numJobCompletions = in.readInt();
8520             mJobCompletions.clear();
8521             for (int j = 0; j < numJobCompletions; j++) {
8522                 String jobName = in.readString();
8523                 int numTypes = in.readInt();
8524                 if (numTypes > 0) {
8525                     SparseIntArray types = new SparseIntArray();
8526                     for (int k = 0; k < numTypes; k++) {
8527                         int type = in.readInt();
8528                         int count = in.readInt();
8529                         types.put(type, count);
8530                     }
8531                     mJobCompletions.put(jobName, types);
8532                 }
8533             }
8534         }
8535 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in)8536         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
8537             mOnBatteryBackgroundTimeBase.readFromParcel(in);
8538             mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
8539 
8540             int numWakelocks = in.readInt();
8541             mWakelockStats.clear();
8542             for (int j = 0; j < numWakelocks; j++) {
8543                 String wakelockName = in.readString();
8544                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
8545                 wakelock.readFromParcelLocked(
8546                         timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
8547                 mWakelockStats.add(wakelockName, wakelock);
8548             }
8549 
8550             int numSyncs = in.readInt();
8551             mSyncStats.clear();
8552             for (int j = 0; j < numSyncs; j++) {
8553                 String syncName = in.readString();
8554                 if (in.readInt() != 0) {
8555                     mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
8556                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8557                 }
8558             }
8559 
8560             int numJobs = in.readInt();
8561             mJobStats.clear();
8562             for (int j = 0; j < numJobs; j++) {
8563                 String jobName = in.readString();
8564                 if (in.readInt() != 0) {
8565                     mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
8566                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8567                 }
8568             }
8569 
8570             readJobCompletionsFromParcelLocked(in);
8571 
8572             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8573             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8574             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8575             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8576                 mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
8577                         in);
8578             }
8579 
8580             int numSensors = in.readInt();
8581             mSensorStats.clear();
8582             for (int k = 0; k < numSensors; k++) {
8583                 int sensorNumber = in.readInt();
8584                 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
8585                 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8586                         in);
8587                 mSensorStats.put(sensorNumber, sensor);
8588             }
8589 
8590             int numProcs = in.readInt();
8591             mProcessStats.clear();
8592             for (int k = 0; k < numProcs; k++) {
8593                 String processName = in.readString();
8594                 Uid.Proc proc = new Proc(mBsi, processName);
8595                 proc.readFromParcelLocked(in);
8596                 mProcessStats.put(processName, proc);
8597             }
8598 
8599             int numPkgs = in.readInt();
8600             mPackageStats.clear();
8601             for (int l = 0; l < numPkgs; l++) {
8602                 String packageName = in.readString();
8603                 Uid.Pkg pkg = new Pkg(mBsi);
8604                 pkg.readFromParcelLocked(in);
8605                 mPackageStats.put(packageName, pkg);
8606             }
8607 
8608             mWifiRunning = false;
8609             if (in.readInt() != 0) {
8610                 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
8611                         mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
8612             } else {
8613                 mWifiRunningTimer = null;
8614             }
8615             mFullWifiLockOut = false;
8616             if (in.readInt() != 0) {
8617                 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
8618                         mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
8619             } else {
8620                 mFullWifiLockTimer = null;
8621             }
8622             mWifiScanStarted = false;
8623             if (in.readInt() != 0) {
8624                 mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
8625                         mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8626                         in);
8627             } else {
8628                 mWifiScanTimer = null;
8629             }
8630             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8631             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8632                 if (in.readInt() != 0) {
8633                     makeWifiBatchedScanBin(i, in);
8634                 } else {
8635                     mWifiBatchedScanTimer[i] = null;
8636                 }
8637             }
8638             mWifiMulticastEnabled = false;
8639             if (in.readInt() != 0) {
8640                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
8641                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
8642             } else {
8643                 mWifiMulticastTimer = null;
8644             }
8645             if (in.readInt() != 0) {
8646                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
8647                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8648             } else {
8649                 mAudioTurnedOnTimer = null;
8650             }
8651             if (in.readInt() != 0) {
8652                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
8653                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8654             } else {
8655                 mVideoTurnedOnTimer = null;
8656             }
8657             if (in.readInt() != 0) {
8658                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8659                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8660             } else {
8661                 mFlashlightTurnedOnTimer = null;
8662             }
8663             if (in.readInt() != 0) {
8664                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
8665                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8666             } else {
8667                 mCameraTurnedOnTimer = null;
8668             }
8669             if (in.readInt() != 0) {
8670                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8671                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
8672             } else {
8673                 mForegroundActivityTimer = null;
8674             }
8675             if (in.readInt() != 0) {
8676                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8677                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
8678             } else {
8679                 mForegroundServiceTimer = null;
8680             }
8681             if (in.readInt() != 0) {
8682                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
8683                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
8684                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
8685                         in);
8686             } else {
8687                 mAggregatedPartialWakelockTimer = null;
8688             }
8689             if (in.readInt() != 0) {
8690                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
8691                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
8692                         mOnBatteryBackgroundTimeBase, in);
8693             } else {
8694                 mBluetoothScanTimer = null;
8695             }
8696             if (in.readInt() != 0) {
8697                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
8698                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
8699                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
8700             } else {
8701                 mBluetoothUnoptimizedScanTimer = null;
8702             }
8703             if (in.readInt() != 0) {
8704                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
8705             } else {
8706                 mBluetoothScanResultCounter = null;
8707             }
8708             if (in.readInt() != 0) {
8709                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
8710             } else {
8711                 mBluetoothScanResultBgCounter = null;
8712             }
8713             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
8714             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8715                 if (in.readInt() != 0) {
8716                     makeProcessState(i, in);
8717                 } else {
8718                     mProcessStateTimer[i] = null;
8719                 }
8720             }
8721             if (in.readInt() != 0) {
8722                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
8723                         mBsi.mOnBatteryTimeBase, in);
8724             } else {
8725                 mVibratorOnTimer = null;
8726             }
8727             if (in.readInt() != 0) {
8728                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
8729                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8730                     mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
8731                 }
8732             } else {
8733                 mUserActivityCounters = null;
8734             }
8735             if (in.readInt() != 0) {
8736                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8737                 mNetworkPacketActivityCounters
8738                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8739                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8740                     mNetworkByteActivityCounters[i]
8741                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8742                     mNetworkPacketActivityCounters[i]
8743                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8744                 }
8745                 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8746                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8747             } else {
8748                 mNetworkByteActivityCounters = null;
8749                 mNetworkPacketActivityCounters = null;
8750             }
8751 
8752             if (in.readInt() != 0) {
8753                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8754                         NUM_WIFI_TX_LEVELS, in);
8755             } else {
8756                 mWifiControllerActivity = null;
8757             }
8758 
8759             if (in.readInt() != 0) {
8760                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8761                         NUM_BT_TX_LEVELS, in);
8762             } else {
8763                 mBluetoothControllerActivity = null;
8764             }
8765 
8766             if (in.readInt() != 0) {
8767                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8768                         ModemActivityInfo.TX_POWER_LEVELS, in);
8769             } else {
8770                 mModemControllerActivity = null;
8771             }
8772 
8773             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8774             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8775 
8776             if (in.readInt() != 0) {
8777                 int numCpuClusters = in.readInt();
8778                 if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
8779                     throw new ParcelFormatException("Incompatible number of cpu clusters");
8780                 }
8781 
8782                 mCpuClusterSpeedTimesUs = new LongSamplingCounter[numCpuClusters][];
8783                 for (int cluster = 0; cluster < numCpuClusters; cluster++) {
8784                     if (in.readInt() != 0) {
8785                         int numSpeeds = in.readInt();
8786                         if (mBsi.mPowerProfile != null &&
8787                                 mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
8788                             throw new ParcelFormatException("Incompatible number of cpu speeds");
8789                         }
8790 
8791                         final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
8792                         mCpuClusterSpeedTimesUs[cluster] = cpuSpeeds;
8793                         for (int speed = 0; speed < numSpeeds; speed++) {
8794                             if (in.readInt() != 0) {
8795                                 cpuSpeeds[speed] = new LongSamplingCounter(
8796                                         mBsi.mOnBatteryTimeBase, in);
8797                             }
8798                         }
8799                     } else {
8800                         mCpuClusterSpeedTimesUs[cluster] = null;
8801                     }
8802                 }
8803             } else {
8804                 mCpuClusterSpeedTimesUs = null;
8805             }
8806 
8807             mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
8808             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
8809                     in, mBsi.mOnBatteryScreenOffTimeBase);
8810 
8811             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8812             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
8813 
8814             int length = in.readInt();
8815             if (length == NUM_PROCESS_STATE) {
8816                 mProcStateTimeMs = new LongSamplingCounterArray[length];
8817                 for (int procState = 0; procState < length; ++procState) {
8818                     mProcStateTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8819                             in, mBsi.mOnBatteryTimeBase);
8820                 }
8821             } else {
8822                 mProcStateTimeMs = null;
8823             }
8824             length = in.readInt();
8825             if (length == NUM_PROCESS_STATE) {
8826                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
8827                 for (int procState = 0; procState < length; ++procState) {
8828                     mProcStateScreenOffTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8829                             in, mBsi.mOnBatteryScreenOffTimeBase);
8830                 }
8831             } else {
8832                 mProcStateScreenOffTimeMs = null;
8833             }
8834 
8835             if (in.readInt() != 0) {
8836                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8837             } else {
8838                 mMobileRadioApWakeupCount = null;
8839             }
8840 
8841             if (in.readInt() != 0) {
8842                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8843             } else {
8844                 mWifiRadioApWakeupCount = null;
8845             }
8846         }
8847 
noteJobsDeferredLocked(int numDeferred, long sinceLast)8848         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
8849             mJobsDeferredEventCount.addAtomic(1);
8850             mJobsDeferredCount.addAtomic(numDeferred);
8851             if (sinceLast != 0) {
8852                 // Add the total time, which can be divided by the event count to get an average
8853                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
8854                 // Also keep track of how many times there were in these different buckets.
8855                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8856                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
8857                         if (mJobsFreshnessBuckets[i] == null) {
8858                             mJobsFreshnessBuckets[i] = new Counter(
8859                                     mBsi.mOnBatteryTimeBase);
8860                         }
8861                         mJobsFreshnessBuckets[i].addAtomic(1);
8862                         break;
8863                     }
8864                 }
8865             }
8866         }
8867 
8868         /**
8869          * The statistics associated with a particular wake lock.
8870          */
8871         public static class Wakelock extends BatteryStats.Uid.Wakelock {
8872             /**
8873              * BatteryStatsImpl that we are associated with.
8874              */
8875             protected BatteryStatsImpl mBsi;
8876 
8877             /**
8878              * BatteryStatsImpl that we are associated with.
8879              */
8880             protected Uid mUid;
8881 
8882             /**
8883              * How long (in ms) this uid has been keeping the device partially awake.
8884              * Tracks both the total time and the time while the app was in the background.
8885              */
8886             DualTimer mTimerPartial;
8887 
8888             /**
8889              * How long (in ms) this uid has been keeping the device fully awake.
8890              */
8891             StopwatchTimer mTimerFull;
8892 
8893             /**
8894              * How long (in ms) this uid has had a window keeping the device awake.
8895              */
8896             StopwatchTimer mTimerWindow;
8897 
8898             /**
8899              * How long (in ms) this uid has had a draw wake lock.
8900              */
8901             StopwatchTimer mTimerDraw;
8902 
Wakelock(BatteryStatsImpl bsi, Uid uid)8903             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
8904                 mBsi = bsi;
8905                 mUid = uid;
8906             }
8907 
8908             /**
8909              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8910              * proper timer pool from the given BatteryStatsImpl object.
8911              *
8912              * @param in the Parcel to be read from.
8913              * return a new Timer, or null.
8914              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)8915             private StopwatchTimer readStopwatchTimerFromParcel(int type,
8916                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
8917                 if (in.readInt() == 0) {
8918                     return null;
8919                 }
8920 
8921                 return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
8922             }
8923 
8924             /**
8925              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8926              * proper timer pool from the given BatteryStatsImpl object.
8927              *
8928              * @param in the Parcel to be read from.
8929              * return a new Timer, or null.
8930              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)8931             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
8932                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8933                 if (in.readInt() == 0) {
8934                     return null;
8935                 }
8936 
8937                 return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
8938             }
8939 
reset()8940             boolean reset() {
8941                 boolean wlactive = false;
8942                 if (mTimerFull != null) {
8943                     wlactive |= !mTimerFull.reset(false);
8944                 }
8945                 if (mTimerPartial != null) {
8946                     wlactive |= !mTimerPartial.reset(false);
8947                 }
8948                 if (mTimerWindow != null) {
8949                     wlactive |= !mTimerWindow.reset(false);
8950                 }
8951                 if (mTimerDraw != null) {
8952                     wlactive |= !mTimerDraw.reset(false);
8953                 }
8954                 if (!wlactive) {
8955                     if (mTimerFull != null) {
8956                         mTimerFull.detach();
8957                         mTimerFull = null;
8958                     }
8959                     if (mTimerPartial != null) {
8960                         mTimerPartial.detach();
8961                         mTimerPartial = null;
8962                     }
8963                     if (mTimerWindow != null) {
8964                         mTimerWindow.detach();
8965                         mTimerWindow = null;
8966                     }
8967                     if (mTimerDraw != null) {
8968                         mTimerDraw.detach();
8969                         mTimerDraw = null;
8970                     }
8971                 }
8972                 return !wlactive;
8973             }
8974 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)8975             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
8976                     TimeBase screenOffBgTimeBase, Parcel in) {
8977                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
8978                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
8979                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
8980                         mBsi.mFullTimers, timeBase, in);
8981                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
8982                         mBsi.mWindowTimers, timeBase, in);
8983                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
8984                         mBsi.mDrawTimers, timeBase, in);
8985             }
8986 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)8987             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
8988                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
8989                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
8990                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
8991                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
8992             }
8993 
8994             @Override
getWakeTime(int type)8995             public Timer getWakeTime(int type) {
8996                 switch (type) {
8997                 case WAKE_TYPE_FULL: return mTimerFull;
8998                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
8999                 case WAKE_TYPE_WINDOW: return mTimerWindow;
9000                 case WAKE_TYPE_DRAW: return mTimerDraw;
9001                 default: throw new IllegalArgumentException("type = " + type);
9002                 }
9003             }
9004         }
9005 
9006         public static class Sensor extends BatteryStats.Uid.Sensor {
9007             /**
9008              * BatteryStatsImpl that we are associated with.
9009              */
9010             protected BatteryStatsImpl mBsi;
9011 
9012             /**
9013              * Uid that we are associated with.
9014              */
9015             protected Uid mUid;
9016 
9017             final int mHandle;
9018             DualTimer mTimer;
9019 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)9020             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
9021                 mBsi = bsi;
9022                 mUid = uid;
9023                 mHandle = handle;
9024             }
9025 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)9026             private DualTimer readTimersFromParcel(
9027                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9028                 if (in.readInt() == 0) {
9029                     return null;
9030                 }
9031 
9032                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
9033                 if (pool == null) {
9034                     pool = new ArrayList<StopwatchTimer>();
9035                     mBsi.mSensorTimers.put(mHandle, pool);
9036                 }
9037                 return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
9038             }
9039 
reset()9040             boolean reset() {
9041                 if (mTimer.reset(true)) {
9042                     mTimer = null;
9043                     return true;
9044                 }
9045                 return false;
9046             }
9047 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)9048             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9049                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
9050             }
9051 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)9052             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
9053                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
9054             }
9055 
9056             @Override
getSensorTime()9057             public Timer getSensorTime() {
9058                 return mTimer;
9059             }
9060 
9061             @Override
getSensorBackgroundTime()9062             public Timer getSensorBackgroundTime() {
9063                 if (mTimer == null) {
9064                     return null;
9065                 }
9066                 return mTimer.getSubTimer();
9067             }
9068 
9069             @Override
getHandle()9070             public int getHandle() {
9071                 return mHandle;
9072             }
9073         }
9074 
9075         /**
9076          * The statistics associated with a particular process.
9077          */
9078         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
9079             /**
9080              * BatteryStatsImpl that we are associated with.
9081              */
9082             protected BatteryStatsImpl mBsi;
9083 
9084             /**
9085              * The name of this process.
9086              */
9087             final String mName;
9088 
9089             /**
9090              * Remains true until removed from the stats.
9091              */
9092             boolean mActive = true;
9093 
9094             /**
9095              * Total time (in ms) spent executing in user code.
9096              */
9097             long mUserTime;
9098 
9099             /**
9100              * Total time (in ms) spent executing in kernel code.
9101              */
9102             long mSystemTime;
9103 
9104             /**
9105              * Amount of time (in ms) the process was running in the foreground.
9106              */
9107             long mForegroundTime;
9108 
9109             /**
9110              * Number of times the process has been started.
9111              */
9112             int mStarts;
9113 
9114             /**
9115              * Number of times the process has crashed.
9116              */
9117             int mNumCrashes;
9118 
9119             /**
9120              * Number of times the process has had an ANR.
9121              */
9122             int mNumAnrs;
9123 
9124             /**
9125              * The amount of user time loaded from a previous save.
9126              */
9127             long mLoadedUserTime;
9128 
9129             /**
9130              * The amount of system time loaded from a previous save.
9131              */
9132             long mLoadedSystemTime;
9133 
9134             /**
9135              * The amount of foreground time loaded from a previous save.
9136              */
9137             long mLoadedForegroundTime;
9138 
9139             /**
9140              * The number of times the process has started from a previous save.
9141              */
9142             int mLoadedStarts;
9143 
9144             /**
9145              * Number of times the process has crashed from a previous save.
9146              */
9147             int mLoadedNumCrashes;
9148 
9149             /**
9150              * Number of times the process has had an ANR from a previous save.
9151              */
9152             int mLoadedNumAnrs;
9153 
9154             /**
9155              * The amount of user time when last unplugged.
9156              */
9157             long mUnpluggedUserTime;
9158 
9159             /**
9160              * The amount of system time when last unplugged.
9161              */
9162             long mUnpluggedSystemTime;
9163 
9164             /**
9165              * The amount of foreground time since unplugged.
9166              */
9167             long mUnpluggedForegroundTime;
9168 
9169             /**
9170              * The number of times the process has started before unplugged.
9171              */
9172             int mUnpluggedStarts;
9173 
9174             /**
9175              * Number of times the process has crashed before unplugged.
9176              */
9177             int mUnpluggedNumCrashes;
9178 
9179             /**
9180              * Number of times the process has had an ANR before unplugged.
9181              */
9182             int mUnpluggedNumAnrs;
9183 
9184             ArrayList<ExcessivePower> mExcessivePower;
9185 
Proc(BatteryStatsImpl bsi, String name)9186             public Proc(BatteryStatsImpl bsi, String name) {
9187                 mBsi = bsi;
9188                 mName = name;
9189                 mBsi.mOnBatteryTimeBase.add(this);
9190             }
9191 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)9192             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
9193                 mUnpluggedUserTime = mUserTime;
9194                 mUnpluggedSystemTime = mSystemTime;
9195                 mUnpluggedForegroundTime = mForegroundTime;
9196                 mUnpluggedStarts = mStarts;
9197                 mUnpluggedNumCrashes = mNumCrashes;
9198                 mUnpluggedNumAnrs = mNumAnrs;
9199             }
9200 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)9201             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
9202             }
9203 
detach()9204             void detach() {
9205                 mActive = false;
9206                 mBsi.mOnBatteryTimeBase.remove(this);
9207             }
9208 
countExcessivePowers()9209             public int countExcessivePowers() {
9210                 return mExcessivePower != null ? mExcessivePower.size() : 0;
9211             }
9212 
getExcessivePower(int i)9213             public ExcessivePower getExcessivePower(int i) {
9214                 if (mExcessivePower != null) {
9215                     return mExcessivePower.get(i);
9216                 }
9217                 return null;
9218             }
9219 
addExcessiveCpu(long overTime, long usedTime)9220             public void addExcessiveCpu(long overTime, long usedTime) {
9221                 if (mExcessivePower == null) {
9222                     mExcessivePower = new ArrayList<ExcessivePower>();
9223                 }
9224                 ExcessivePower ew = new ExcessivePower();
9225                 ew.type = ExcessivePower.TYPE_CPU;
9226                 ew.overTime = overTime;
9227                 ew.usedTime = usedTime;
9228                 mExcessivePower.add(ew);
9229             }
9230 
writeExcessivePowerToParcelLocked(Parcel out)9231             void writeExcessivePowerToParcelLocked(Parcel out) {
9232                 if (mExcessivePower == null) {
9233                     out.writeInt(0);
9234                     return;
9235                 }
9236 
9237                 final int N = mExcessivePower.size();
9238                 out.writeInt(N);
9239                 for (int i=0; i<N; i++) {
9240                     ExcessivePower ew = mExcessivePower.get(i);
9241                     out.writeInt(ew.type);
9242                     out.writeLong(ew.overTime);
9243                     out.writeLong(ew.usedTime);
9244                 }
9245             }
9246 
readExcessivePowerFromParcelLocked(Parcel in)9247             void readExcessivePowerFromParcelLocked(Parcel in) {
9248                 final int N = in.readInt();
9249                 if (N == 0) {
9250                     mExcessivePower = null;
9251                     return;
9252                 }
9253 
9254                 if (N > 10000) {
9255                     throw new ParcelFormatException(
9256                             "File corrupt: too many excessive power entries " + N);
9257                 }
9258 
9259                 mExcessivePower = new ArrayList<>();
9260                 for (int i=0; i<N; i++) {
9261                     ExcessivePower ew = new ExcessivePower();
9262                     ew.type = in.readInt();
9263                     ew.overTime = in.readLong();
9264                     ew.usedTime = in.readLong();
9265                     mExcessivePower.add(ew);
9266                 }
9267             }
9268 
writeToParcelLocked(Parcel out)9269             void writeToParcelLocked(Parcel out) {
9270                 out.writeLong(mUserTime);
9271                 out.writeLong(mSystemTime);
9272                 out.writeLong(mForegroundTime);
9273                 out.writeInt(mStarts);
9274                 out.writeInt(mNumCrashes);
9275                 out.writeInt(mNumAnrs);
9276                 out.writeLong(mLoadedUserTime);
9277                 out.writeLong(mLoadedSystemTime);
9278                 out.writeLong(mLoadedForegroundTime);
9279                 out.writeInt(mLoadedStarts);
9280                 out.writeInt(mLoadedNumCrashes);
9281                 out.writeInt(mLoadedNumAnrs);
9282                 out.writeLong(mUnpluggedUserTime);
9283                 out.writeLong(mUnpluggedSystemTime);
9284                 out.writeLong(mUnpluggedForegroundTime);
9285                 out.writeInt(mUnpluggedStarts);
9286                 out.writeInt(mUnpluggedNumCrashes);
9287                 out.writeInt(mUnpluggedNumAnrs);
9288                 writeExcessivePowerToParcelLocked(out);
9289             }
9290 
readFromParcelLocked(Parcel in)9291             void readFromParcelLocked(Parcel in) {
9292                 mUserTime = in.readLong();
9293                 mSystemTime = in.readLong();
9294                 mForegroundTime = in.readLong();
9295                 mStarts = in.readInt();
9296                 mNumCrashes = in.readInt();
9297                 mNumAnrs = in.readInt();
9298                 mLoadedUserTime = in.readLong();
9299                 mLoadedSystemTime = in.readLong();
9300                 mLoadedForegroundTime = in.readLong();
9301                 mLoadedStarts = in.readInt();
9302                 mLoadedNumCrashes = in.readInt();
9303                 mLoadedNumAnrs = in.readInt();
9304                 mUnpluggedUserTime = in.readLong();
9305                 mUnpluggedSystemTime = in.readLong();
9306                 mUnpluggedForegroundTime = in.readLong();
9307                 mUnpluggedStarts = in.readInt();
9308                 mUnpluggedNumCrashes = in.readInt();
9309                 mUnpluggedNumAnrs = in.readInt();
9310                 readExcessivePowerFromParcelLocked(in);
9311             }
9312 
addCpuTimeLocked(int utime, int stime)9313             public void addCpuTimeLocked(int utime, int stime) {
9314                 addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
9315             }
9316 
addCpuTimeLocked(int utime, int stime, boolean isRunning)9317             public void addCpuTimeLocked(int utime, int stime, boolean isRunning) {
9318                 if (isRunning) {
9319                     mUserTime += utime;
9320                     mSystemTime += stime;
9321                 }
9322             }
9323 
addForegroundTimeLocked(long ttime)9324             public void addForegroundTimeLocked(long ttime) {
9325                 mForegroundTime += ttime;
9326             }
9327 
incStartsLocked()9328             public void incStartsLocked() {
9329                 mStarts++;
9330             }
9331 
incNumCrashesLocked()9332             public void incNumCrashesLocked() {
9333                 mNumCrashes++;
9334             }
9335 
incNumAnrsLocked()9336             public void incNumAnrsLocked() {
9337                 mNumAnrs++;
9338             }
9339 
9340             @Override
isActive()9341             public boolean isActive() {
9342                 return mActive;
9343             }
9344 
9345             @Override
getUserTime(int which)9346             public long getUserTime(int which) {
9347                 long val = mUserTime;
9348                 if (which == STATS_CURRENT) {
9349                     val -= mLoadedUserTime;
9350                 } else if (which == STATS_SINCE_UNPLUGGED) {
9351                     val -= mUnpluggedUserTime;
9352                 }
9353                 return val;
9354             }
9355 
9356             @Override
getSystemTime(int which)9357             public long getSystemTime(int which) {
9358                 long val = mSystemTime;
9359                 if (which == STATS_CURRENT) {
9360                     val -= mLoadedSystemTime;
9361                 } else if (which == STATS_SINCE_UNPLUGGED) {
9362                     val -= mUnpluggedSystemTime;
9363                 }
9364                 return val;
9365             }
9366 
9367             @Override
getForegroundTime(int which)9368             public long getForegroundTime(int which) {
9369                 long val = mForegroundTime;
9370                 if (which == STATS_CURRENT) {
9371                     val -= mLoadedForegroundTime;
9372                 } else if (which == STATS_SINCE_UNPLUGGED) {
9373                     val -= mUnpluggedForegroundTime;
9374                 }
9375                 return val;
9376             }
9377 
9378             @Override
getStarts(int which)9379             public int getStarts(int which) {
9380                 int val = mStarts;
9381                 if (which == STATS_CURRENT) {
9382                     val -= mLoadedStarts;
9383                 } else if (which == STATS_SINCE_UNPLUGGED) {
9384                     val -= mUnpluggedStarts;
9385                 }
9386                 return val;
9387             }
9388 
9389             @Override
getNumCrashes(int which)9390             public int getNumCrashes(int which) {
9391                 int val = mNumCrashes;
9392                 if (which == STATS_CURRENT) {
9393                     val -= mLoadedNumCrashes;
9394                 } else if (which == STATS_SINCE_UNPLUGGED) {
9395                     val -= mUnpluggedNumCrashes;
9396                 }
9397                 return val;
9398             }
9399 
9400             @Override
getNumAnrs(int which)9401             public int getNumAnrs(int which) {
9402                 int val = mNumAnrs;
9403                 if (which == STATS_CURRENT) {
9404                     val -= mLoadedNumAnrs;
9405                 } else if (which == STATS_SINCE_UNPLUGGED) {
9406                     val -= mUnpluggedNumAnrs;
9407                 }
9408                 return val;
9409             }
9410         }
9411 
9412         /**
9413          * The statistics associated with a particular package.
9414          */
9415         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
9416             /**
9417              * BatteryStatsImpl that we are associated with.
9418              */
9419             protected BatteryStatsImpl mBsi;
9420 
9421             /**
9422              * Number of times wakeup alarms have occurred for this app.
9423              * On screen-off timebase starting in report v25.
9424              */
9425             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
9426 
9427             /**
9428              * The statics we have collected for this package's services.
9429              */
9430             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
9431 
Pkg(BatteryStatsImpl bsi)9432             public Pkg(BatteryStatsImpl bsi) {
9433                 mBsi = bsi;
9434                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
9435             }
9436 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)9437             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
9438             }
9439 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)9440             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
9441             }
9442 
detach()9443             void detach() {
9444                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
9445             }
9446 
readFromParcelLocked(Parcel in)9447             void readFromParcelLocked(Parcel in) {
9448                 int numWA = in.readInt();
9449                 mWakeupAlarms.clear();
9450                 for (int i=0; i<numWA; i++) {
9451                     String tag = in.readString();
9452                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
9453                 }
9454 
9455                 int numServs = in.readInt();
9456                 mServiceStats.clear();
9457                 for (int m = 0; m < numServs; m++) {
9458                     String serviceName = in.readString();
9459                     Uid.Pkg.Serv serv = new Serv(mBsi);
9460                     mServiceStats.put(serviceName, serv);
9461 
9462                     serv.readFromParcelLocked(in);
9463                 }
9464             }
9465 
writeToParcelLocked(Parcel out)9466             void writeToParcelLocked(Parcel out) {
9467                 int numWA = mWakeupAlarms.size();
9468                 out.writeInt(numWA);
9469                 for (int i=0; i<numWA; i++) {
9470                     out.writeString(mWakeupAlarms.keyAt(i));
9471                     mWakeupAlarms.valueAt(i).writeToParcel(out);
9472                 }
9473 
9474                 final int NS = mServiceStats.size();
9475                 out.writeInt(NS);
9476                 for (int i=0; i<NS; i++) {
9477                     out.writeString(mServiceStats.keyAt(i));
9478                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
9479                     serv.writeToParcelLocked(out);
9480                 }
9481             }
9482 
9483             @Override
getWakeupAlarmStats()9484             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
9485                 return mWakeupAlarms;
9486             }
9487 
noteWakeupAlarmLocked(String tag)9488             public void noteWakeupAlarmLocked(String tag) {
9489                 Counter c = mWakeupAlarms.get(tag);
9490                 if (c == null) {
9491                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
9492                     mWakeupAlarms.put(tag, c);
9493                 }
9494                 c.stepAtomic();
9495             }
9496 
9497             @Override
getServiceStats()9498             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
9499                 return mServiceStats;
9500             }
9501 
9502             /**
9503              * The statistics associated with a particular service.
9504              */
9505             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
9506                 /**
9507                  * BatteryStatsImpl that we are associated with.
9508                  */
9509                 protected BatteryStatsImpl mBsi;
9510 
9511                 /**
9512                  * The android package in which this service resides.
9513                  */
9514                 protected Pkg mPkg;
9515 
9516                 /**
9517                  * Total time (ms in battery uptime) the service has been left started.
9518                  */
9519                 protected long mStartTime;
9520 
9521                 /**
9522                  * If service has been started and not yet stopped, this is
9523                  * when it was started.
9524                  */
9525                 protected long mRunningSince;
9526 
9527                 /**
9528                  * True if we are currently running.
9529                  */
9530                 protected boolean mRunning;
9531 
9532                 /**
9533                  * Total number of times startService() has been called.
9534                  */
9535                 protected int mStarts;
9536 
9537                 /**
9538                  * Total time (ms in battery uptime) the service has been left launched.
9539                  */
9540                 protected long mLaunchedTime;
9541 
9542                 /**
9543                  * If service has been launched and not yet exited, this is
9544                  * when it was launched (ms in battery uptime).
9545                  */
9546                 protected long mLaunchedSince;
9547 
9548                 /**
9549                  * True if we are currently launched.
9550                  */
9551                 protected boolean mLaunched;
9552 
9553                 /**
9554                  * Total number times the service has been launched.
9555                  */
9556                 protected int mLaunches;
9557 
9558                 /**
9559                  * The amount of time spent started loaded from a previous save
9560                  * (ms in battery uptime).
9561                  */
9562                 protected long mLoadedStartTime;
9563 
9564                 /**
9565                  * The number of starts loaded from a previous save.
9566                  */
9567                 protected int mLoadedStarts;
9568 
9569                 /**
9570                  * The number of launches loaded from a previous save.
9571                  */
9572                 protected int mLoadedLaunches;
9573 
9574                 /**
9575                  * The amount of time spent started as of the last run (ms
9576                  * in battery uptime).
9577                  */
9578                 protected long mLastStartTime;
9579 
9580                 /**
9581                  * The number of starts as of the last run.
9582                  */
9583                 protected int mLastStarts;
9584 
9585                 /**
9586                  * The number of launches as of the last run.
9587                  */
9588                 protected int mLastLaunches;
9589 
9590                 /**
9591                  * The amount of time spent started when last unplugged (ms
9592                  * in battery uptime).
9593                  */
9594                 protected long mUnpluggedStartTime;
9595 
9596                 /**
9597                  * The number of starts when last unplugged.
9598                  */
9599                 protected int mUnpluggedStarts;
9600 
9601                 /**
9602                  * The number of launches when last unplugged.
9603                  */
9604                 protected int mUnpluggedLaunches;
9605 
9606                 /**
9607                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
9608                  */
Serv(BatteryStatsImpl bsi)9609                 public Serv(BatteryStatsImpl bsi) {
9610                     mBsi = bsi;
9611                     mBsi.mOnBatteryTimeBase.add(this);
9612                 }
9613 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)9614                 public void onTimeStarted(long elapsedRealtime, long baseUptime,
9615                         long baseRealtime) {
9616                     mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
9617                     mUnpluggedStarts = mStarts;
9618                     mUnpluggedLaunches = mLaunches;
9619                 }
9620 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)9621                 public void onTimeStopped(long elapsedRealtime, long baseUptime,
9622                         long baseRealtime) {
9623                 }
9624 
9625                 /**
9626                  * Remove this Serv as a listener from the time base.
9627                  */
detach()9628                 public void detach() {
9629                     mBsi.mOnBatteryTimeBase.remove(this);
9630                 }
9631 
readFromParcelLocked(Parcel in)9632                 public void readFromParcelLocked(Parcel in) {
9633                     mStartTime = in.readLong();
9634                     mRunningSince = in.readLong();
9635                     mRunning = in.readInt() != 0;
9636                     mStarts = in.readInt();
9637                     mLaunchedTime = in.readLong();
9638                     mLaunchedSince = in.readLong();
9639                     mLaunched = in.readInt() != 0;
9640                     mLaunches = in.readInt();
9641                     mLoadedStartTime = in.readLong();
9642                     mLoadedStarts = in.readInt();
9643                     mLoadedLaunches = in.readInt();
9644                     mLastStartTime = 0;
9645                     mLastStarts = 0;
9646                     mLastLaunches = 0;
9647                     mUnpluggedStartTime = in.readLong();
9648                     mUnpluggedStarts = in.readInt();
9649                     mUnpluggedLaunches = in.readInt();
9650                 }
9651 
writeToParcelLocked(Parcel out)9652                 public void writeToParcelLocked(Parcel out) {
9653                     out.writeLong(mStartTime);
9654                     out.writeLong(mRunningSince);
9655                     out.writeInt(mRunning ? 1 : 0);
9656                     out.writeInt(mStarts);
9657                     out.writeLong(mLaunchedTime);
9658                     out.writeLong(mLaunchedSince);
9659                     out.writeInt(mLaunched ? 1 : 0);
9660                     out.writeInt(mLaunches);
9661                     out.writeLong(mLoadedStartTime);
9662                     out.writeInt(mLoadedStarts);
9663                     out.writeInt(mLoadedLaunches);
9664                     out.writeLong(mUnpluggedStartTime);
9665                     out.writeInt(mUnpluggedStarts);
9666                     out.writeInt(mUnpluggedLaunches);
9667                 }
9668 
getLaunchTimeToNowLocked(long batteryUptime)9669                 public long getLaunchTimeToNowLocked(long batteryUptime) {
9670                     if (!mLaunched) return mLaunchedTime;
9671                     return mLaunchedTime + batteryUptime - mLaunchedSince;
9672                 }
9673 
getStartTimeToNowLocked(long batteryUptime)9674                 public long getStartTimeToNowLocked(long batteryUptime) {
9675                     if (!mRunning) return mStartTime;
9676                     return mStartTime + batteryUptime - mRunningSince;
9677                 }
9678 
startLaunchedLocked()9679                 public void startLaunchedLocked() {
9680                     if (!mLaunched) {
9681                         mLaunches++;
9682                         mLaunchedSince = mBsi.getBatteryUptimeLocked();
9683                         mLaunched = true;
9684                     }
9685                 }
9686 
stopLaunchedLocked()9687                 public void stopLaunchedLocked() {
9688                     if (mLaunched) {
9689                         long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
9690                         if (time > 0) {
9691                             mLaunchedTime += time;
9692                         } else {
9693                             mLaunches--;
9694                         }
9695                         mLaunched = false;
9696                     }
9697                 }
9698 
startRunningLocked()9699                 public void startRunningLocked() {
9700                     if (!mRunning) {
9701                         mStarts++;
9702                         mRunningSince = mBsi.getBatteryUptimeLocked();
9703                         mRunning = true;
9704                     }
9705                 }
9706 
stopRunningLocked()9707                 public void stopRunningLocked() {
9708                     if (mRunning) {
9709                         long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
9710                         if (time > 0) {
9711                             mStartTime += time;
9712                         } else {
9713                             mStarts--;
9714                         }
9715                         mRunning = false;
9716                     }
9717                 }
9718 
getBatteryStats()9719                 public BatteryStatsImpl getBatteryStats() {
9720                     return mBsi;
9721                 }
9722 
9723                 @Override
getLaunches(int which)9724                 public int getLaunches(int which) {
9725                     int val = mLaunches;
9726                     if (which == STATS_CURRENT) {
9727                         val -= mLoadedLaunches;
9728                     } else if (which == STATS_SINCE_UNPLUGGED) {
9729                         val -= mUnpluggedLaunches;
9730                     }
9731                     return val;
9732                 }
9733 
9734                 @Override
getStartTime(long now, int which)9735                 public long getStartTime(long now, int which) {
9736                     long val = getStartTimeToNowLocked(now);
9737                     if (which == STATS_CURRENT) {
9738                         val -= mLoadedStartTime;
9739                     } else if (which == STATS_SINCE_UNPLUGGED) {
9740                         val -= mUnpluggedStartTime;
9741                     }
9742                     return val;
9743                 }
9744 
9745                 @Override
getStarts(int which)9746                 public int getStarts(int which) {
9747                     int val = mStarts;
9748                     if (which == STATS_CURRENT) {
9749                         val -= mLoadedStarts;
9750                     } else if (which == STATS_SINCE_UNPLUGGED) {
9751                         val -= mUnpluggedStarts;
9752                     }
9753 
9754                     return val;
9755                 }
9756             }
9757 
newServiceStatsLocked()9758             final Serv newServiceStatsLocked() {
9759                 return new Serv(mBsi);
9760             }
9761         }
9762 
9763         /**
9764          * Retrieve the statistics object for a particular process, creating
9765          * if needed.
9766          */
getProcessStatsLocked(String name)9767         public Proc getProcessStatsLocked(String name) {
9768             Proc ps = mProcessStats.get(name);
9769             if (ps == null) {
9770                 ps = new Proc(mBsi, name);
9771                 mProcessStats.put(name, ps);
9772             }
9773 
9774             return ps;
9775         }
9776 
9777         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState)9778         public void updateUidProcessStateLocked(int procState) {
9779             int uidRunningState;
9780             // Make special note of Foreground Services
9781             final boolean userAwareService =
9782                     (procState == ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
9783             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
9784 
9785             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
9786                 return;
9787             }
9788 
9789             final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
9790             if (mProcessState != uidRunningState) {
9791                 final long uptimeMs = mBsi.mClocks.uptimeMillis();
9792 
9793                 if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9794                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
9795 
9796                     if (mBsi.trackPerProcStateCpuTimes()) {
9797                         if (mBsi.mPendingUids.size() == 0) {
9798                             mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
9799                                     mBsi.mOnBatteryTimeBase.isRunning(),
9800                                     mBsi.mOnBatteryScreenOffTimeBase.isRunning(),
9801                                     mBsi.mConstants.PROC_STATE_CPU_TIMES_READ_DELAY_MS);
9802                             mBsi.mNumSingleUidCpuTimeReads++;
9803                         } else {
9804                             mBsi.mNumBatchedSingleUidCpuTimeReads++;
9805                         }
9806                         if (mBsi.mPendingUids.indexOfKey(mUid) < 0
9807                                 || ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
9808                             mBsi.mPendingUids.put(mUid, mProcessState);
9809                         }
9810                     } else {
9811                         mBsi.mPendingUids.clear();
9812                     }
9813                 }
9814                 mProcessState = uidRunningState;
9815                 if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9816                     if (mProcessStateTimer[uidRunningState] == null) {
9817                         makeProcessState(uidRunningState, null);
9818                     }
9819                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
9820                 }
9821 
9822                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9823                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9824             }
9825 
9826             if (userAwareService != mInForegroundService) {
9827                 if (userAwareService) {
9828                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
9829                 } else {
9830                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
9831                 }
9832                 mInForegroundService = userAwareService;
9833             }
9834         }
9835 
9836         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()9837         public boolean isInBackground() {
9838             // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
9839             // also considered to be 'background' for our purposes, because it's not foreground.
9840             return mProcessState >= PROCESS_STATE_BACKGROUND;
9841         }
9842 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)9843         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
9844             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
9845             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9846         }
9847 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)9848         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
9849             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
9850             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9851         }
9852 
getPidStats()9853         public SparseArray<? extends Pid> getPidStats() {
9854             return mPids;
9855         }
9856 
getPidStatsLocked(int pid)9857         public Pid getPidStatsLocked(int pid) {
9858             Pid p = mPids.get(pid);
9859             if (p == null) {
9860                 p = new Pid();
9861                 mPids.put(pid, p);
9862             }
9863             return p;
9864         }
9865 
9866         /**
9867          * Retrieve the statistics object for a particular service, creating
9868          * if needed.
9869          */
getPackageStatsLocked(String name)9870         public Pkg getPackageStatsLocked(String name) {
9871             Pkg ps = mPackageStats.get(name);
9872             if (ps == null) {
9873                 ps = new Pkg(mBsi);
9874                 mPackageStats.put(name, ps);
9875             }
9876 
9877             return ps;
9878         }
9879 
9880         /**
9881          * Retrieve the statistics object for a particular service, creating
9882          * if needed.
9883          */
getServiceStatsLocked(String pkg, String serv)9884         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
9885             Pkg ps = getPackageStatsLocked(pkg);
9886             Pkg.Serv ss = ps.mServiceStats.get(serv);
9887             if (ss == null) {
9888                 ss = ps.newServiceStatsLocked();
9889                 ps.mServiceStats.put(serv, ss);
9890             }
9891 
9892             return ss;
9893         }
9894 
readSyncSummaryFromParcelLocked(String name, Parcel in)9895         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
9896             DualTimer timer = mSyncStats.instantiateObject();
9897             timer.readSummaryFromParcelLocked(in);
9898             mSyncStats.add(name, timer);
9899         }
9900 
readJobSummaryFromParcelLocked(String name, Parcel in)9901         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
9902             DualTimer timer = mJobStats.instantiateObject();
9903             timer.readSummaryFromParcelLocked(in);
9904             mJobStats.add(name, timer);
9905         }
9906 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)9907         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
9908             Wakelock wl = new Wakelock(mBsi, this);
9909             mWakelockStats.add(wlName, wl);
9910             if (in.readInt() != 0) {
9911                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
9912             }
9913             if (in.readInt() != 0) {
9914                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
9915             }
9916             if (in.readInt() != 0) {
9917                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
9918             }
9919             if (in.readInt() != 0) {
9920                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
9921             }
9922         }
9923 
getSensorTimerLocked(int sensor, boolean create)9924         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
9925             Sensor se = mSensorStats.get(sensor);
9926             if (se == null) {
9927                 if (!create) {
9928                     return null;
9929                 }
9930                 se = new Sensor(mBsi, this, sensor);
9931                 mSensorStats.put(sensor, se);
9932             }
9933             DualTimer t = se.mTimer;
9934             if (t != null) {
9935                 return t;
9936             }
9937             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
9938             if (timers == null) {
9939                 timers = new ArrayList<StopwatchTimer>();
9940                 mBsi.mSensorTimers.put(sensor, timers);
9941             }
9942             t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
9943                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
9944             se.mTimer = t;
9945             return t;
9946         }
9947 
noteStartSyncLocked(String name, long elapsedRealtimeMs)9948         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
9949             DualTimer t = mSyncStats.startObject(name);
9950             if (t != null) {
9951                 t.startRunningLocked(elapsedRealtimeMs);
9952             }
9953         }
9954 
noteStopSyncLocked(String name, long elapsedRealtimeMs)9955         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
9956             DualTimer t = mSyncStats.stopObject(name);
9957             if (t != null) {
9958                 t.stopRunningLocked(elapsedRealtimeMs);
9959             }
9960         }
9961 
noteStartJobLocked(String name, long elapsedRealtimeMs)9962         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
9963             DualTimer t = mJobStats.startObject(name);
9964             if (t != null) {
9965                 t.startRunningLocked(elapsedRealtimeMs);
9966             }
9967         }
9968 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)9969         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
9970             DualTimer t = mJobStats.stopObject(name);
9971             if (t != null) {
9972                 t.stopRunningLocked(elapsedRealtimeMs);
9973             }
9974             if (mBsi.mOnBatteryTimeBase.isRunning()) {
9975                 SparseIntArray types = mJobCompletions.get(name);
9976                 if (types == null) {
9977                     types = new SparseIntArray();
9978                     mJobCompletions.put(name, types);
9979                 }
9980                 int last = types.get(stopReason, 0);
9981                 types.put(stopReason, last + 1);
9982             }
9983         }
9984 
getWakelockTimerLocked(Wakelock wl, int type)9985         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
9986             if (wl == null) {
9987                 return null;
9988             }
9989             switch (type) {
9990                 case WAKE_TYPE_PARTIAL: {
9991                     DualTimer t = wl.mTimerPartial;
9992                     if (t == null) {
9993                         t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
9994                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
9995                                 mOnBatteryScreenOffBackgroundTimeBase);
9996                         wl.mTimerPartial = t;
9997                     }
9998                     return t;
9999                 }
10000                 case WAKE_TYPE_FULL: {
10001                     StopwatchTimer t = wl.mTimerFull;
10002                     if (t == null) {
10003                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
10004                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
10005                         wl.mTimerFull = t;
10006                     }
10007                     return t;
10008                 }
10009                 case WAKE_TYPE_WINDOW: {
10010                     StopwatchTimer t = wl.mTimerWindow;
10011                     if (t == null) {
10012                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
10013                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
10014                         wl.mTimerWindow = t;
10015                     }
10016                     return t;
10017                 }
10018                 case WAKE_TYPE_DRAW: {
10019                     StopwatchTimer t = wl.mTimerDraw;
10020                     if (t == null) {
10021                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
10022                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
10023                         wl.mTimerDraw = t;
10024                     }
10025                     return t;
10026                 }
10027                 default:
10028                     throw new IllegalArgumentException("type=" + type);
10029             }
10030         }
10031 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)10032         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10033             Wakelock wl = mWakelockStats.startObject(name);
10034             if (wl != null) {
10035                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
10036             }
10037             if (type == WAKE_TYPE_PARTIAL) {
10038                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
10039                 if (pid >= 0) {
10040                     Pid p = getPidStatsLocked(pid);
10041                     if (p.mWakeNesting++ == 0) {
10042                         p.mWakeStartMs = elapsedRealtimeMs;
10043                     }
10044                 }
10045             }
10046         }
10047 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)10048         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10049             Wakelock wl = mWakelockStats.stopObject(name);
10050             if (wl != null) {
10051                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
10052                 wlt.stopRunningLocked(elapsedRealtimeMs);
10053             }
10054             if (type == WAKE_TYPE_PARTIAL) {
10055                 if (mAggregatedPartialWakelockTimer != null) {
10056                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
10057                 }
10058                 if (pid >= 0) {
10059                     Pid p = mPids.get(pid);
10060                     if (p != null && p.mWakeNesting > 0) {
10061                         if (p.mWakeNesting-- == 1) {
10062                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
10063                             p.mWakeStartMs = 0;
10064                         }
10065                     }
10066                 }
10067             }
10068         }
10069 
reportExcessiveCpuLocked(String proc, long overTime, long usedTime)10070         public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
10071             Proc p = getProcessStatsLocked(proc);
10072             if (p != null) {
10073                 p.addExcessiveCpu(overTime, usedTime);
10074             }
10075         }
10076 
noteStartSensor(int sensor, long elapsedRealtimeMs)10077         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
10078             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
10079             t.startRunningLocked(elapsedRealtimeMs);
10080         }
10081 
noteStopSensor(int sensor, long elapsedRealtimeMs)10082         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
10083             // Don't create a timer if one doesn't already exist
10084             DualTimer t = getSensorTimerLocked(sensor, false);
10085             if (t != null) {
10086                 t.stopRunningLocked(elapsedRealtimeMs);
10087             }
10088         }
10089 
noteStartGps(long elapsedRealtimeMs)10090         public void noteStartGps(long elapsedRealtimeMs) {
10091             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
10092         }
10093 
noteStopGps(long elapsedRealtimeMs)10094         public void noteStopGps(long elapsedRealtimeMs) {
10095             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
10096         }
10097 
getBatteryStats()10098         public BatteryStatsImpl getBatteryStats() {
10099             return mBsi;
10100         }
10101     }
10102 
getCpuFreqs()10103     public long[] getCpuFreqs() {
10104         return mCpuFreqs;
10105     }
10106 
BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, UserInfoProvider userInfoProvider)10107     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
10108             UserInfoProvider userInfoProvider) {
10109         this(new SystemClocks(), systemDir, handler, cb, userInfoProvider);
10110     }
10111 
BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, PlatformIdleStateCallback cb, UserInfoProvider userInfoProvider)10112     private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
10113             PlatformIdleStateCallback cb,
10114             UserInfoProvider userInfoProvider) {
10115         init(clocks);
10116 
10117         if (systemDir != null) {
10118             mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
10119                     new File(systemDir, "batterystats.bin.tmp"));
10120         } else {
10121             mFile = null;
10122         }
10123         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
10124         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
10125         mHandler = new MyHandler(handler.getLooper());
10126         mConstants = new Constants(mHandler);
10127         mStartCount++;
10128         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
10129         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
10130         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10131             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
10132                     mOnBatteryTimeBase);
10133         }
10134         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
10135         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
10136                 mOnBatteryTimeBase);
10137         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
10138                 mOnBatteryTimeBase);
10139         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
10140         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
10141         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
10142         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
10143         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10144             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
10145                     mOnBatteryTimeBase);
10146         }
10147         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
10148                 mOnBatteryTimeBase);
10149         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10150             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
10151                     mOnBatteryTimeBase);
10152         }
10153         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10154             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
10155             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
10156         }
10157         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
10158         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10159                 NUM_BT_TX_LEVELS);
10160         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10161                 ModemActivityInfo.TX_POWER_LEVELS);
10162         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
10163         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
10164                 mOnBatteryTimeBase);
10165         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
10166         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
10167         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
10168         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null,
10169                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
10170         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
10171         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
10172         for (int i=0; i<NUM_WIFI_STATES; i++) {
10173             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
10174                     mOnBatteryTimeBase);
10175         }
10176         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10177             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
10178                     mOnBatteryTimeBase);
10179         }
10180         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10181             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
10182                     mOnBatteryTimeBase);
10183         }
10184         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
10185         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
10186             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
10187                 mOnBatteryTimeBase);
10188         }
10189         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
10190         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
10191         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
10192         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
10193         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
10194         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
10195         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10196         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10197         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10198         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10199         mOnBattery = mOnBatteryInternal = false;
10200         long uptime = mClocks.uptimeMillis() * 1000;
10201         long realtime = mClocks.elapsedRealtime() * 1000;
10202         initTimes(uptime, realtime);
10203         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
10204         mDischargeStartLevel = 0;
10205         mDischargeUnplugLevel = 0;
10206         mDischargePlugLevel = -1;
10207         mDischargeCurrentLevel = 0;
10208         mCurrentBatteryLevel = 0;
10209         initDischarge();
10210         clearHistoryLocked();
10211         updateDailyDeadlineLocked();
10212         mPlatformIdleStateCallback = cb;
10213         mUserInfoProvider = userInfoProvider;
10214     }
10215 
BatteryStatsImpl(Parcel p)10216     public BatteryStatsImpl(Parcel p) {
10217         this(new SystemClocks(), p);
10218     }
10219 
BatteryStatsImpl(Clocks clocks, Parcel p)10220     public BatteryStatsImpl(Clocks clocks, Parcel p) {
10221         init(clocks);
10222         mFile = null;
10223         mCheckinFile = null;
10224         mDailyFile = null;
10225         mHandler = null;
10226         mExternalSync = null;
10227         mConstants = new Constants(mHandler);
10228         clearHistoryLocked();
10229         readFromParcel(p);
10230         mPlatformIdleStateCallback = null;
10231     }
10232 
setPowerProfileLocked(PowerProfile profile)10233     public void setPowerProfileLocked(PowerProfile profile) {
10234         mPowerProfile = profile;
10235 
10236         // We need to initialize the KernelCpuSpeedReaders to read from
10237         // the first cpu of each core. Once we have the PowerProfile, we have access to this
10238         // information.
10239         final int numClusters = mPowerProfile.getNumCpuClusters();
10240         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
10241         int firstCpuOfCluster = 0;
10242         for (int i = 0; i < numClusters; i++) {
10243             final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
10244             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
10245                     numSpeedSteps);
10246             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
10247         }
10248 
10249         if (mEstimatedBatteryCapacity == -1) {
10250             // Initialize the estimated battery capacity to a known preset one.
10251             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
10252         }
10253     }
10254 
setCallback(BatteryCallback cb)10255     public void setCallback(BatteryCallback cb) {
10256         mCallback = cb;
10257     }
10258 
setRadioScanningTimeoutLocked(long timeout)10259     public void setRadioScanningTimeoutLocked(long timeout) {
10260         if (mPhoneSignalScanningTimer != null) {
10261             mPhoneSignalScanningTimer.setTimeout(timeout);
10262         }
10263     }
10264 
setExternalStatsSyncLocked(ExternalStatsSync sync)10265     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
10266         mExternalSync = sync;
10267     }
10268 
updateDailyDeadlineLocked()10269     public void updateDailyDeadlineLocked() {
10270         // Get the current time.
10271         long currentTime = mDailyStartTime = System.currentTimeMillis();
10272         Calendar calDeadline = Calendar.getInstance();
10273         calDeadline.setTimeInMillis(currentTime);
10274 
10275         // Move time up to the next day, ranging from 1am to 3pm.
10276         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
10277         calDeadline.set(Calendar.MILLISECOND, 0);
10278         calDeadline.set(Calendar.SECOND, 0);
10279         calDeadline.set(Calendar.MINUTE, 0);
10280         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
10281         mNextMinDailyDeadline = calDeadline.getTimeInMillis();
10282         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
10283         mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
10284     }
10285 
recordDailyStatsIfNeededLocked(boolean settled)10286     public void recordDailyStatsIfNeededLocked(boolean settled) {
10287         long currentTime = System.currentTimeMillis();
10288         if (currentTime >= mNextMaxDailyDeadline) {
10289             recordDailyStatsLocked();
10290         } else if (settled && currentTime >= mNextMinDailyDeadline) {
10291             recordDailyStatsLocked();
10292         } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
10293             recordDailyStatsLocked();
10294         }
10295     }
10296 
recordDailyStatsLocked()10297     public void recordDailyStatsLocked() {
10298         DailyItem item = new DailyItem();
10299         item.mStartTime = mDailyStartTime;
10300         item.mEndTime = System.currentTimeMillis();
10301         boolean hasData = false;
10302         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
10303             hasData = true;
10304             item.mDischargeSteps = new LevelStepTracker(
10305                     mDailyDischargeStepTracker.mNumStepDurations,
10306                     mDailyDischargeStepTracker.mStepDurations);
10307         }
10308         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
10309             hasData = true;
10310             item.mChargeSteps = new LevelStepTracker(
10311                     mDailyChargeStepTracker.mNumStepDurations,
10312                     mDailyChargeStepTracker.mStepDurations);
10313         }
10314         if (mDailyPackageChanges != null) {
10315             hasData = true;
10316             item.mPackageChanges = mDailyPackageChanges;
10317             mDailyPackageChanges = null;
10318         }
10319         mDailyDischargeStepTracker.init();
10320         mDailyChargeStepTracker.init();
10321         updateDailyDeadlineLocked();
10322 
10323         if (hasData) {
10324             final long startTime = SystemClock.uptimeMillis();
10325             mDailyItems.add(item);
10326             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
10327                 mDailyItems.remove(0);
10328             }
10329             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
10330             try {
10331                 XmlSerializer out = new FastXmlSerializer();
10332                 out.setOutput(memStream, StandardCharsets.UTF_8.name());
10333                 writeDailyItemsLocked(out);
10334                 final long initialTime = SystemClock.uptimeMillis() - startTime;
10335                 BackgroundThread.getHandler().post(new Runnable() {
10336                     @Override
10337                     public void run() {
10338                         synchronized (mCheckinFile) {
10339                             final long startTime2 = SystemClock.uptimeMillis();
10340                             FileOutputStream stream = null;
10341                             try {
10342                                 stream = mDailyFile.startWrite();
10343                                 memStream.writeTo(stream);
10344                                 stream.flush();
10345                                 FileUtils.sync(stream);
10346                                 stream.close();
10347                                 mDailyFile.finishWrite(stream);
10348                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
10349                                         "batterystats-daily",
10350                                         initialTime + SystemClock.uptimeMillis() - startTime2);
10351                             } catch (IOException e) {
10352                                 Slog.w("BatteryStats",
10353                                         "Error writing battery daily items", e);
10354                                 mDailyFile.failWrite(stream);
10355                             }
10356                         }
10357                     }
10358                 });
10359             } catch (IOException e) {
10360             }
10361         }
10362     }
10363 
writeDailyItemsLocked(XmlSerializer out)10364     private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
10365         StringBuilder sb = new StringBuilder(64);
10366         out.startDocument(null, true);
10367         out.startTag(null, "daily-items");
10368         for (int i=0; i<mDailyItems.size(); i++) {
10369             final DailyItem dit = mDailyItems.get(i);
10370             out.startTag(null, "item");
10371             out.attribute(null, "start", Long.toString(dit.mStartTime));
10372             out.attribute(null, "end", Long.toString(dit.mEndTime));
10373             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
10374             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
10375             if (dit.mPackageChanges != null) {
10376                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
10377                     PackageChange pc = dit.mPackageChanges.get(j);
10378                     if (pc.mUpdate) {
10379                         out.startTag(null, "upd");
10380                         out.attribute(null, "pkg", pc.mPackageName);
10381                         out.attribute(null, "ver", Long.toString(pc.mVersionCode));
10382                         out.endTag(null, "upd");
10383                     } else {
10384                         out.startTag(null, "rem");
10385                         out.attribute(null, "pkg", pc.mPackageName);
10386                         out.endTag(null, "rem");
10387                     }
10388                 }
10389             }
10390             out.endTag(null, "item");
10391         }
10392         out.endTag(null, "daily-items");
10393         out.endDocument();
10394     }
10395 
writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)10396     private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
10397             StringBuilder tmpBuilder) throws IOException {
10398         if (steps != null) {
10399             out.startTag(null, tag);
10400             out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
10401             for (int i=0; i<steps.mNumStepDurations; i++) {
10402                 out.startTag(null, "s");
10403                 tmpBuilder.setLength(0);
10404                 steps.encodeEntryAt(i, tmpBuilder);
10405                 out.attribute(null, "v", tmpBuilder.toString());
10406                 out.endTag(null, "s");
10407             }
10408             out.endTag(null, tag);
10409         }
10410     }
10411 
readDailyStatsLocked()10412     public void readDailyStatsLocked() {
10413         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
10414         mDailyItems.clear();
10415         FileInputStream stream;
10416         try {
10417             stream = mDailyFile.openRead();
10418         } catch (FileNotFoundException e) {
10419             return;
10420         }
10421         try {
10422             XmlPullParser parser = Xml.newPullParser();
10423             parser.setInput(stream, StandardCharsets.UTF_8.name());
10424             readDailyItemsLocked(parser);
10425         } catch (XmlPullParserException e) {
10426         } finally {
10427             try {
10428                 stream.close();
10429             } catch (IOException e) {
10430             }
10431         }
10432     }
10433 
readDailyItemsLocked(XmlPullParser parser)10434     private void readDailyItemsLocked(XmlPullParser parser) {
10435         try {
10436             int type;
10437             while ((type = parser.next()) != XmlPullParser.START_TAG
10438                     && type != XmlPullParser.END_DOCUMENT) {
10439                 ;
10440             }
10441 
10442             if (type != XmlPullParser.START_TAG) {
10443                 throw new IllegalStateException("no start tag found");
10444             }
10445 
10446             int outerDepth = parser.getDepth();
10447             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10448                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10449                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10450                     continue;
10451                 }
10452 
10453                 String tagName = parser.getName();
10454                 if (tagName.equals("item")) {
10455                     readDailyItemTagLocked(parser);
10456                 } else {
10457                     Slog.w(TAG, "Unknown element under <daily-items>: "
10458                             + parser.getName());
10459                     XmlUtils.skipCurrentTag(parser);
10460                 }
10461             }
10462 
10463         } catch (IllegalStateException e) {
10464             Slog.w(TAG, "Failed parsing daily " + e);
10465         } catch (NullPointerException e) {
10466             Slog.w(TAG, "Failed parsing daily " + e);
10467         } catch (NumberFormatException e) {
10468             Slog.w(TAG, "Failed parsing daily " + e);
10469         } catch (XmlPullParserException e) {
10470             Slog.w(TAG, "Failed parsing daily " + e);
10471         } catch (IOException e) {
10472             Slog.w(TAG, "Failed parsing daily " + e);
10473         } catch (IndexOutOfBoundsException e) {
10474             Slog.w(TAG, "Failed parsing daily " + e);
10475         }
10476     }
10477 
readDailyItemTagLocked(XmlPullParser parser)10478     void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
10479             XmlPullParserException, IOException {
10480         DailyItem dit = new DailyItem();
10481         String attr = parser.getAttributeValue(null, "start");
10482         if (attr != null) {
10483             dit.mStartTime = Long.parseLong(attr);
10484         }
10485         attr = parser.getAttributeValue(null, "end");
10486         if (attr != null) {
10487             dit.mEndTime = Long.parseLong(attr);
10488         }
10489         int outerDepth = parser.getDepth();
10490         int type;
10491         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10492                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10493             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10494                 continue;
10495             }
10496 
10497             String tagName = parser.getName();
10498             if (tagName.equals("dis")) {
10499                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
10500             } else if (tagName.equals("chg")) {
10501                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
10502             } else if (tagName.equals("upd")) {
10503                 if (dit.mPackageChanges == null) {
10504                     dit.mPackageChanges = new ArrayList<>();
10505                 }
10506                 PackageChange pc = new PackageChange();
10507                 pc.mUpdate = true;
10508                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
10509                 String verStr = parser.getAttributeValue(null, "ver");
10510                 pc.mVersionCode = verStr != null ? Long.parseLong(verStr) : 0;
10511                 dit.mPackageChanges.add(pc);
10512                 XmlUtils.skipCurrentTag(parser);
10513             } else if (tagName.equals("rem")) {
10514                 if (dit.mPackageChanges == null) {
10515                     dit.mPackageChanges = new ArrayList<>();
10516                 }
10517                 PackageChange pc = new PackageChange();
10518                 pc.mUpdate = false;
10519                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
10520                 dit.mPackageChanges.add(pc);
10521                 XmlUtils.skipCurrentTag(parser);
10522             } else {
10523                 Slog.w(TAG, "Unknown element under <item>: "
10524                         + parser.getName());
10525                 XmlUtils.skipCurrentTag(parser);
10526             }
10527         }
10528         mDailyItems.add(dit);
10529     }
10530 
readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge, String tag)10531     void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
10532             String tag)
10533             throws NumberFormatException, XmlPullParserException, IOException {
10534         final String numAttr = parser.getAttributeValue(null, "n");
10535         if (numAttr == null) {
10536             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
10537             XmlUtils.skipCurrentTag(parser);
10538             return;
10539         }
10540         final int num = Integer.parseInt(numAttr);
10541         LevelStepTracker steps = new LevelStepTracker(num);
10542         if (isCharge) {
10543             dit.mChargeSteps = steps;
10544         } else {
10545             dit.mDischargeSteps = steps;
10546         }
10547         int i = 0;
10548         int outerDepth = parser.getDepth();
10549         int type;
10550         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10551                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10552             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10553                 continue;
10554             }
10555 
10556             String tagName = parser.getName();
10557             if ("s".equals(tagName)) {
10558                 if (i < num) {
10559                     String valueAttr = parser.getAttributeValue(null, "v");
10560                     if (valueAttr != null) {
10561                         steps.decodeEntryAt(i, valueAttr);
10562                         i++;
10563                     }
10564                 }
10565             } else {
10566                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
10567                         + parser.getName());
10568                 XmlUtils.skipCurrentTag(parser);
10569             }
10570         }
10571         steps.mNumStepDurations = i;
10572     }
10573 
10574     @Override
getDailyItemLocked(int daysAgo)10575     public DailyItem getDailyItemLocked(int daysAgo) {
10576         int index = mDailyItems.size()-1-daysAgo;
10577         return index >= 0 ? mDailyItems.get(index) : null;
10578     }
10579 
10580     @Override
getCurrentDailyStartTime()10581     public long getCurrentDailyStartTime() {
10582         return mDailyStartTime;
10583     }
10584 
10585     @Override
getNextMinDailyDeadline()10586     public long getNextMinDailyDeadline() {
10587         return mNextMinDailyDeadline;
10588     }
10589 
10590     @Override
getNextMaxDailyDeadline()10591     public long getNextMaxDailyDeadline() {
10592         return mNextMaxDailyDeadline;
10593     }
10594 
10595     @Override
startIteratingOldHistoryLocked()10596     public boolean startIteratingOldHistoryLocked() {
10597         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
10598                 + " pos=" + mHistoryBuffer.dataPosition());
10599         if ((mHistoryIterator = mHistory) == null) {
10600             return false;
10601         }
10602         mHistoryBuffer.setDataPosition(0);
10603         mHistoryReadTmp.clear();
10604         mReadOverflow = false;
10605         mIteratingHistory = true;
10606         return true;
10607     }
10608 
10609     @Override
getNextOldHistoryLocked(HistoryItem out)10610     public boolean getNextOldHistoryLocked(HistoryItem out) {
10611         boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
10612         if (!end) {
10613             readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
10614             mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
10615         }
10616         HistoryItem cur = mHistoryIterator;
10617         if (cur == null) {
10618             if (!mReadOverflow && !end) {
10619                 Slog.w(TAG, "Old history ends before new history!");
10620             }
10621             return false;
10622         }
10623         out.setTo(cur);
10624         mHistoryIterator = cur.next;
10625         if (!mReadOverflow) {
10626             if (end) {
10627                 Slog.w(TAG, "New history ends before old history!");
10628             } else if (!out.same(mHistoryReadTmp)) {
10629                 PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
10630                 pw.println("Histories differ!");
10631                 pw.println("Old history:");
10632                 (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
10633                 pw.println("New history:");
10634                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
10635                         true);
10636                 pw.flush();
10637             }
10638         }
10639         return true;
10640     }
10641 
10642     @Override
finishIteratingOldHistoryLocked()10643     public void finishIteratingOldHistoryLocked() {
10644         mIteratingHistory = false;
10645         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
10646         mHistoryIterator = null;
10647     }
10648 
getHistoryTotalSize()10649     public int getHistoryTotalSize() {
10650         return MAX_HISTORY_BUFFER;
10651     }
10652 
getHistoryUsedSize()10653     public int getHistoryUsedSize() {
10654         return mHistoryBuffer.dataSize();
10655     }
10656 
10657     @Override
startIteratingHistoryLocked()10658     public boolean startIteratingHistoryLocked() {
10659         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
10660                 + " pos=" + mHistoryBuffer.dataPosition());
10661         if (mHistoryBuffer.dataSize() <= 0) {
10662             return false;
10663         }
10664         mHistoryBuffer.setDataPosition(0);
10665         mReadOverflow = false;
10666         mIteratingHistory = true;
10667         mReadHistoryStrings = new String[mHistoryTagPool.size()];
10668         mReadHistoryUids = new int[mHistoryTagPool.size()];
10669         mReadHistoryChars = 0;
10670         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
10671             final HistoryTag tag = ent.getKey();
10672             final int idx = ent.getValue();
10673             mReadHistoryStrings[idx] = tag.string;
10674             mReadHistoryUids[idx] = tag.uid;
10675             mReadHistoryChars += tag.string.length() + 1;
10676         }
10677         return true;
10678     }
10679 
10680     @Override
getHistoryStringPoolSize()10681     public int getHistoryStringPoolSize() {
10682         return mReadHistoryStrings.length;
10683     }
10684 
10685     @Override
getHistoryStringPoolBytes()10686     public int getHistoryStringPoolBytes() {
10687         // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
10688         // Each string character is 2 bytes.
10689         return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
10690     }
10691 
10692     @Override
getHistoryTagPoolString(int index)10693     public String getHistoryTagPoolString(int index) {
10694         return mReadHistoryStrings[index];
10695     }
10696 
10697     @Override
getHistoryTagPoolUid(int index)10698     public int getHistoryTagPoolUid(int index) {
10699         return mReadHistoryUids[index];
10700     }
10701 
10702     @Override
getNextHistoryLocked(HistoryItem out)10703     public boolean getNextHistoryLocked(HistoryItem out) {
10704         final int pos = mHistoryBuffer.dataPosition();
10705         if (pos == 0) {
10706             out.clear();
10707         }
10708         boolean end = pos >= mHistoryBuffer.dataSize();
10709         if (end) {
10710             return false;
10711         }
10712 
10713         final long lastRealtime = out.time;
10714         final long lastWalltime = out.currentTime;
10715         readHistoryDelta(mHistoryBuffer, out);
10716         if (out.cmd != HistoryItem.CMD_CURRENT_TIME
10717                 && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
10718             out.currentTime = lastWalltime + (out.time - lastRealtime);
10719         }
10720         return true;
10721     }
10722 
10723     @Override
finishIteratingHistoryLocked()10724     public void finishIteratingHistoryLocked() {
10725         mIteratingHistory = false;
10726         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
10727         mReadHistoryStrings = null;
10728     }
10729 
10730     @Override
getHistoryBaseTime()10731     public long getHistoryBaseTime() {
10732         return mHistoryBaseTime;
10733     }
10734 
10735     @Override
getStartCount()10736     public int getStartCount() {
10737         return mStartCount;
10738     }
10739 
isOnBattery()10740     public boolean isOnBattery() {
10741         return mOnBattery;
10742     }
10743 
isCharging()10744     public boolean isCharging() {
10745         return mCharging;
10746     }
10747 
isScreenOn(int state)10748     public boolean isScreenOn(int state) {
10749         return state == Display.STATE_ON || state == Display.STATE_VR
10750             || state == Display.STATE_ON_SUSPEND;
10751     }
10752 
isScreenOff(int state)10753     public boolean isScreenOff(int state) {
10754         return state == Display.STATE_OFF;
10755     }
10756 
isScreenDoze(int state)10757     public boolean isScreenDoze(int state) {
10758         return state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND;
10759     }
10760 
initTimes(long uptime, long realtime)10761     void initTimes(long uptime, long realtime) {
10762         mStartClockTime = System.currentTimeMillis();
10763         mOnBatteryTimeBase.init(uptime, realtime);
10764         mOnBatteryScreenOffTimeBase.init(uptime, realtime);
10765         mRealtime = 0;
10766         mUptime = 0;
10767         mRealtimeStart = realtime;
10768         mUptimeStart = uptime;
10769     }
10770 
initDischarge()10771     void initDischarge() {
10772         mLowDischargeAmountSinceCharge = 0;
10773         mHighDischargeAmountSinceCharge = 0;
10774         mDischargeAmountScreenOn = 0;
10775         mDischargeAmountScreenOnSinceCharge = 0;
10776         mDischargeAmountScreenOff = 0;
10777         mDischargeAmountScreenOffSinceCharge = 0;
10778         mDischargeAmountScreenDoze = 0;
10779         mDischargeAmountScreenDozeSinceCharge = 0;
10780         mDischargeStepTracker.init();
10781         mChargeStepTracker.init();
10782         mDischargeScreenOffCounter.reset(false);
10783         mDischargeScreenDozeCounter.reset(false);
10784         mDischargeLightDozeCounter.reset(false);
10785         mDischargeDeepDozeCounter.reset(false);
10786         mDischargeCounter.reset(false);
10787     }
10788 
resetAllStatsCmdLocked()10789     public void resetAllStatsCmdLocked() {
10790         resetAllStatsLocked();
10791         final long mSecUptime = mClocks.uptimeMillis();
10792         long uptime = mSecUptime * 1000;
10793         long mSecRealtime = mClocks.elapsedRealtime();
10794         long realtime = mSecRealtime * 1000;
10795         mDischargeStartLevel = mHistoryCur.batteryLevel;
10796         pullPendingStateUpdatesLocked();
10797         addHistoryRecordLocked(mSecRealtime, mSecUptime);
10798         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
10799                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
10800         mOnBatteryTimeBase.reset(uptime, realtime);
10801         mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
10802         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
10803             if (isScreenOn(mScreenState)) {
10804                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
10805                 mDischargeScreenDozeUnplugLevel = 0;
10806                 mDischargeScreenOffUnplugLevel = 0;
10807             } else if (isScreenDoze(mScreenState)) {
10808                 mDischargeScreenOnUnplugLevel = 0;
10809                 mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
10810                 mDischargeScreenOffUnplugLevel = 0;
10811             } else {
10812                 mDischargeScreenOnUnplugLevel = 0;
10813                 mDischargeScreenDozeUnplugLevel = 0;
10814                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
10815             }
10816             mDischargeAmountScreenOn = 0;
10817             mDischargeAmountScreenOff = 0;
10818             mDischargeAmountScreenDoze = 0;
10819         }
10820         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
10821     }
10822 
resetAllStatsLocked()10823     private void resetAllStatsLocked() {
10824         final long uptimeMillis = mClocks.uptimeMillis();
10825         final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
10826         mStartCount = 0;
10827         initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
10828         mScreenOnTimer.reset(false);
10829         mScreenDozeTimer.reset(false);
10830         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10831             mScreenBrightnessTimer[i].reset(false);
10832         }
10833 
10834         if (mPowerProfile != null) {
10835             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
10836         } else {
10837             mEstimatedBatteryCapacity = -1;
10838         }
10839         mMinLearnedBatteryCapacity = -1;
10840         mMaxLearnedBatteryCapacity = -1;
10841         mInteractiveTimer.reset(false);
10842         mPowerSaveModeEnabledTimer.reset(false);
10843         mLastIdleTimeStart = elapsedRealtimeMillis;
10844         mLongestLightIdleTime = 0;
10845         mLongestFullIdleTime = 0;
10846         mDeviceIdleModeLightTimer.reset(false);
10847         mDeviceIdleModeFullTimer.reset(false);
10848         mDeviceLightIdlingTimer.reset(false);
10849         mDeviceIdlingTimer.reset(false);
10850         mPhoneOnTimer.reset(false);
10851         mAudioOnTimer.reset(false);
10852         mVideoOnTimer.reset(false);
10853         mFlashlightOnTimer.reset(false);
10854         mCameraOnTimer.reset(false);
10855         mBluetoothScanTimer.reset(false);
10856         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10857             mPhoneSignalStrengthsTimer[i].reset(false);
10858         }
10859         mPhoneSignalScanningTimer.reset(false);
10860         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10861             mPhoneDataConnectionsTimer[i].reset(false);
10862         }
10863         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10864             mNetworkByteActivityCounters[i].reset(false);
10865             mNetworkPacketActivityCounters[i].reset(false);
10866         }
10867         mMobileRadioActiveTimer.reset(false);
10868         mMobileRadioActivePerAppTimer.reset(false);
10869         mMobileRadioActiveAdjustedTime.reset(false);
10870         mMobileRadioActiveUnknownTime.reset(false);
10871         mMobileRadioActiveUnknownCount.reset(false);
10872         mWifiOnTimer.reset(false);
10873         mGlobalWifiRunningTimer.reset(false);
10874         for (int i=0; i<NUM_WIFI_STATES; i++) {
10875             mWifiStateTimer[i].reset(false);
10876         }
10877         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10878             mWifiSupplStateTimer[i].reset(false);
10879         }
10880         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10881             mWifiSignalStrengthsTimer[i].reset(false);
10882         }
10883         mWifiMulticastWakelockTimer.reset(false);
10884         mWifiActiveTimer.reset(false);
10885         mWifiActivity.reset(false);
10886         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
10887             mGpsSignalQualityTimer[i].reset(false);
10888         }
10889         mBluetoothActivity.reset(false);
10890         mModemActivity.reset(false);
10891         mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
10892 
10893         for (int i=0; i<mUidStats.size(); i++) {
10894             if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
10895                 mUidStats.remove(mUidStats.keyAt(i));
10896                 i--;
10897             }
10898         }
10899 
10900         if (mRpmStats.size() > 0) {
10901             for (SamplingTimer timer : mRpmStats.values()) {
10902                 mOnBatteryTimeBase.remove(timer);
10903             }
10904             mRpmStats.clear();
10905         }
10906         if (mScreenOffRpmStats.size() > 0) {
10907             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
10908                 mOnBatteryScreenOffTimeBase.remove(timer);
10909             }
10910             mScreenOffRpmStats.clear();
10911         }
10912 
10913         if (mKernelWakelockStats.size() > 0) {
10914             for (SamplingTimer timer : mKernelWakelockStats.values()) {
10915                 mOnBatteryScreenOffTimeBase.remove(timer);
10916             }
10917             mKernelWakelockStats.clear();
10918         }
10919 
10920         if (mKernelMemoryStats.size() > 0) {
10921             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
10922                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
10923             }
10924             mKernelMemoryStats.clear();
10925         }
10926 
10927         if (mWakeupReasonStats.size() > 0) {
10928             for (SamplingTimer timer : mWakeupReasonStats.values()) {
10929                 mOnBatteryTimeBase.remove(timer);
10930             }
10931             mWakeupReasonStats.clear();
10932         }
10933 
10934         mLastHistoryStepDetails = null;
10935         mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
10936         mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
10937         mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
10938         mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
10939         mLastStepStatUserTime = mCurStepStatUserTime = 0;
10940         mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
10941         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
10942         mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
10943         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
10944         mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
10945 
10946         mNumAllUidCpuTimeReads = 0;
10947         mNumUidsRemoved = 0;
10948 
10949         initDischarge();
10950 
10951         clearHistoryLocked();
10952         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
10953     }
10954 
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)10955     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
10956         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
10957             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
10958                 // Not recording process starts/stops.
10959                 continue;
10960             }
10961             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
10962             if (active == null) {
10963                 continue;
10964             }
10965             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
10966                 SparseIntArray uids = ent.getValue();
10967                 for (int j=0; j<uids.size(); j++) {
10968                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
10969                             uids.keyAt(j));
10970                 }
10971             }
10972         }
10973     }
10974 
updateDischargeScreenLevelsLocked(int oldState, int newState)10975     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
10976         updateOldDischargeScreenLevelLocked(oldState);
10977         updateNewDischargeScreenLevelLocked(newState);
10978     }
10979 
updateOldDischargeScreenLevelLocked(int state)10980     private void updateOldDischargeScreenLevelLocked(int state) {
10981         if (isScreenOn(state)) {
10982             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
10983             if (diff > 0) {
10984                 mDischargeAmountScreenOn += diff;
10985                 mDischargeAmountScreenOnSinceCharge += diff;
10986             }
10987         } else if (isScreenDoze(state)) {
10988             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
10989             if (diff > 0) {
10990                 mDischargeAmountScreenDoze += diff;
10991                 mDischargeAmountScreenDozeSinceCharge += diff;
10992             }
10993         } else if (isScreenOff(state)){
10994             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
10995             if (diff > 0) {
10996                 mDischargeAmountScreenOff += diff;
10997                 mDischargeAmountScreenOffSinceCharge += diff;
10998             }
10999         }
11000     }
11001 
updateNewDischargeScreenLevelLocked(int state)11002     private void updateNewDischargeScreenLevelLocked(int state) {
11003         if (isScreenOn(state)) {
11004             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
11005             mDischargeScreenOffUnplugLevel = 0;
11006             mDischargeScreenDozeUnplugLevel = 0;
11007         } else if (isScreenDoze(state)){
11008             mDischargeScreenOnUnplugLevel = 0;
11009             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
11010             mDischargeScreenOffUnplugLevel = 0;
11011         } else if (isScreenOff(state)) {
11012             mDischargeScreenOnUnplugLevel = 0;
11013             mDischargeScreenDozeUnplugLevel = 0;
11014             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
11015         }
11016     }
11017 
pullPendingStateUpdatesLocked()11018     public void pullPendingStateUpdatesLocked() {
11019         if (mOnBatteryInternal) {
11020             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
11021         }
11022     }
11023 
11024     private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
11025     private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
11026 
11027     private final Object mWifiNetworkLock = new Object();
11028 
11029     @GuardedBy("mWifiNetworkLock")
11030     private String[] mWifiIfaces = EmptyArray.STRING;
11031 
11032     @GuardedBy("mWifiNetworkLock")
11033     private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
11034 
11035     private final Object mModemNetworkLock = new Object();
11036 
11037     @GuardedBy("mModemNetworkLock")
11038     private String[] mModemIfaces = EmptyArray.STRING;
11039 
11040     @GuardedBy("mModemNetworkLock")
11041     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
11042 
readNetworkStatsLocked(String[] ifaces)11043     private NetworkStats readNetworkStatsLocked(String[] ifaces) {
11044         try {
11045             if (!ArrayUtils.isEmpty(ifaces)) {
11046                 return mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
11047                         NetworkStats.TAG_NONE, mNetworkStatsPool.acquire());
11048             }
11049         } catch (IOException e) {
11050             Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces));
11051         }
11052         return null;
11053     }
11054 
11055    /**
11056      * Distribute WiFi energy info and network traffic to apps.
11057      * @param info The energy information from the WiFi controller.
11058      */
updateWifiState(@ullable final WifiActivityEnergyInfo info)11059     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
11060         if (DEBUG_ENERGY) {
11061             Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
11062         }
11063 
11064         // Grab a separate lock to acquire the network stats, which may do I/O.
11065         NetworkStats delta = null;
11066         synchronized (mWifiNetworkLock) {
11067             final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
11068             if (latestStats != null) {
11069                 delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
11070                         mNetworkStatsPool.acquire());
11071                 mNetworkStatsPool.release(mLastWifiNetworkStats);
11072                 mLastWifiNetworkStats = latestStats;
11073             }
11074         }
11075 
11076         synchronized (this) {
11077             if (!mOnBatteryInternal) {
11078                 if (delta != null) {
11079                     mNetworkStatsPool.release(delta);
11080                 }
11081                 return;
11082             }
11083 
11084             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11085             SparseLongArray rxPackets = new SparseLongArray();
11086             SparseLongArray txPackets = new SparseLongArray();
11087             long totalTxPackets = 0;
11088             long totalRxPackets = 0;
11089             if (delta != null) {
11090                 NetworkStats.Entry entry = new NetworkStats.Entry();
11091                 final int size = delta.size();
11092                 for (int i = 0; i < size; i++) {
11093                     entry = delta.getValues(i, entry);
11094 
11095                     if (DEBUG_ENERGY) {
11096                         Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
11097                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11098                                 + " txPackets=" + entry.txPackets);
11099                     }
11100 
11101                     if (entry.rxBytes == 0 && entry.txBytes == 0) {
11102                         // Skip the lookup below since there is no work to do.
11103                         continue;
11104                     }
11105 
11106                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
11107                     if (entry.rxBytes != 0) {
11108                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
11109                                 entry.rxPackets);
11110                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11111                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
11112                                     entry.rxPackets);
11113                         }
11114                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11115                                 entry.rxBytes);
11116                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11117                                 entry.rxPackets);
11118 
11119                         rxPackets.put(u.getUid(), entry.rxPackets);
11120 
11121                         // Sum the total number of packets so that the Rx Power can
11122                         // be evenly distributed amongst the apps.
11123                         totalRxPackets += entry.rxPackets;
11124                     }
11125 
11126                     if (entry.txBytes != 0) {
11127                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
11128                                 entry.txPackets);
11129                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11130                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
11131                                     entry.txPackets);
11132                         }
11133                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11134                                 entry.txBytes);
11135                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11136                                 entry.txPackets);
11137 
11138                         txPackets.put(u.getUid(), entry.txPackets);
11139 
11140                         // Sum the total number of packets so that the Tx Power can
11141                         // be evenly distributed amongst the apps.
11142                         totalTxPackets += entry.txPackets;
11143                     }
11144                 }
11145                 mNetworkStatsPool.release(delta);
11146                 delta = null;
11147             }
11148 
11149             if (info != null) {
11150                 mHasWifiReporting = true;
11151 
11152                 // Measured in mAms
11153                 final long txTimeMs = info.getControllerTxTimeMillis();
11154                 final long rxTimeMs = info.getControllerRxTimeMillis();
11155                 final long scanTimeMs = info.getControllerScanTimeMillis();
11156                 final long idleTimeMs = info.getControllerIdleTimeMillis();
11157                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
11158 
11159                 long leftOverRxTimeMs = rxTimeMs;
11160                 long leftOverTxTimeMs = txTimeMs;
11161 
11162                 if (DEBUG_ENERGY) {
11163                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
11164                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11165                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11166                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11167                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
11168                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
11169                 }
11170 
11171                 long totalWifiLockTimeMs = 0;
11172                 long totalScanTimeMs = 0;
11173 
11174                 // On the first pass, collect some totals so that we can normalize power
11175                 // calculations if we need to.
11176                 final int uidStatsSize = mUidStats.size();
11177                 for (int i = 0; i < uidStatsSize; i++) {
11178                     final Uid uid = mUidStats.valueAt(i);
11179 
11180                     // Sum the total scan power for all apps.
11181                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
11182                             elapsedRealtimeMs * 1000) / 1000;
11183 
11184                     // Sum the total time holding wifi lock for all apps.
11185                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
11186                             elapsedRealtimeMs * 1000) / 1000;
11187                 }
11188 
11189                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
11190                     Slog.d(TAG,
11191                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
11192                                     + rxTimeMs + " ms). Normalizing scan time.");
11193                 }
11194                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
11195                     Slog.d(TAG,
11196                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
11197                                     + txTimeMs + " ms). Normalizing scan time.");
11198                 }
11199 
11200                 // Actually assign and distribute power usage to apps.
11201                 for (int i = 0; i < uidStatsSize; i++) {
11202                     final Uid uid = mUidStats.valueAt(i);
11203 
11204                     long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
11205                             elapsedRealtimeMs * 1000) / 1000;
11206                     if (scanTimeSinceMarkMs > 0) {
11207                         // Set the new mark so that next time we get new data since this point.
11208                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
11209 
11210                         long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
11211                         long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
11212 
11213                         // Our total scan time is more than the reported Tx/Rx time.
11214                         // This is possible because the cost of a scan is approximate.
11215                         // Let's normalize the result so that we evenly blame each app
11216                         // scanning.
11217                         //
11218                         // This means that we may have apps that transmitted/received packets not be
11219                         // blamed for this, but this is fine as scans are relatively more expensive.
11220                         if (totalScanTimeMs > rxTimeMs) {
11221                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
11222                                     totalScanTimeMs;
11223                         }
11224                         if (totalScanTimeMs > txTimeMs) {
11225                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
11226                                     totalScanTimeMs;
11227                         }
11228 
11229                         if (DEBUG_ENERGY) {
11230                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
11231                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
11232                                     + scanTxTimeSinceMarkMs + " ms)");
11233                         }
11234 
11235                         ControllerActivityCounterImpl activityCounter =
11236                                 uid.getOrCreateWifiControllerActivityLocked();
11237                         activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
11238                         activityCounter.getTxTimeCounters()[0].addCountLocked(
11239                                 scanTxTimeSinceMarkMs);
11240                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
11241                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
11242                     }
11243 
11244                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
11245                     // lock.
11246                     final long wifiLockTimeSinceMarkMs =
11247                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
11248                                     elapsedRealtimeMs * 1000) / 1000;
11249                     if (wifiLockTimeSinceMarkMs > 0) {
11250                         // Set the new mark so that next time we get new data since this point.
11251                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
11252 
11253                         final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
11254                                 / totalWifiLockTimeMs;
11255                         if (DEBUG_ENERGY) {
11256                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
11257                                     + myIdleTimeMs + " ms");
11258                         }
11259                         uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
11260                                 .addCountLocked(myIdleTimeMs);
11261                     }
11262                 }
11263 
11264                 if (DEBUG_ENERGY) {
11265                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
11266                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
11267                 }
11268 
11269                 // Distribute the remaining Tx power appropriately between all apps that transmitted
11270                 // packets.
11271                 for (int i = 0; i < txPackets.size(); i++) {
11272                     final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
11273                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
11274                             / totalTxPackets;
11275                     if (DEBUG_ENERGY) {
11276                         Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
11277                     }
11278                     uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
11279                             .addCountLocked(myTxTimeMs);
11280                 }
11281 
11282                 // Distribute the remaining Rx power appropriately between all apps that received
11283                 // packets.
11284                 for (int i = 0; i < rxPackets.size(); i++) {
11285                     final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
11286                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
11287                             / totalRxPackets;
11288                     if (DEBUG_ENERGY) {
11289                         Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
11290                     }
11291                     uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
11292                             .addCountLocked(myRxTimeMs);
11293                 }
11294 
11295                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
11296 
11297 
11298                 // Update WiFi controller stats.
11299                 mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
11300                 mWifiActivity.getTxTimeCounters()[0].addCountLocked(
11301                         info.getControllerTxTimeMillis());
11302                 mWifiActivity.getScanTimeCounter().addCountLocked(
11303                     info.getControllerScanTimeMillis());
11304                 mWifiActivity.getIdleTimeCounter().addCountLocked(
11305                         info.getControllerIdleTimeMillis());
11306 
11307                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11308                 final double opVolt = mPowerProfile.getAveragePower(
11309                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11310                 if (opVolt != 0) {
11311                     // We store the power drain as mAms.
11312                     mWifiActivity.getPowerCounter().addCountLocked(
11313                             (long) (info.getControllerEnergyUsed() / opVolt));
11314                 }
11315             }
11316         }
11317     }
11318 
11319     private ModemActivityInfo mLastModemActivityInfo =
11320             new ModemActivityInfo(0, 0, 0, new int[0], 0, 0);
11321 
getDeltaModemActivityInfo(ModemActivityInfo activityInfo)11322     private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
11323         if (activityInfo == null) {
11324             return null;
11325         }
11326         int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
11327         for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
11328             txTimeMs[i] = activityInfo.getTxTimeMillis()[i]
11329                     - mLastModemActivityInfo.getTxTimeMillis()[i];
11330         }
11331         ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
11332                 activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
11333                 activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
11334                 txTimeMs,
11335                 activityInfo.getRxTimeMillis() - mLastModemActivityInfo.getRxTimeMillis(),
11336                 activityInfo.getEnergyUsed() - mLastModemActivityInfo.getEnergyUsed());
11337         mLastModemActivityInfo = activityInfo;
11338         return deltaInfo;
11339     }
11340 
11341     /**
11342      * Distribute Cell radio energy info and network traffic to apps.
11343      */
updateMobileRadioState(@ullable final ModemActivityInfo activityInfo)11344     public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
11345         if (DEBUG_ENERGY) {
11346             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
11347         }
11348         ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
11349 
11350         // Add modem tx power to history.
11351         addModemTxPowerToHistory(deltaInfo);
11352 
11353         // Grab a separate lock to acquire the network stats, which may do I/O.
11354         NetworkStats delta = null;
11355         synchronized (mModemNetworkLock) {
11356             final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
11357             if (latestStats != null) {
11358                 delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
11359                         mNetworkStatsPool.acquire());
11360                 mNetworkStatsPool.release(mLastModemNetworkStats);
11361                 mLastModemNetworkStats = latestStats;
11362             }
11363         }
11364 
11365         synchronized (this) {
11366             if (!mOnBatteryInternal) {
11367                 if (delta != null) {
11368                     mNetworkStatsPool.release(delta);
11369                 }
11370                 return;
11371             }
11372 
11373             if (deltaInfo != null) {
11374                 mHasModemReporting = true;
11375                 mModemActivity.getIdleTimeCounter().addCountLocked(
11376                         deltaInfo.getIdleTimeMillis());
11377                 mModemActivity.getSleepTimeCounter().addCountLocked(
11378                         deltaInfo.getSleepTimeMillis());
11379                 mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getRxTimeMillis());
11380                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11381                     mModemActivity.getTxTimeCounters()[lvl]
11382                         .addCountLocked(deltaInfo.getTxTimeMillis()[lvl]);
11383                 }
11384 
11385                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11386                 final double opVolt = mPowerProfile.getAveragePower(
11387                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11388                 if (opVolt != 0) {
11389                     double energyUsed =
11390                             deltaInfo.getSleepTimeMillis() *
11391                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
11392                             + deltaInfo.getIdleTimeMillis() *
11393                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
11394                             + deltaInfo.getRxTimeMillis() *
11395                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
11396                     int[] txTimeMs = deltaInfo.getTxTimeMillis();
11397                     for (int i = 0; i < Math.min(txTimeMs.length,
11398                             SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
11399                         energyUsed += txTimeMs[i] * mPowerProfile.getAveragePower(
11400                                 PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
11401                     }
11402 
11403                     // We store the power drain as mAms.
11404                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
11405                 }
11406             }
11407 
11408             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11409             long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
11410                     elapsedRealtimeMs * 1000);
11411             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
11412 
11413             long totalRxPackets = 0;
11414             long totalTxPackets = 0;
11415             if (delta != null) {
11416                 NetworkStats.Entry entry = new NetworkStats.Entry();
11417                 final int size = delta.size();
11418                 for (int i = 0; i < size; i++) {
11419                     entry = delta.getValues(i, entry);
11420                     if (entry.rxPackets == 0 && entry.txPackets == 0) {
11421                         continue;
11422                     }
11423 
11424                     if (DEBUG_ENERGY) {
11425                         Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
11426                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11427                                 + " txPackets=" + entry.txPackets);
11428                     }
11429 
11430                     totalRxPackets += entry.rxPackets;
11431                     totalTxPackets += entry.txPackets;
11432 
11433                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
11434                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
11435                             entry.rxPackets);
11436                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
11437                             entry.txPackets);
11438                     if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11439                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
11440                                 entry.rxBytes, entry.rxPackets);
11441                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
11442                                 entry.txBytes, entry.txPackets);
11443                     }
11444 
11445                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11446                             entry.rxBytes);
11447                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11448                             entry.txBytes);
11449                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11450                             entry.rxPackets);
11451                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11452                             entry.txPackets);
11453                 }
11454 
11455                 // Now distribute proportional blame to the apps that did networking.
11456                 long totalPackets = totalRxPackets + totalTxPackets;
11457                 if (totalPackets > 0) {
11458                     for (int i = 0; i < size; i++) {
11459                         entry = delta.getValues(i, entry);
11460                         if (entry.rxPackets == 0 && entry.txPackets == 0) {
11461                             continue;
11462                         }
11463 
11464                         final Uid u = getUidStatsLocked(mapUid(entry.uid));
11465 
11466                         // Distribute total radio active time in to this app.
11467                         final long appPackets = entry.rxPackets + entry.txPackets;
11468                         final long appRadioTime = (radioTime * appPackets) / totalPackets;
11469                         u.noteMobileRadioActiveTimeLocked(appRadioTime);
11470 
11471                         // Remove this app from the totals, so that we don't lose any time
11472                         // due to rounding.
11473                         radioTime -= appRadioTime;
11474                         totalPackets -= appPackets;
11475 
11476                         if (deltaInfo != null) {
11477                             ControllerActivityCounterImpl activityCounter =
11478                                     u.getOrCreateModemControllerActivityLocked();
11479                             if (totalRxPackets > 0 && entry.rxPackets > 0) {
11480                                 final long rxMs = (entry.rxPackets * deltaInfo.getRxTimeMillis())
11481                                         / totalRxPackets;
11482                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
11483                             }
11484 
11485                             if (totalTxPackets > 0 && entry.txPackets > 0) {
11486                                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11487                                     long txMs =
11488                                             entry.txPackets * deltaInfo.getTxTimeMillis()[lvl];
11489                                     txMs /= totalTxPackets;
11490                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
11491                                 }
11492                             }
11493                         }
11494                     }
11495                 }
11496 
11497                 if (radioTime > 0) {
11498                     // Whoops, there is some radio time we can't blame on an app!
11499                     mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
11500                     mMobileRadioActiveUnknownCount.addCountLocked(1);
11501                 }
11502 
11503                 mNetworkStatsPool.release(delta);
11504                 delta = null;
11505             }
11506         }
11507     }
11508 
11509     /**
11510      * Add modem tx power to history
11511      * Device is said to be in high cellular transmit power when it has spent most of the transmit
11512      * time at the highest power level.
11513      * @param activityInfo
11514      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo)11515     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo) {
11516         if (activityInfo == null) {
11517             return;
11518         }
11519         int[] txTimeMs = activityInfo.getTxTimeMillis();
11520         if (txTimeMs == null || txTimeMs.length != ModemActivityInfo.TX_POWER_LEVELS) {
11521             return;
11522         }
11523         final long elapsedRealtime = mClocks.elapsedRealtime();
11524         final long uptime = mClocks.uptimeMillis();
11525         int levelMaxTimeSpent = 0;
11526         for (int i = 1; i < txTimeMs.length; i++) {
11527             if (txTimeMs[i] > txTimeMs[levelMaxTimeSpent]) {
11528                 levelMaxTimeSpent = i;
11529             }
11530         }
11531         if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
11532             if (!mIsCellularTxPowerHigh) {
11533                 mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
11534                 addHistoryRecordLocked(elapsedRealtime, uptime);
11535                 mIsCellularTxPowerHigh = true;
11536             }
11537             return;
11538         }
11539         if (mIsCellularTxPowerHigh) {
11540             mHistoryCur.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
11541             addHistoryRecordLocked(elapsedRealtime, uptime);
11542             mIsCellularTxPowerHigh = false;
11543         }
11544         return;
11545     }
11546 
11547     private final class BluetoothActivityInfoCache {
11548         long idleTimeMs;
11549         long rxTimeMs;
11550         long txTimeMs;
11551         long energy;
11552 
11553         SparseLongArray uidRxBytes = new SparseLongArray();
11554         SparseLongArray uidTxBytes = new SparseLongArray();
11555 
set(BluetoothActivityEnergyInfo info)11556         void set(BluetoothActivityEnergyInfo info) {
11557             idleTimeMs = info.getControllerIdleTimeMillis();
11558             rxTimeMs = info.getControllerRxTimeMillis();
11559             txTimeMs = info.getControllerTxTimeMillis();
11560             energy = info.getControllerEnergyUsed();
11561             if (info.getUidTraffic() != null) {
11562                 for (UidTraffic traffic : info.getUidTraffic()) {
11563                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
11564                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
11565                 }
11566             }
11567         }
11568     }
11569 
11570     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
11571             = new BluetoothActivityInfoCache();
11572 
11573     /**
11574      * Distribute Bluetooth energy info and network traffic to apps.
11575      *
11576      * @param info The energy information from the bluetooth controller.
11577      */
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info)11578     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
11579         if (DEBUG_ENERGY) {
11580             Slog.d(TAG, "Updating bluetooth stats: " + info);
11581         }
11582 
11583         if (info == null || !mOnBatteryInternal) {
11584             return;
11585         }
11586 
11587         mHasBluetoothReporting = true;
11588 
11589         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11590         final long rxTimeMs =
11591                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
11592         final long txTimeMs =
11593                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
11594         final long idleTimeMs =
11595                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
11596 
11597         if (DEBUG_ENERGY) {
11598             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
11599             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11600             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11601             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11602         }
11603 
11604         long totalScanTimeMs = 0;
11605 
11606         final int uidCount = mUidStats.size();
11607         for (int i = 0; i < uidCount; i++) {
11608             final Uid u = mUidStats.valueAt(i);
11609             if (u.mBluetoothScanTimer == null) {
11610                 continue;
11611             }
11612 
11613             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11614                     elapsedRealtimeMs * 1000) / 1000;
11615         }
11616 
11617         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
11618         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
11619 
11620         if (DEBUG_ENERGY) {
11621             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
11622                     + " TX=" + normalizeScanTxTime);
11623         }
11624 
11625         long leftOverRxTimeMs = rxTimeMs;
11626         long leftOverTxTimeMs = txTimeMs;
11627 
11628         for (int i = 0; i < uidCount; i++) {
11629             final Uid u = mUidStats.valueAt(i);
11630             if (u.mBluetoothScanTimer == null) {
11631                 continue;
11632             }
11633 
11634             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11635                     elapsedRealtimeMs * 1000) / 1000;
11636             if (scanTimeSinceMarkMs > 0) {
11637                 // Set the new mark so that next time we get new data since this point.
11638                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
11639 
11640                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
11641                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
11642 
11643                 if (normalizeScanRxTime) {
11644                     // Scan time is longer than the total rx time in the controller,
11645                     // so distribute the scan time proportionately. This means regular traffic
11646                     // will not blamed, but scans are more expensive anyways.
11647                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
11648                 }
11649 
11650                 if (normalizeScanTxTime) {
11651                     // Scan time is longer than the total tx time in the controller,
11652                     // so distribute the scan time proportionately. This means regular traffic
11653                     // will not blamed, but scans are more expensive anyways.
11654                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
11655                 }
11656 
11657                 final ControllerActivityCounterImpl counter =
11658                         u.getOrCreateBluetoothControllerActivityLocked();
11659                 counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
11660                 counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
11661 
11662                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
11663                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
11664             }
11665         }
11666 
11667         if (DEBUG_ENERGY) {
11668             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
11669                     + leftOverTxTimeMs);
11670         }
11671 
11672         //
11673         // Now distribute blame to apps that did bluetooth traffic.
11674         //
11675 
11676         long totalTxBytes = 0;
11677         long totalRxBytes = 0;
11678 
11679         final UidTraffic[] uidTraffic = info.getUidTraffic();
11680         final int numUids = uidTraffic != null ? uidTraffic.length : 0;
11681         for (int i = 0; i < numUids; i++) {
11682             final UidTraffic traffic = uidTraffic[i];
11683             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
11684                     traffic.getUid());
11685             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
11686                     traffic.getUid());
11687 
11688             // Add to the global counters.
11689             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
11690             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
11691 
11692             // Add to the UID counters.
11693             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
11694             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
11695             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
11696 
11697             // Calculate the total traffic.
11698             totalRxBytes += rxBytes;
11699             totalTxBytes += txBytes;
11700         }
11701 
11702         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
11703                 || leftOverTxTimeMs != 0)) {
11704             for (int i = 0; i < numUids; i++) {
11705                 final UidTraffic traffic = uidTraffic[i];
11706                 final int uid = traffic.getUid();
11707                 final long rxBytes =
11708                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
11709                 final long txBytes =
11710                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
11711 
11712                 final Uid u = getUidStatsLocked(mapUid(uid));
11713                 final ControllerActivityCounterImpl counter =
11714                         u.getOrCreateBluetoothControllerActivityLocked();
11715 
11716                 if (totalRxBytes > 0 && rxBytes > 0) {
11717                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
11718                     if (DEBUG_ENERGY) {
11719                         Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
11720                     }
11721                     counter.getRxTimeCounter().addCountLocked(timeRxMs);
11722                     leftOverRxTimeMs -= timeRxMs;
11723                 }
11724 
11725                 if (totalTxBytes > 0 && txBytes > 0) {
11726                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
11727                     if (DEBUG_ENERGY) {
11728                         Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
11729                     }
11730                     counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
11731                     leftOverTxTimeMs -= timeTxMs;
11732                 }
11733             }
11734         }
11735 
11736         mBluetoothActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
11737         mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(txTimeMs);
11738         mBluetoothActivity.getIdleTimeCounter().addCountLocked(idleTimeMs);
11739 
11740         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11741         final double opVolt = mPowerProfile.getAveragePower(
11742                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11743         if (opVolt != 0) {
11744             // We store the power drain as mAms.
11745             mBluetoothActivity.getPowerCounter().addCountLocked(
11746                     (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
11747                             / opVolt));
11748         }
11749         mLastBluetoothActivityInfo.set(info);
11750     }
11751 
11752     /**
11753      * Read and record Resource Power Manager (RPM) state and voter times.
11754      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
11755      * instead of fetching it anew.
11756      */
updateRpmStatsLocked()11757     public void updateRpmStatsLocked() {
11758         if (mPlatformIdleStateCallback == null) return;
11759         long now = SystemClock.elapsedRealtime();
11760         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
11761             mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats);
11762             mLastRpmStatsUpdateTimeMs = now;
11763         }
11764 
11765         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
11766                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
11767 
11768             // Update values for this platform state.
11769             final String pName = pstate.getKey();
11770             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
11771             final int pCount = pstate.getValue().mCount;
11772             getRpmTimerLocked(pName).update(pTimeUs, pCount);
11773             if (SCREEN_OFF_RPM_STATS_ENABLED) {
11774                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount);
11775             }
11776 
11777             // Update values for each voter of this platform state.
11778             for (Map.Entry<String, RpmStats.PowerStateElement> voter
11779                     : pstate.getValue().mVoters.entrySet()) {
11780                 final String vName = pName + "." + voter.getKey();
11781                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
11782                 final int vCount = voter.getValue().mCount;
11783                 getRpmTimerLocked(vName).update(vTimeUs, vCount);
11784                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
11785                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount);
11786                 }
11787             }
11788         }
11789 
11790         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
11791                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
11792 
11793             final String subsysName = subsys.getKey();
11794             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
11795                     : subsys.getValue().mStates.entrySet()) {
11796                 final String name = subsysName + "." + sstate.getKey();
11797                 final long timeUs = sstate.getValue().mTimeMs * 1000;
11798                 final int count = sstate.getValue().mCount;
11799                 getRpmTimerLocked(name).update(timeUs, count);
11800                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
11801                     getScreenOffRpmTimerLocked(name).update(timeUs, count);
11802                 }
11803             }
11804         }
11805     }
11806 
11807     /**
11808      * Read and distribute kernel wake lock use across apps.
11809      */
updateKernelWakelocksLocked()11810     public void updateKernelWakelocksLocked() {
11811         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
11812                 mTmpWakelockStats);
11813         if (wakelockStats == null) {
11814             // Not crashing might make board bringup easier.
11815             Slog.w(TAG, "Couldn't get kernel wake lock stats");
11816             return;
11817         }
11818 
11819         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
11820             String name = ent.getKey();
11821             KernelWakelockStats.Entry kws = ent.getValue();
11822 
11823             SamplingTimer kwlt = mKernelWakelockStats.get(name);
11824             if (kwlt == null) {
11825                 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
11826                 mKernelWakelockStats.put(name, kwlt);
11827             }
11828 
11829             kwlt.update(kws.mTotalTime, kws.mCount);
11830             kwlt.setUpdateVersion(kws.mVersion);
11831         }
11832 
11833         int numWakelocksSetStale = 0;
11834         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
11835         // this time.
11836         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11837             SamplingTimer st = ent.getValue();
11838             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
11839                 st.endSample();
11840                 numWakelocksSetStale++;
11841             }
11842         }
11843 
11844         // Record whether we've seen a non-zero time (for debugging b/22716723).
11845         if (wakelockStats.isEmpty()) {
11846             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
11847         }
11848 
11849         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
11850             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
11851                     wakelockStats.kernelWakelockVersion);
11852         }
11853     }
11854 
11855     // We use an anonymous class to access these variables,
11856     // so they can't live on the stack or they'd have to be
11857     // final MutableLong objects (more allocations).
11858     // Used in updateCpuTimeLocked().
11859     long mTempTotalCpuUserTimeUs;
11860     long mTempTotalCpuSystemTimeUs;
11861     long[][] mWakeLockAllocationsUs;
11862 
11863     /**
11864      * Reads the newest memory stats from the kernel.
11865      */
updateKernelMemoryBandwidthLocked()11866     public void updateKernelMemoryBandwidthLocked() {
11867         mKernelMemoryBandwidthStats.updateStats();
11868         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
11869         final int bandwidthEntryCount = bandwidthEntries.size();
11870         int index;
11871         for (int i = 0; i < bandwidthEntryCount; i++) {
11872             SamplingTimer timer;
11873             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
11874                 timer = mKernelMemoryStats.valueAt(index);
11875             } else {
11876                 timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
11877                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
11878             }
11879             timer.update(bandwidthEntries.valueAt(i), 1);
11880             if (DEBUG_MEMORY) {
11881                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
11882                         + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i),
11883                         mKernelMemoryStats.get(
11884                                 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime,
11885                         mKernelMemoryStats.size()));
11886             }
11887         }
11888     }
11889 
isOnBatteryLocked()11890     public boolean isOnBatteryLocked() {
11891         return mOnBatteryTimeBase.isRunning();
11892     }
11893 
isOnBatteryScreenOffLocked()11894     public boolean isOnBatteryScreenOffLocked() {
11895         return mOnBatteryScreenOffTimeBase.isRunning();
11896     }
11897 
11898     /**
11899      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
11900      * and we are on battery with screen off, we give more of the cpu time to those apps holding
11901      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
11902      * It's possible this will be invoked after the internal battery/screen states are updated, so
11903      * passing the appropriate battery/screen states to try attribute the cpu times to correct
11904      * buckets.
11905      */
11906     @GuardedBy("this")
updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff)11907     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) {
11908         if (mPowerProfile == null) {
11909             return;
11910         }
11911 
11912         if (DEBUG_ENERGY_CPU) {
11913             Slog.d(TAG, "!Cpu updating!");
11914         }
11915 
11916         if (mCpuFreqs == null) {
11917             mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
11918         }
11919 
11920         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
11921         // usually holding the wakelock on behalf of an app.
11922         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
11923         ArrayList<StopwatchTimer> partialTimersToConsider = null;
11924         if (onBatteryScreenOff) {
11925             partialTimersToConsider = new ArrayList<>();
11926             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11927                 final StopwatchTimer timer = mPartialTimers.get(i);
11928                 // Since the collection and blaming of wakelocks can be scheduled to run after
11929                 // some delay, the mPartialTimers list may have new entries. We can't blame
11930                 // the newly added timer for past cpu time, so we only consider timers that
11931                 // were present for one round of collection. Once a timer has gone through
11932                 // a round of collection, its mInList field is set to true.
11933                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
11934                     partialTimersToConsider.add(timer);
11935                 }
11936             }
11937         }
11938         markPartialTimersAsEligible();
11939 
11940         // When the battery is not on, we don't attribute the cpu times to any timers but we still
11941         // need to take the snapshots.
11942         if (!onBattery) {
11943             mKernelUidCpuTimeReader.readDelta(null);
11944             mKernelUidCpuFreqTimeReader.readDelta(null);
11945             mNumAllUidCpuTimeReads += 2;
11946             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11947                 mKernelUidCpuActiveTimeReader.readDelta(null);
11948                 mKernelUidCpuClusterTimeReader.readDelta(null);
11949                 mNumAllUidCpuTimeReads += 2;
11950             }
11951             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
11952                 mKernelCpuSpeedReaders[cluster].readDelta();
11953             }
11954             return;
11955         }
11956 
11957         mUserInfoProvider.refreshUserIds();
11958         final SparseLongArray updatedUids = mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()
11959                 ? null : new SparseLongArray();
11960         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
11961         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
11962         // freqs, so no need to approximate these values.
11963         if (updatedUids != null) {
11964             updateClusterSpeedTimes(updatedUids, onBattery);
11965         }
11966         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff);
11967         mNumAllUidCpuTimeReads += 2;
11968         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11969             readKernelUidCpuActiveTimesLocked(onBattery);
11970             readKernelUidCpuClusterTimesLocked(onBattery);
11971             mNumAllUidCpuTimeReads += 2;
11972         }
11973     }
11974 
11975     /**
11976      * Mark the current partial timers as gone through a collection so that they will be
11977      * considered in the next cpu times distribution to wakelock holders.
11978      */
11979     @VisibleForTesting
markPartialTimersAsEligible()11980     public void markPartialTimersAsEligible() {
11981         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
11982             // No difference, so each timer is now considered for the next collection.
11983             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11984                 mPartialTimers.get(i).mInList = true;
11985             }
11986         } else {
11987             // The lists are different, meaning we added (or removed a timer) since the last
11988             // collection.
11989             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
11990                 mLastPartialTimers.get(i).mInList = false;
11991             }
11992             mLastPartialTimers.clear();
11993 
11994             // Mark the current timers as gone through a collection.
11995             final int numPartialTimers = mPartialTimers.size();
11996             for (int i = 0; i < numPartialTimers; ++i) {
11997                 final StopwatchTimer timer = mPartialTimers.get(i);
11998                 timer.mInList = true;
11999                 mLastPartialTimers.add(timer);
12000             }
12001         }
12002     }
12003 
12004     /**
12005      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
12006      * calculate cpu times spent by each uid at different frequencies.
12007      *
12008      * @param updatedUids The uids for which times spent at different frequencies are calculated.
12009      */
12010     @VisibleForTesting
updateClusterSpeedTimes(@onNull SparseLongArray updatedUids, boolean onBattery)12011     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) {
12012         long totalCpuClustersTimeMs = 0;
12013         // Read the time spent for each cluster at various cpu frequencies.
12014         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
12015         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
12016             clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
12017             if (clusterSpeedTimesMs[cluster] != null) {
12018                 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
12019                     totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
12020                 }
12021             }
12022         }
12023         if (totalCpuClustersTimeMs != 0) {
12024             // We have cpu times per freq aggregated over all uids but we need the times per uid.
12025             // So, we distribute total time spent by an uid to different cpu freqs based on the
12026             // amount of time cpu was running at that freq.
12027             final int updatedUidsCount = updatedUids.size();
12028             for (int i = 0; i < updatedUidsCount; ++i) {
12029                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
12030                 final long appCpuTimeUs = updatedUids.valueAt(i);
12031                 // Add the cpu speeds to this UID.
12032                 final int numClusters = mPowerProfile.getNumCpuClusters();
12033                 if (u.mCpuClusterSpeedTimesUs == null ||
12034                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
12035                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
12036                 }
12037 
12038                 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
12039                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
12040                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
12041                             u.mCpuClusterSpeedTimesUs[cluster].length) {
12042                         u.mCpuClusterSpeedTimesUs[cluster]
12043                                 = new LongSamplingCounter[speedsInCluster];
12044                     }
12045 
12046                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
12047                     for (int speed = 0; speed < speedsInCluster; speed++) {
12048                         if (cpuSpeeds[speed] == null) {
12049                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
12050                         }
12051                         cpuSpeeds[speed].addCountLocked(appCpuTimeUs
12052                                 * clusterSpeedTimesMs[cluster][speed]
12053                                 / totalCpuClustersTimeMs, onBattery);
12054                     }
12055                 }
12056             }
12057         }
12058     }
12059 
12060     /**
12061      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
12062      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
12063      * wakelock holders.
12064      *
12065      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
12066      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
12067      */
12068     @VisibleForTesting
readKernelUidCpuTimesLocked(@ullable ArrayList<StopwatchTimer> partialTimers, @Nullable SparseLongArray updatedUids, boolean onBattery)12069     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
12070             @Nullable SparseLongArray updatedUids, boolean onBattery) {
12071         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
12072         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
12073         final long startTimeMs = mClocks.uptimeMillis();
12074 
12075         mKernelUidCpuTimeReader.readDelta((uid, userTimeUs, systemTimeUs) -> {
12076             uid = mapUid(uid);
12077             if (Process.isIsolated(uid)) {
12078                 // This could happen if the isolated uid mapping was removed before that process
12079                 // was actually killed.
12080                 mKernelUidCpuTimeReader.removeUid(uid);
12081                 Slog.d(TAG, "Got readings for an isolated uid with no mapping: " + uid);
12082                 return;
12083             }
12084             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12085                 Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
12086                 mKernelUidCpuTimeReader.removeUid(uid);
12087                 return;
12088             }
12089             final Uid u = getUidStatsLocked(uid);
12090 
12091             // Accumulate the total system and user time.
12092             mTempTotalCpuUserTimeUs += userTimeUs;
12093             mTempTotalCpuSystemTimeUs += systemTimeUs;
12094 
12095             StringBuilder sb = null;
12096             if (DEBUG_ENERGY_CPU) {
12097                 sb = new StringBuilder();
12098                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
12099                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
12100                 sb.append(" s=");
12101                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
12102                 sb.append("\n");
12103             }
12104 
12105             if (numWakelocks > 0) {
12106                 // We have wakelocks being held, so only give a portion of the
12107                 // time to the process. The rest will be distributed among wakelock
12108                 // holders.
12109                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
12110                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
12111             }
12112 
12113             if (sb != null) {
12114                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
12115                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
12116                 sb.append(" s=");
12117                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
12118                 Slog.d(TAG, sb.toString());
12119             }
12120 
12121             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
12122             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
12123             if (updatedUids != null) {
12124                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
12125             }
12126         });
12127 
12128         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12129         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12130             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
12131         }
12132 
12133         if (numWakelocks > 0) {
12134             // Distribute a portion of the total cpu time to wakelock holders.
12135             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
12136             mTempTotalCpuSystemTimeUs =
12137                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
12138 
12139             for (int i = 0; i < numWakelocks; ++i) {
12140                 final StopwatchTimer timer = partialTimers.get(i);
12141                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
12142                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
12143 
12144                 if (DEBUG_ENERGY_CPU) {
12145                     final StringBuilder sb = new StringBuilder();
12146                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
12147                             .append(": u=");
12148                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
12149                     sb.append(" s=");
12150                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
12151                     Slog.d(TAG, sb.toString());
12152                 }
12153 
12154                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
12155                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
12156                 if (updatedUids != null) {
12157                     final int uid = timer.mUid.getUid();
12158                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
12159                 }
12160 
12161                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
12162                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
12163 
12164                 mTempTotalCpuUserTimeUs -= userTimeUs;
12165                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
12166             }
12167         }
12168     }
12169 
12170     /**
12171      * Take a snapshot of the cpu times spent by each uid in each freq and update the
12172      * corresponding counters.
12173      *
12174      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
12175      */
12176     @VisibleForTesting
readKernelUidCpuFreqTimesLocked(@ullable ArrayList<StopwatchTimer> partialTimers, boolean onBattery, boolean onBatteryScreenOff)12177     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
12178             boolean onBattery, boolean onBatteryScreenOff) {
12179         final boolean perClusterTimesAvailable =
12180                 mKernelUidCpuFreqTimeReader.perClusterTimesAvailable();
12181         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
12182         final int numClusters = mPowerProfile.getNumCpuClusters();
12183         mWakeLockAllocationsUs = null;
12184         final long startTimeMs = mClocks.uptimeMillis();
12185         mKernelUidCpuFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
12186             uid = mapUid(uid);
12187             if (Process.isIsolated(uid)) {
12188                 mKernelUidCpuFreqTimeReader.removeUid(uid);
12189                 Slog.d(TAG, "Got freq readings for an isolated uid with no mapping: " + uid);
12190                 return;
12191             }
12192             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12193                 Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
12194                 mKernelUidCpuFreqTimeReader.removeUid(uid);
12195                 return;
12196             }
12197             final Uid u = getUidStatsLocked(uid);
12198             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
12199                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
12200             }
12201             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
12202             if (u.mScreenOffCpuFreqTimeMs == null ||
12203                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
12204                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
12205                         mOnBatteryScreenOffTimeBase);
12206             }
12207             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
12208 
12209             if (perClusterTimesAvailable) {
12210                 if (u.mCpuClusterSpeedTimesUs == null ||
12211                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
12212                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
12213                 }
12214                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
12215                     mWakeLockAllocationsUs = new long[numClusters][];
12216                 }
12217 
12218                 int freqIndex = 0;
12219                 for (int cluster = 0; cluster < numClusters; ++cluster) {
12220                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
12221                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
12222                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
12223                         u.mCpuClusterSpeedTimesUs[cluster]
12224                                 = new LongSamplingCounter[speedsInCluster];
12225                     }
12226                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
12227                         mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
12228                     }
12229                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
12230                     for (int speed = 0; speed < speedsInCluster; ++speed) {
12231                         if (cpuTimesUs[speed] == null) {
12232                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
12233                         }
12234                         final long appAllocationUs;
12235                         if (mWakeLockAllocationsUs != null) {
12236                             appAllocationUs =
12237                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
12238                             mWakeLockAllocationsUs[cluster][speed] +=
12239                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
12240                         } else {
12241                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
12242                         }
12243                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
12244                         freqIndex++;
12245                     }
12246                 }
12247             }
12248         });
12249 
12250         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12251         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12252             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
12253         }
12254 
12255         if (mWakeLockAllocationsUs != null) {
12256             for (int i = 0; i < numWakelocks; ++i) {
12257                 final Uid u = partialTimers.get(i).mUid;
12258                 if (u.mCpuClusterSpeedTimesUs == null ||
12259                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
12260                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
12261                 }
12262 
12263                 for (int cluster = 0; cluster < numClusters; ++cluster) {
12264                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
12265                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
12266                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
12267                         u.mCpuClusterSpeedTimesUs[cluster]
12268                                 = new LongSamplingCounter[speedsInCluster];
12269                     }
12270                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
12271                     for (int speed = 0; speed < speedsInCluster; ++speed) {
12272                         if (cpuTimeUs[speed] == null) {
12273                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
12274                         }
12275                         final long allocationUs =
12276                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
12277                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
12278                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
12279                     }
12280                 }
12281             }
12282         }
12283     }
12284 
12285     /**
12286      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
12287      * counters.
12288      */
12289     @VisibleForTesting
readKernelUidCpuActiveTimesLocked(boolean onBattery)12290     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
12291         final long startTimeMs = mClocks.uptimeMillis();
12292         mKernelUidCpuActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> {
12293             uid = mapUid(uid);
12294             if (Process.isIsolated(uid)) {
12295                 mKernelUidCpuActiveTimeReader.removeUid(uid);
12296                 Slog.w(TAG, "Got active times for an isolated uid with no mapping: " + uid);
12297                 return;
12298             }
12299             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12300                 Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
12301                 mKernelUidCpuActiveTimeReader.removeUid(uid);
12302                 return;
12303             }
12304             final Uid u = getUidStatsLocked(uid);
12305             u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery);
12306         });
12307 
12308         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12309         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12310             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
12311         }
12312     }
12313 
12314     /**
12315      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
12316      * counters.
12317      */
12318     @VisibleForTesting
readKernelUidCpuClusterTimesLocked(boolean onBattery)12319     public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
12320         final long startTimeMs = mClocks.uptimeMillis();
12321         mKernelUidCpuClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> {
12322             uid = mapUid(uid);
12323             if (Process.isIsolated(uid)) {
12324                 mKernelUidCpuClusterTimeReader.removeUid(uid);
12325                 Slog.w(TAG, "Got cluster times for an isolated uid with no mapping: " + uid);
12326                 return;
12327             }
12328             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12329                 Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
12330                 mKernelUidCpuClusterTimeReader.removeUid(uid);
12331                 return;
12332             }
12333             final Uid u = getUidStatsLocked(uid);
12334             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
12335         });
12336 
12337         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12338         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12339             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
12340         }
12341     }
12342 
setChargingLocked(boolean charging)12343     boolean setChargingLocked(boolean charging) {
12344         if (mCharging != charging) {
12345             mCharging = charging;
12346             if (charging) {
12347                 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12348             } else {
12349                 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
12350             }
12351             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
12352             return true;
12353         }
12354         return false;
12355     }
12356 
12357     @GuardedBy("this")
setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery, final int oldStatus, final int level, final int chargeUAh)12358     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
12359             final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
12360         boolean doWrite = false;
12361         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
12362         m.arg1 = onBattery ? 1 : 0;
12363         mHandler.sendMessage(m);
12364 
12365         final long uptime = mSecUptime * 1000;
12366         final long realtime = mSecRealtime * 1000;
12367         final int screenState = mScreenState;
12368         if (onBattery) {
12369             // We will reset our status if we are unplugging after the
12370             // battery was last full, or the level is at 100, or
12371             // we have gone through a significant charge (from a very low
12372             // level to a now very high level).
12373             boolean reset = false;
12374             if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
12375                     || level >= 90
12376                     || (mDischargeCurrentLevel < 20 && level >= 80)
12377                     || (getHighDischargeAmountSinceCharge() >= 200
12378                             && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
12379                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
12380                         + " dischargeLevel=" + mDischargeCurrentLevel
12381                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
12382                         + " highAmount=" + getHighDischargeAmountSinceCharge());
12383                 // Before we write, collect a snapshot of the final aggregated
12384                 // stats to be reported in the next checkin.  Only do this if we have
12385                 // a sufficient amount of data to make it interesting.
12386                 if (getLowDischargeAmountSinceCharge() >= 20) {
12387                     final long startTime = SystemClock.uptimeMillis();
12388                     final Parcel parcel = Parcel.obtain();
12389                     writeSummaryToParcel(parcel, true);
12390                     final long initialTime = SystemClock.uptimeMillis() - startTime;
12391                     BackgroundThread.getHandler().post(new Runnable() {
12392                         @Override public void run() {
12393                             synchronized (mCheckinFile) {
12394                                 final long startTime2 = SystemClock.uptimeMillis();
12395                                 FileOutputStream stream = null;
12396                                 try {
12397                                     stream = mCheckinFile.startWrite();
12398                                     stream.write(parcel.marshall());
12399                                     stream.flush();
12400                                     FileUtils.sync(stream);
12401                                     stream.close();
12402                                     mCheckinFile.finishWrite(stream);
12403                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
12404                                             "batterystats-checkin",
12405                                             initialTime + SystemClock.uptimeMillis() - startTime2);
12406                                 } catch (IOException e) {
12407                                     Slog.w("BatteryStats",
12408                                             "Error writing checkin battery statistics", e);
12409                                     mCheckinFile.failWrite(stream);
12410                                 } finally {
12411                                     parcel.recycle();
12412                                 }
12413                             }
12414                         }
12415                     });
12416                 }
12417                 doWrite = true;
12418                 resetAllStatsLocked();
12419                 if (chargeUAh > 0 && level > 0) {
12420                     // Only use the reported coulomb charge value if it is supported and reported.
12421                     mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
12422                 }
12423                 mDischargeStartLevel = level;
12424                 reset = true;
12425                 mDischargeStepTracker.init();
12426             }
12427             if (mCharging) {
12428                 setChargingLocked(false);
12429             }
12430             mLastChargingStateLevel = level;
12431             mOnBattery = mOnBatteryInternal = true;
12432             mLastDischargeStepLevel = level;
12433             mMinDischargeStepLevel = level;
12434             mDischargeStepTracker.clearTime();
12435             mDailyDischargeStepTracker.clearTime();
12436             mInitStepMode = mCurStepMode;
12437             mModStepMode = 0;
12438             pullPendingStateUpdatesLocked();
12439             mHistoryCur.batteryLevel = (byte)level;
12440             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12441             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
12442                     + Integer.toHexString(mHistoryCur.states));
12443             if (reset) {
12444                 mRecordingHistory = true;
12445                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
12446             }
12447             addHistoryRecordLocked(mSecRealtime, mSecUptime);
12448             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
12449             if (isScreenOn(screenState)) {
12450                 mDischargeScreenOnUnplugLevel = level;
12451                 mDischargeScreenDozeUnplugLevel = 0;
12452                 mDischargeScreenOffUnplugLevel = 0;
12453             } else if (isScreenDoze(screenState)) {
12454                 mDischargeScreenOnUnplugLevel = 0;
12455                 mDischargeScreenDozeUnplugLevel = level;
12456                 mDischargeScreenOffUnplugLevel = 0;
12457             } else {
12458                 mDischargeScreenOnUnplugLevel = 0;
12459                 mDischargeScreenDozeUnplugLevel = 0;
12460                 mDischargeScreenOffUnplugLevel = level;
12461             }
12462             mDischargeAmountScreenOn = 0;
12463             mDischargeAmountScreenDoze = 0;
12464             mDischargeAmountScreenOff = 0;
12465             updateTimeBasesLocked(true, screenState, uptime, realtime);
12466         } else {
12467             mLastChargingStateLevel = level;
12468             mOnBattery = mOnBatteryInternal = false;
12469             pullPendingStateUpdatesLocked();
12470             mHistoryCur.batteryLevel = (byte)level;
12471             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12472             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
12473                     + Integer.toHexString(mHistoryCur.states));
12474             addHistoryRecordLocked(mSecRealtime, mSecUptime);
12475             mDischargeCurrentLevel = mDischargePlugLevel = level;
12476             if (level < mDischargeUnplugLevel) {
12477                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
12478                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
12479             }
12480             updateDischargeScreenLevelsLocked(screenState, screenState);
12481             updateTimeBasesLocked(false, screenState, uptime, realtime);
12482             mChargeStepTracker.init();
12483             mLastChargeStepLevel = level;
12484             mMaxChargeStepLevel = level;
12485             mInitStepMode = mCurStepMode;
12486             mModStepMode = 0;
12487         }
12488         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
12489             if (mFile != null) {
12490                 writeAsyncLocked();
12491             }
12492         }
12493     }
12494 
startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs, boolean reset)12495     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
12496             boolean reset) {
12497         mRecordingHistory = true;
12498         mHistoryCur.currentTime = System.currentTimeMillis();
12499         addHistoryBufferLocked(elapsedRealtimeMs,
12500                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
12501                 mHistoryCur);
12502         mHistoryCur.currentTime = 0;
12503         if (reset) {
12504             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
12505         }
12506     }
12507 
recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs, final long uptimeMs)12508     private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
12509             final long uptimeMs) {
12510         if (mRecordingHistory) {
12511             mHistoryCur.currentTime = currentTime;
12512             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
12513             mHistoryCur.currentTime = 0;
12514         }
12515     }
12516 
recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs)12517     private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
12518         if (mRecordingHistory) {
12519             mHistoryCur.currentTime = System.currentTimeMillis();
12520             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
12521             mHistoryCur.currentTime = 0;
12522         }
12523     }
12524 
scheduleSyncExternalStatsLocked(String reason, int updateFlags)12525     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
12526         if (mExternalSync != null) {
12527             mExternalSync.scheduleSync(reason, updateFlags);
12528         }
12529     }
12530 
12531     // This should probably be exposed in the API, though it's not critical
12532     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
12533 
12534     @GuardedBy("this")
setBatteryStateLocked(final int status, final int health, final int plugType, final int level, int temp, final int volt, final int chargeUAh, final int chargeFullUAh)12535     public void setBatteryStateLocked(final int status, final int health, final int plugType,
12536             final int level, /* not final */ int temp, final int volt, final int chargeUAh,
12537             final int chargeFullUAh) {
12538         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
12539         temp = Math.max(0, temp);
12540 
12541         reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
12542                 status, plugType, level);
12543 
12544         final boolean onBattery = isOnBattery(plugType, status);
12545         final long uptime = mClocks.uptimeMillis();
12546         final long elapsedRealtime = mClocks.elapsedRealtime();
12547         if (!mHaveBatteryLevel) {
12548             mHaveBatteryLevel = true;
12549             // We start out assuming that the device is plugged in (not
12550             // on battery).  If our first report is now that we are indeed
12551             // plugged in, then twiddle our state to correctly reflect that
12552             // since we won't be going through the full setOnBattery().
12553             if (onBattery == mOnBattery) {
12554                 if (onBattery) {
12555                     mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12556                 } else {
12557                     mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12558                 }
12559             }
12560             // Always start out assuming charging, that will be updated later.
12561             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12562             mHistoryCur.batteryStatus = (byte)status;
12563             mHistoryCur.batteryLevel = (byte)level;
12564             mHistoryCur.batteryChargeUAh = chargeUAh;
12565             mMaxChargeStepLevel = mMinDischargeStepLevel =
12566                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
12567             mLastChargingStateLevel = level;
12568         } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
12569             recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
12570         }
12571         int oldStatus = mHistoryCur.batteryStatus;
12572         if (onBattery) {
12573             mDischargeCurrentLevel = level;
12574             if (!mRecordingHistory) {
12575                 mRecordingHistory = true;
12576                 startRecordingHistory(elapsedRealtime, uptime, true);
12577             }
12578         } else if (level < 96 &&
12579             status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
12580             if (!mRecordingHistory) {
12581                 mRecordingHistory = true;
12582                 startRecordingHistory(elapsedRealtime, uptime, true);
12583             }
12584         }
12585         mCurrentBatteryLevel = level;
12586         if (mDischargePlugLevel < 0) {
12587             mDischargePlugLevel = level;
12588         }
12589 
12590         if (onBattery != mOnBattery) {
12591             mHistoryCur.batteryLevel = (byte)level;
12592             mHistoryCur.batteryStatus = (byte)status;
12593             mHistoryCur.batteryHealth = (byte)health;
12594             mHistoryCur.batteryPlugType = (byte)plugType;
12595             mHistoryCur.batteryTemperature = (short)temp;
12596             mHistoryCur.batteryVoltage = (char)volt;
12597             if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12598                 // Only record discharges
12599                 final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12600                 mDischargeCounter.addCountLocked(chargeDiff);
12601                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12602                 if (isScreenDoze(mScreenState)) {
12603                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12604                 }
12605                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12606                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12607                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12608                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12609                 }
12610             }
12611             mHistoryCur.batteryChargeUAh = chargeUAh;
12612             setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
12613         } else {
12614             boolean changed = false;
12615             if (mHistoryCur.batteryLevel != level) {
12616                 mHistoryCur.batteryLevel = (byte)level;
12617                 changed = true;
12618 
12619                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
12620                 // which will pull external stats.
12621                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
12622                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
12623             }
12624             if (mHistoryCur.batteryStatus != status) {
12625                 mHistoryCur.batteryStatus = (byte)status;
12626                 changed = true;
12627             }
12628             if (mHistoryCur.batteryHealth != health) {
12629                 mHistoryCur.batteryHealth = (byte)health;
12630                 changed = true;
12631             }
12632             if (mHistoryCur.batteryPlugType != plugType) {
12633                 mHistoryCur.batteryPlugType = (byte)plugType;
12634                 changed = true;
12635             }
12636             if (temp >= (mHistoryCur.batteryTemperature+10)
12637                     || temp <= (mHistoryCur.batteryTemperature-10)) {
12638                 mHistoryCur.batteryTemperature = (short)temp;
12639                 changed = true;
12640             }
12641             if (volt > (mHistoryCur.batteryVoltage+20)
12642                     || volt < (mHistoryCur.batteryVoltage-20)) {
12643                 mHistoryCur.batteryVoltage = (char)volt;
12644                 changed = true;
12645             }
12646             if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
12647                     || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
12648                 if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12649                     // Only record discharges
12650                     final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12651                     mDischargeCounter.addCountLocked(chargeDiff);
12652                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12653                     if (isScreenDoze(mScreenState)) {
12654                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12655                     }
12656                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12657                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12658                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12659                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12660                     }
12661                 }
12662                 mHistoryCur.batteryChargeUAh = chargeUAh;
12663                 changed = true;
12664             }
12665             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
12666                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
12667                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
12668             if (onBattery) {
12669                 changed |= setChargingLocked(false);
12670                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
12671                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12672                             modeBits, elapsedRealtime);
12673                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12674                             modeBits, elapsedRealtime);
12675                     mLastDischargeStepLevel = level;
12676                     mMinDischargeStepLevel = level;
12677                     mInitStepMode = mCurStepMode;
12678                     mModStepMode = 0;
12679                 }
12680             } else {
12681                 if (level >= 90) {
12682                     // If the battery level is at least 90%, always consider the device to be
12683                     // charging even if it happens to go down a level.
12684                     changed |= setChargingLocked(true);
12685                     mLastChargeStepLevel = level;
12686                 } if (!mCharging) {
12687                     if (mLastChargeStepLevel < level) {
12688                         // We have not reporting that we are charging, but the level has now
12689                         // gone up, so consider the state to be charging.
12690                         changed |= setChargingLocked(true);
12691                         mLastChargeStepLevel = level;
12692                     }
12693                 } else {
12694                     if (mLastChargeStepLevel > level) {
12695                         // We had reported that the device was charging, but here we are with
12696                         // power connected and the level going down.  Looks like the current
12697                         // power supplied isn't enough, so consider the device to now be
12698                         // discharging.
12699                         changed |= setChargingLocked(false);
12700                         mLastChargeStepLevel = level;
12701                     }
12702                 }
12703                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
12704                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12705                             modeBits, elapsedRealtime);
12706                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12707                             modeBits, elapsedRealtime);
12708                     mLastChargeStepLevel = level;
12709                     mMaxChargeStepLevel = level;
12710                     mInitStepMode = mCurStepMode;
12711                     mModStepMode = 0;
12712                 }
12713             }
12714             if (changed) {
12715                 addHistoryRecordLocked(elapsedRealtime, uptime);
12716             }
12717         }
12718         if (!onBattery &&
12719             (status == BatteryManager.BATTERY_STATUS_FULL ||
12720              status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
12721             // We don't record history while we are plugged in and fully charged
12722             // (or when battery is not present).  The next time we are
12723             // unplugged, history will be cleared.
12724             mRecordingHistory = DEBUG;
12725         }
12726 
12727         if (mMinLearnedBatteryCapacity == -1) {
12728             mMinLearnedBatteryCapacity = chargeFullUAh;
12729         } else {
12730             Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
12731         }
12732         mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
12733     }
12734 
isOnBattery(int plugType, int status)12735     public static boolean isOnBattery(int plugType, int status) {
12736         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
12737     }
12738 
12739     // Inform StatsLog of setBatteryState changes.
12740     // If this is the first reporting, pass in recentPast == null.
reportChangesToStatsLog(HistoryItem recentPast, final int status, final int plugType, final int level)12741     private void reportChangesToStatsLog(HistoryItem recentPast,
12742             final int status, final int plugType, final int level) {
12743 
12744         if (recentPast == null || recentPast.batteryStatus != status) {
12745             StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, status);
12746         }
12747         if (recentPast == null || recentPast.batteryPlugType != plugType) {
12748             StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, plugType);
12749         }
12750         if (recentPast == null || recentPast.batteryLevel != level) {
12751             StatsLog.write(StatsLog.BATTERY_LEVEL_CHANGED, level);
12752         }
12753     }
12754 
getAwakeTimeBattery()12755     public long getAwakeTimeBattery() {
12756         return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
12757     }
12758 
getAwakeTimePlugged()12759     public long getAwakeTimePlugged() {
12760         return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
12761     }
12762 
12763     @Override
computeUptime(long curTime, int which)12764     public long computeUptime(long curTime, int which) {
12765         switch (which) {
12766             case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
12767             case STATS_CURRENT: return (curTime-mUptimeStart);
12768             case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
12769         }
12770         return 0;
12771     }
12772 
12773     @Override
computeRealtime(long curTime, int which)12774     public long computeRealtime(long curTime, int which) {
12775         switch (which) {
12776             case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
12777             case STATS_CURRENT: return (curTime-mRealtimeStart);
12778             case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
12779         }
12780         return 0;
12781     }
12782 
12783     @Override
computeBatteryUptime(long curTime, int which)12784     public long computeBatteryUptime(long curTime, int which) {
12785         return mOnBatteryTimeBase.computeUptime(curTime, which);
12786     }
12787 
12788     @Override
computeBatteryRealtime(long curTime, int which)12789     public long computeBatteryRealtime(long curTime, int which) {
12790         return mOnBatteryTimeBase.computeRealtime(curTime, which);
12791     }
12792 
12793     @Override
computeBatteryScreenOffUptime(long curTime, int which)12794     public long computeBatteryScreenOffUptime(long curTime, int which) {
12795         return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
12796     }
12797 
12798     @Override
computeBatteryScreenOffRealtime(long curTime, int which)12799     public long computeBatteryScreenOffRealtime(long curTime, int which) {
12800         return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
12801     }
12802 
computeTimePerLevel(long[] steps, int numSteps)12803     private long computeTimePerLevel(long[] steps, int numSteps) {
12804         // For now we'll do a simple average across all steps.
12805         if (numSteps <= 0) {
12806             return -1;
12807         }
12808         long total = 0;
12809         for (int i=0; i<numSteps; i++) {
12810             total += steps[i] & STEP_LEVEL_TIME_MASK;
12811         }
12812         return total / numSteps;
12813         /*
12814         long[] buckets = new long[numSteps];
12815         int numBuckets = 0;
12816         int numToAverage = 4;
12817         int i = 0;
12818         while (i < numSteps) {
12819             long totalTime = 0;
12820             int num = 0;
12821             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
12822                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
12823                 num++;
12824             }
12825             buckets[numBuckets] = totalTime / num;
12826             numBuckets++;
12827             numToAverage *= 2;
12828             i += num;
12829         }
12830         if (numBuckets < 1) {
12831             return -1;
12832         }
12833         long averageTime = buckets[numBuckets-1];
12834         for (i=numBuckets-2; i>=0; i--) {
12835             averageTime = (averageTime + buckets[i]) / 2;
12836         }
12837         return averageTime;
12838         */
12839     }
12840 
12841     @Override
computeBatteryTimeRemaining(long curTime)12842     public long computeBatteryTimeRemaining(long curTime) {
12843         if (!mOnBattery) {
12844             return -1;
12845         }
12846         /* Simple implementation just looks at the average discharge per level across the
12847            entire sample period.
12848         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
12849         if (discharge < 2) {
12850             return -1;
12851         }
12852         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
12853         if (duration < 1000*1000) {
12854             return -1;
12855         }
12856         long usPerLevel = duration/discharge;
12857         return usPerLevel * mCurrentBatteryLevel;
12858         */
12859         if (mDischargeStepTracker.mNumStepDurations < 1) {
12860             return -1;
12861         }
12862         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
12863         if (msPerLevel <= 0) {
12864             return -1;
12865         }
12866         return (msPerLevel * mCurrentBatteryLevel) * 1000;
12867     }
12868 
12869     @Override
getDischargeLevelStepTracker()12870     public LevelStepTracker getDischargeLevelStepTracker() {
12871         return mDischargeStepTracker;
12872     }
12873 
12874     @Override
getDailyDischargeLevelStepTracker()12875     public LevelStepTracker getDailyDischargeLevelStepTracker() {
12876         return mDailyDischargeStepTracker;
12877     }
12878 
12879     @Override
computeChargeTimeRemaining(long curTime)12880     public long computeChargeTimeRemaining(long curTime) {
12881         if (mOnBattery) {
12882             // Not yet working.
12883             return -1;
12884         }
12885         /* Broken
12886         int curLevel = mCurrentBatteryLevel;
12887         int plugLevel = mDischargePlugLevel;
12888         if (plugLevel < 0 || curLevel < (plugLevel+1)) {
12889             return -1;
12890         }
12891         long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
12892         if (duration < 1000*1000) {
12893             return -1;
12894         }
12895         long usPerLevel = duration/(curLevel-plugLevel);
12896         return usPerLevel * (100-curLevel);
12897         */
12898         if (mChargeStepTracker.mNumStepDurations < 1) {
12899             return -1;
12900         }
12901         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
12902         if (msPerLevel <= 0) {
12903             return -1;
12904         }
12905         return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
12906     }
12907 
12908     /*@hide */
getCellularBatteryStats()12909     public CellularBatteryStats getCellularBatteryStats() {
12910         CellularBatteryStats s = new CellularBatteryStats();
12911         final int which = STATS_SINCE_CHARGED;
12912         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12913         final ControllerActivityCounter counter = getModemControllerActivity();
12914         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
12915         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12916         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12917         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12918         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
12919         for (int i = 0; i < timeInRatMs.length; i++) {
12920            timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
12921         }
12922         long[] timeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
12923         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
12924            timeInRxSignalStrengthLevelMs[i]
12925                = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
12926         }
12927         long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
12928             counter.getTxTimeCounters().length)];
12929         long totalTxTimeMs = 0;
12930         for (int i = 0; i < txTimeMs.length; i++) {
12931             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
12932             totalTxTimeMs += txTimeMs[i];
12933         }
12934         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12935         s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
12936         s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
12937         s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
12938         s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
12939         s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
12940         s.setSleepTimeMs(sleepTimeMs);
12941         s.setIdleTimeMs(idleTimeMs);
12942         s.setRxTimeMs(rxTimeMs);
12943         s.setEnergyConsumedMaMs(energyConsumedMaMs);
12944         s.setTimeInRatMs(timeInRatMs);
12945         s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
12946         s.setTxTimeMs(txTimeMs);
12947         return s;
12948     }
12949 
12950      /*@hide */
getWifiBatteryStats()12951      public WifiBatteryStats getWifiBatteryStats() {
12952          WifiBatteryStats s = new WifiBatteryStats();
12953          final int which = STATS_SINCE_CHARGED;
12954          final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12955          final ControllerActivityCounter counter = getWifiControllerActivity();
12956          final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12957          final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
12958          final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12959          final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
12960          final long totalControllerActivityTimeMs
12961              = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
12962          final long sleepTimeMs
12963              = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
12964          final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12965          long numAppScanRequest = 0;
12966          for (int i = 0; i < mUidStats.size(); i++) {
12967              numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
12968          }
12969          long[] timeInStateMs = new long[NUM_WIFI_STATES];
12970          for (int i=0; i<NUM_WIFI_STATES; i++) {
12971             timeInStateMs[i] = getWifiStateTime(i, rawRealTime, which) / 1000;
12972          }
12973          long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
12974          for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12975              timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000;
12976          }
12977          long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
12978          for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12979              timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000;
12980          }
12981          s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12982          s.setKernelActiveTimeMs(getWifiActiveTime(rawRealTime, which) / 1000);
12983          s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
12984          s.setNumBytesTx(getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
12985          s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
12986          s.setNumBytesRx(getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
12987          s.setSleepTimeMs(sleepTimeMs);
12988          s.setIdleTimeMs(idleTimeMs);
12989          s.setRxTimeMs(rxTimeMs);
12990          s.setTxTimeMs(txTimeMs);
12991          s.setScanTimeMs(scanTimeMs);
12992          s.setEnergyConsumedMaMs(energyConsumedMaMs);
12993          s.setNumAppScanRequest(numAppScanRequest);
12994          s.setTimeInStateMs(timeInStateMs);
12995          s.setTimeInSupplicantStateMs(timeInSupplStateMs);
12996          s.setTimeInRxSignalStrengthLevelMs(timeSignalStrengthTimeMs);
12997          return s;
12998      }
12999 
13000     /*@hide */
getGpsBatteryStats()13001     public GpsBatteryStats getGpsBatteryStats() {
13002         GpsBatteryStats s = new GpsBatteryStats();
13003         final int which = STATS_SINCE_CHARGED;
13004         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
13005         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
13006         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
13007         long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
13008         for (int i=0; i<time.length; i++) {
13009             time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
13010         }
13011         s.setTimeInGpsSignalQualityLevel(time);
13012         return s;
13013     }
13014 
13015     @Override
getChargeLevelStepTracker()13016     public LevelStepTracker getChargeLevelStepTracker() {
13017         return mChargeStepTracker;
13018     }
13019 
13020     @Override
getDailyChargeLevelStepTracker()13021     public LevelStepTracker getDailyChargeLevelStepTracker() {
13022         return mDailyChargeStepTracker;
13023     }
13024 
13025     @Override
getDailyPackageChanges()13026     public ArrayList<PackageChange> getDailyPackageChanges() {
13027         return mDailyPackageChanges;
13028     }
13029 
getBatteryUptimeLocked()13030     protected long getBatteryUptimeLocked() {
13031         return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
13032     }
13033 
13034     @Override
getBatteryUptime(long curTime)13035     public long getBatteryUptime(long curTime) {
13036         return mOnBatteryTimeBase.getUptime(curTime);
13037     }
13038 
13039     @Override
getBatteryRealtime(long curTime)13040     public long getBatteryRealtime(long curTime) {
13041         return mOnBatteryTimeBase.getRealtime(curTime);
13042     }
13043 
13044     @Override
getDischargeStartLevel()13045     public int getDischargeStartLevel() {
13046         synchronized(this) {
13047             return getDischargeStartLevelLocked();
13048         }
13049     }
13050 
getDischargeStartLevelLocked()13051     public int getDischargeStartLevelLocked() {
13052             return mDischargeUnplugLevel;
13053     }
13054 
13055     @Override
getDischargeCurrentLevel()13056     public int getDischargeCurrentLevel() {
13057         synchronized(this) {
13058             return getDischargeCurrentLevelLocked();
13059         }
13060     }
13061 
getDischargeCurrentLevelLocked()13062     public int getDischargeCurrentLevelLocked() {
13063         return mDischargeCurrentLevel;
13064     }
13065 
13066     @Override
getLowDischargeAmountSinceCharge()13067     public int getLowDischargeAmountSinceCharge() {
13068         synchronized(this) {
13069             int val = mLowDischargeAmountSinceCharge;
13070             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
13071                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
13072             }
13073             return val;
13074         }
13075     }
13076 
13077     @Override
getHighDischargeAmountSinceCharge()13078     public int getHighDischargeAmountSinceCharge() {
13079         synchronized(this) {
13080             int val = mHighDischargeAmountSinceCharge;
13081             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
13082                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
13083             }
13084             return val;
13085         }
13086     }
13087 
13088     @Override
getDischargeAmount(int which)13089     public int getDischargeAmount(int which) {
13090         int dischargeAmount = which == STATS_SINCE_CHARGED
13091                 ? getHighDischargeAmountSinceCharge()
13092                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
13093         if (dischargeAmount < 0) {
13094             dischargeAmount = 0;
13095         }
13096         return dischargeAmount;
13097     }
13098 
13099     @Override
getDischargeAmountScreenOn()13100     public int getDischargeAmountScreenOn() {
13101         synchronized(this) {
13102             int val = mDischargeAmountScreenOn;
13103             if (mOnBattery && isScreenOn(mScreenState)
13104                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
13105                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
13106             }
13107             return val;
13108         }
13109     }
13110 
13111     @Override
getDischargeAmountScreenOnSinceCharge()13112     public int getDischargeAmountScreenOnSinceCharge() {
13113         synchronized(this) {
13114             int val = mDischargeAmountScreenOnSinceCharge;
13115             if (mOnBattery && isScreenOn(mScreenState)
13116                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
13117                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
13118             }
13119             return val;
13120         }
13121     }
13122 
13123     @Override
getDischargeAmountScreenOff()13124     public int getDischargeAmountScreenOff() {
13125         synchronized(this) {
13126             int val = mDischargeAmountScreenOff;
13127             if (mOnBattery && isScreenOff(mScreenState)
13128                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
13129                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
13130             }
13131             // For backward compatibility, doze discharge is counted into screen off.
13132             return val + getDischargeAmountScreenDoze();
13133         }
13134     }
13135 
13136     @Override
getDischargeAmountScreenOffSinceCharge()13137     public int getDischargeAmountScreenOffSinceCharge() {
13138         synchronized(this) {
13139             int val = mDischargeAmountScreenOffSinceCharge;
13140             if (mOnBattery && isScreenOff(mScreenState)
13141                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
13142                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
13143             }
13144             // For backward compatibility, doze discharge is counted into screen off.
13145             return val + getDischargeAmountScreenDozeSinceCharge();
13146         }
13147     }
13148 
13149     @Override
getDischargeAmountScreenDoze()13150     public int getDischargeAmountScreenDoze() {
13151         synchronized(this) {
13152             int val = mDischargeAmountScreenDoze;
13153             if (mOnBattery && isScreenDoze(mScreenState)
13154                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
13155                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
13156             }
13157             return val;
13158         }
13159     }
13160 
13161     @Override
getDischargeAmountScreenDozeSinceCharge()13162     public int getDischargeAmountScreenDozeSinceCharge() {
13163         synchronized(this) {
13164             int val = mDischargeAmountScreenDozeSinceCharge;
13165             if (mOnBattery && isScreenDoze(mScreenState)
13166                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
13167                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
13168             }
13169             return val;
13170         }
13171     }
13172 
13173     /**
13174      * Retrieve the statistics object for a particular uid, creating if needed.
13175      */
getUidStatsLocked(int uid)13176     public Uid getUidStatsLocked(int uid) {
13177         Uid u = mUidStats.get(uid);
13178         if (u == null) {
13179             u = new Uid(this, uid);
13180             mUidStats.put(uid, u);
13181         }
13182         return u;
13183     }
13184 
13185     /**
13186      * Retrieve the statistics object for a particular uid. Returns null if the object is not
13187      * available.
13188      */
getAvailableUidStatsLocked(int uid)13189     public Uid getAvailableUidStatsLocked(int uid) {
13190         Uid u = mUidStats.get(uid);
13191         return u;
13192     }
13193 
onCleanupUserLocked(int userId)13194     public void onCleanupUserLocked(int userId) {
13195         final int firstUidForUser = UserHandle.getUid(userId, 0);
13196         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
13197         mPendingRemovedUids.add(
13198                 new UidToRemove(firstUidForUser, lastUidForUser, mClocks.elapsedRealtime()));
13199     }
13200 
onUserRemovedLocked(int userId)13201     public void onUserRemovedLocked(int userId) {
13202         final int firstUidForUser = UserHandle.getUid(userId, 0);
13203         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
13204         mUidStats.put(firstUidForUser, null);
13205         mUidStats.put(lastUidForUser, null);
13206         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
13207         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
13208         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
13209     }
13210 
13211     /**
13212      * Remove the statistics object for a particular uid.
13213      */
removeUidStatsLocked(int uid)13214     public void removeUidStatsLocked(int uid) {
13215         mUidStats.remove(uid);
13216         mPendingRemovedUids.add(new UidToRemove(uid, mClocks.elapsedRealtime()));
13217     }
13218 
13219     /**
13220      * Retrieve the statistics object for a particular process, creating
13221      * if needed.
13222      */
getProcessStatsLocked(int uid, String name)13223     public Uid.Proc getProcessStatsLocked(int uid, String name) {
13224         uid = mapUid(uid);
13225         Uid u = getUidStatsLocked(uid);
13226         return u.getProcessStatsLocked(name);
13227     }
13228 
13229     /**
13230      * Retrieve the statistics object for a particular process, creating
13231      * if needed.
13232      */
getPackageStatsLocked(int uid, String pkg)13233     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
13234         uid = mapUid(uid);
13235         Uid u = getUidStatsLocked(uid);
13236         return u.getPackageStatsLocked(pkg);
13237     }
13238 
13239     /**
13240      * Retrieve the statistics object for a particular service, creating
13241      * if needed.
13242      */
getServiceStatsLocked(int uid, String pkg, String name)13243     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
13244         uid = mapUid(uid);
13245         Uid u = getUidStatsLocked(uid);
13246         return u.getServiceStatsLocked(pkg, name);
13247     }
13248 
shutdownLocked()13249     public void shutdownLocked() {
13250         recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
13251         writeSyncLocked();
13252         mShuttingDown = true;
13253     }
13254 
trackPerProcStateCpuTimes()13255     public boolean trackPerProcStateCpuTimes() {
13256         return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
13257     }
13258 
systemServicesReady(Context context)13259     public void systemServicesReady(Context context) {
13260         mConstants.startObserving(context.getContentResolver());
13261         registerUsbStateReceiver(context);
13262     }
13263 
13264     @VisibleForTesting
13265     public final class Constants extends ContentObserver {
13266         public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE
13267                 = "track_cpu_times_by_proc_state";
13268         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
13269                 = "track_cpu_active_cluster_time";
13270         public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
13271                 = "proc_state_cpu_times_read_delay_ms";
13272         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
13273                 = "kernel_uid_readers_throttle_time";
13274         public static final String KEY_UID_REMOVE_DELAY_MS
13275                 = "uid_remove_delay_ms";
13276         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
13277                 = "external_stats_collection_rate_limit_ms";
13278         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
13279                 = "battery_level_collection_delay_ms";
13280 
13281         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = true;
13282         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
13283         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
13284         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 10_000;
13285         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
13286         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
13287         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
13288 
13289         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
13290         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
13291         public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
13292         public long KERNEL_UID_READERS_THROTTLE_TIME = DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME;
13293         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
13294         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
13295                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
13296         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
13297                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
13298 
13299         private ContentResolver mResolver;
13300         private final KeyValueListParser mParser = new KeyValueListParser(',');
13301 
Constants(Handler handler)13302         public Constants(Handler handler) {
13303             super(handler);
13304         }
13305 
startObserving(ContentResolver resolver)13306         public void startObserving(ContentResolver resolver) {
13307             mResolver = resolver;
13308             mResolver.registerContentObserver(
13309                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
13310                     false /* notifyForDescendants */, this);
13311             updateConstants();
13312         }
13313 
13314         @Override
onChange(boolean selfChange, Uri uri)13315         public void onChange(boolean selfChange, Uri uri) {
13316             updateConstants();
13317         }
13318 
updateConstants()13319         private void updateConstants() {
13320             synchronized (BatteryStatsImpl.this) {
13321                 try {
13322                     mParser.setString(Settings.Global.getString(mResolver,
13323                             Settings.Global.BATTERY_STATS_CONSTANTS));
13324                 } catch (IllegalArgumentException e) {
13325                     // Failed to parse the settings string, log this and move on
13326                     // with defaults.
13327                     Slog.e(TAG, "Bad batterystats settings", e);
13328                 }
13329 
13330                 updateTrackCpuTimesByProcStateLocked(TRACK_CPU_TIMES_BY_PROC_STATE,
13331                         mParser.getBoolean(KEY_TRACK_CPU_TIMES_BY_PROC_STATE,
13332                                 DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE));
13333                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
13334                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
13335                 updateProcStateCpuTimesReadDelayMs(PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13336                         mParser.getLong(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13337                                 DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS));
13338                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
13339                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
13340                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
13341                 updateUidRemoveDelay(
13342                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
13343                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
13344                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
13345                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
13346                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
13347                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
13348                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
13349             }
13350         }
13351 
updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled)13352         private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
13353             TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
13354             if (isEnabled && !wasEnabled) {
13355                 mKernelSingleUidTimeReader.markDataAsStale(true);
13356                 mExternalSync.scheduleCpuSyncDueToSettingChange();
13357 
13358                 mNumSingleUidCpuTimeReads = 0;
13359                 mNumBatchedSingleUidCpuTimeReads = 0;
13360                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13361             }
13362         }
13363 
updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis)13364         private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
13365             PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
13366             if (oldDelayMillis != newDelayMillis) {
13367                 mNumSingleUidCpuTimeReads = 0;
13368                 mNumBatchedSingleUidCpuTimeReads = 0;
13369                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13370             }
13371         }
13372 
updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs)13373         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
13374             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
13375             if (oldTimeMs != newTimeMs) {
13376                 mKernelUidCpuTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
13377                 mKernelUidCpuFreqTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
13378                 mKernelUidCpuActiveTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
13379                 mKernelUidCpuClusterTimeReader
13380                         .setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
13381             }
13382         }
13383 
updateUidRemoveDelay(long newTimeMs)13384         private void updateUidRemoveDelay(long newTimeMs) {
13385             UID_REMOVE_DELAY_MS = newTimeMs;
13386             clearPendingRemovedUids();
13387         }
13388 
dumpLocked(PrintWriter pw)13389         public void dumpLocked(PrintWriter pw) {
13390             pw.print(KEY_TRACK_CPU_TIMES_BY_PROC_STATE); pw.print("=");
13391             pw.println(TRACK_CPU_TIMES_BY_PROC_STATE);
13392             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
13393             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
13394             pw.print(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS); pw.print("=");
13395             pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
13396             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
13397             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
13398             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
13399             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
13400             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
13401             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
13402         }
13403     }
13404 
getExternalStatsCollectionRateLimitMs()13405     public long getExternalStatsCollectionRateLimitMs() {
13406         synchronized (this) {
13407             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
13408         }
13409     }
13410 
13411     @GuardedBy("this")
dumpConstantsLocked(PrintWriter pw)13412     public void dumpConstantsLocked(PrintWriter pw) {
13413         mConstants.dumpLocked(pw);
13414     }
13415 
13416     @GuardedBy("this")
dumpCpuStatsLocked(PrintWriter pw)13417     public void dumpCpuStatsLocked(PrintWriter pw) {
13418         int size = mUidStats.size();
13419         pw.println("Per UID CPU user & system time in ms:");
13420         for (int i = 0; i < size; i++) {
13421             int u = mUidStats.keyAt(i);
13422             Uid uid = mUidStats.get(u);
13423             pw.print("  "); pw.print(u); pw.print(": ");
13424             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
13425             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
13426         }
13427         pw.println("Per UID CPU active time in ms:");
13428         for (int i = 0; i < size; i++) {
13429             int u = mUidStats.keyAt(i);
13430             Uid uid = mUidStats.get(u);
13431             if (uid.getCpuActiveTime() > 0) {
13432                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
13433             }
13434         }
13435         pw.println("Per UID CPU cluster time in ms:");
13436         for (int i = 0; i < size; i++) {
13437             int u = mUidStats.keyAt(i);
13438             long[] times = mUidStats.get(u).getCpuClusterTimes();
13439             if (times != null) {
13440                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
13441             }
13442         }
13443         pw.println("Per UID CPU frequency time in ms:");
13444         for (int i = 0; i < size; i++) {
13445             int u = mUidStats.keyAt(i);
13446             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
13447             if (times != null) {
13448                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
13449             }
13450         }
13451     }
13452 
13453     Parcel mPendingWrite = null;
13454     final ReentrantLock mWriteLock = new ReentrantLock();
13455 
writeAsyncLocked()13456     public void writeAsyncLocked() {
13457         writeLocked(false);
13458     }
13459 
writeSyncLocked()13460     public void writeSyncLocked() {
13461         writeLocked(true);
13462     }
13463 
writeLocked(boolean sync)13464     void writeLocked(boolean sync) {
13465         if (mFile == null) {
13466             Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
13467             return;
13468         }
13469 
13470         if (mShuttingDown) {
13471             return;
13472         }
13473 
13474         Parcel out = Parcel.obtain();
13475         writeSummaryToParcel(out, true);
13476         mLastWriteTime = mClocks.elapsedRealtime();
13477 
13478         if (mPendingWrite != null) {
13479             mPendingWrite.recycle();
13480         }
13481         mPendingWrite = out;
13482 
13483         if (sync) {
13484             commitPendingDataToDisk();
13485         } else {
13486             BackgroundThread.getHandler().post(new Runnable() {
13487                 @Override public void run() {
13488                     commitPendingDataToDisk();
13489                 }
13490             });
13491         }
13492     }
13493 
commitPendingDataToDisk()13494     public void commitPendingDataToDisk() {
13495         final Parcel next;
13496         synchronized (this) {
13497             next = mPendingWrite;
13498             mPendingWrite = null;
13499             if (next == null) {
13500                 return;
13501             }
13502         }
13503 
13504         mWriteLock.lock();
13505         try {
13506             final long startTime = SystemClock.uptimeMillis();
13507             FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
13508             stream.write(next.marshall());
13509             stream.flush();
13510             FileUtils.sync(stream);
13511             stream.close();
13512             mFile.commit();
13513             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
13514                     "batterystats", SystemClock.uptimeMillis() - startTime);
13515         } catch (IOException e) {
13516             Slog.w("BatteryStats", "Error writing battery statistics", e);
13517             mFile.rollback();
13518         } finally {
13519             next.recycle();
13520             mWriteLock.unlock();
13521         }
13522     }
13523 
readLocked()13524     public void readLocked() {
13525         if (mDailyFile != null) {
13526             readDailyStatsLocked();
13527         }
13528 
13529         if (mFile == null) {
13530             Slog.w("BatteryStats", "readLocked: no file associated with this instance");
13531             return;
13532         }
13533 
13534         mUidStats.clear();
13535 
13536         try {
13537             File file = mFile.chooseForRead();
13538             if (!file.exists()) {
13539                 return;
13540             }
13541             FileInputStream stream = new FileInputStream(file);
13542 
13543             byte[] raw = BatteryStatsHelper.readFully(stream);
13544             Parcel in = Parcel.obtain();
13545             in.unmarshall(raw, 0, raw.length);
13546             in.setDataPosition(0);
13547             stream.close();
13548 
13549             readSummaryFromParcel(in);
13550         } catch(Exception e) {
13551             Slog.e("BatteryStats", "Error reading battery statistics", e);
13552             resetAllStatsLocked();
13553         }
13554 
13555         mEndPlatformVersion = Build.ID;
13556 
13557         if (mHistoryBuffer.dataPosition() > 0) {
13558             mRecordingHistory = true;
13559             final long elapsedRealtime = mClocks.elapsedRealtime();
13560             final long uptime = mClocks.uptimeMillis();
13561             if (USE_OLD_HISTORY) {
13562                 addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
13563             }
13564             addHistoryBufferLocked(elapsedRealtime, HistoryItem.CMD_START, mHistoryCur);
13565             startRecordingHistory(elapsedRealtime, uptime, false);
13566         }
13567 
13568         recordDailyStatsIfNeededLocked(false);
13569     }
13570 
describeContents()13571     public int describeContents() {
13572         return 0;
13573     }
13574 
readHistory(Parcel in, boolean andOldHistory)13575     void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
13576         final long historyBaseTime = in.readLong();
13577 
13578         mHistoryBuffer.setDataSize(0);
13579         mHistoryBuffer.setDataPosition(0);
13580         mHistoryTagPool.clear();
13581         mNextHistoryTagIdx = 0;
13582         mNumHistoryTagChars = 0;
13583 
13584         int numTags = in.readInt();
13585         for (int i=0; i<numTags; i++) {
13586             int idx = in.readInt();
13587             String str = in.readString();
13588             if (str == null) {
13589                 throw new ParcelFormatException("null history tag string");
13590             }
13591             int uid = in.readInt();
13592             HistoryTag tag = new HistoryTag();
13593             tag.string = str;
13594             tag.uid = uid;
13595             tag.poolIdx = idx;
13596             mHistoryTagPool.put(tag, idx);
13597             if (idx >= mNextHistoryTagIdx) {
13598                 mNextHistoryTagIdx = idx+1;
13599             }
13600             mNumHistoryTagChars += tag.string.length() + 1;
13601         }
13602 
13603         int bufSize = in.readInt();
13604         int curPos = in.dataPosition();
13605         if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
13606             throw new ParcelFormatException("File corrupt: history data buffer too large " +
13607                     bufSize);
13608         } else if ((bufSize&~3) != bufSize) {
13609             throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
13610                     bufSize);
13611         } else {
13612             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
13613                     + " bytes at " + curPos);
13614             mHistoryBuffer.appendFrom(in, curPos, bufSize);
13615             in.setDataPosition(curPos + bufSize);
13616         }
13617 
13618         if (andOldHistory) {
13619             readOldHistory(in);
13620         }
13621 
13622         if (DEBUG_HISTORY) {
13623             StringBuilder sb = new StringBuilder(128);
13624             sb.append("****************** OLD mHistoryBaseTime: ");
13625             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13626             Slog.i(TAG, sb.toString());
13627         }
13628         mHistoryBaseTime = historyBaseTime;
13629         if (DEBUG_HISTORY) {
13630             StringBuilder sb = new StringBuilder(128);
13631             sb.append("****************** NEW mHistoryBaseTime: ");
13632             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13633             Slog.i(TAG, sb.toString());
13634         }
13635 
13636         // We are just arbitrarily going to insert 1 minute from the sample of
13637         // the last run until samples in this run.
13638         if (mHistoryBaseTime > 0) {
13639             long oldnow = mClocks.elapsedRealtime();
13640             mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
13641             if (DEBUG_HISTORY) {
13642                 StringBuilder sb = new StringBuilder(128);
13643                 sb.append("****************** ADJUSTED mHistoryBaseTime: ");
13644                 TimeUtils.formatDuration(mHistoryBaseTime, sb);
13645                 Slog.i(TAG, sb.toString());
13646             }
13647         }
13648     }
13649 
readOldHistory(Parcel in)13650     void readOldHistory(Parcel in) {
13651         if (!USE_OLD_HISTORY) {
13652             return;
13653         }
13654         mHistory = mHistoryEnd = mHistoryCache = null;
13655         long time;
13656         while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
13657             HistoryItem rec = new HistoryItem(time, in);
13658             addHistoryRecordLocked(rec);
13659         }
13660     }
13661 
writeHistory(Parcel out, boolean inclData, boolean andOldHistory)13662     void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
13663         if (DEBUG_HISTORY) {
13664             StringBuilder sb = new StringBuilder(128);
13665             sb.append("****************** WRITING mHistoryBaseTime: ");
13666             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13667             sb.append(" mLastHistoryElapsedRealtime: ");
13668             TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
13669             Slog.i(TAG, sb.toString());
13670         }
13671         out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
13672         if (!inclData) {
13673             out.writeInt(0);
13674             out.writeInt(0);
13675             return;
13676         }
13677         out.writeInt(mHistoryTagPool.size());
13678         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
13679             HistoryTag tag = ent.getKey();
13680             out.writeInt(ent.getValue());
13681             out.writeString(tag.string);
13682             out.writeInt(tag.uid);
13683         }
13684         out.writeInt(mHistoryBuffer.dataSize());
13685         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
13686                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
13687         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
13688 
13689         if (andOldHistory) {
13690             writeOldHistory(out);
13691         }
13692     }
13693 
writeOldHistory(Parcel out)13694     void writeOldHistory(Parcel out) {
13695         if (!USE_OLD_HISTORY) {
13696             return;
13697         }
13698         HistoryItem rec = mHistory;
13699         while (rec != null) {
13700             if (rec.time >= 0) rec.writeToParcel(out, 0);
13701             rec = rec.next;
13702         }
13703         out.writeLong(-1);
13704     }
13705 
readSummaryFromParcel(Parcel in)13706     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
13707         final int version = in.readInt();
13708         if (version != VERSION) {
13709             Slog.w("BatteryStats", "readFromParcel: version got " + version
13710                 + ", expected " + VERSION + "; erasing old stats");
13711             return;
13712         }
13713 
13714         readHistory(in, true);
13715 
13716         mStartCount = in.readInt();
13717         mUptime = in.readLong();
13718         mRealtime = in.readLong();
13719         mStartClockTime = in.readLong();
13720         mStartPlatformVersion = in.readString();
13721         mEndPlatformVersion = in.readString();
13722         mOnBatteryTimeBase.readSummaryFromParcel(in);
13723         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
13724         mDischargeUnplugLevel = in.readInt();
13725         mDischargePlugLevel = in.readInt();
13726         mDischargeCurrentLevel = in.readInt();
13727         mCurrentBatteryLevel = in.readInt();
13728         mEstimatedBatteryCapacity = in.readInt();
13729         mMinLearnedBatteryCapacity = in.readInt();
13730         mMaxLearnedBatteryCapacity = in.readInt();
13731         mLowDischargeAmountSinceCharge = in.readInt();
13732         mHighDischargeAmountSinceCharge = in.readInt();
13733         mDischargeAmountScreenOnSinceCharge = in.readInt();
13734         mDischargeAmountScreenOffSinceCharge = in.readInt();
13735         mDischargeAmountScreenDozeSinceCharge = in.readInt();
13736         mDischargeStepTracker.readFromParcel(in);
13737         mChargeStepTracker.readFromParcel(in);
13738         mDailyDischargeStepTracker.readFromParcel(in);
13739         mDailyChargeStepTracker.readFromParcel(in);
13740         mDischargeCounter.readSummaryFromParcelLocked(in);
13741         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
13742         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
13743         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
13744         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
13745         int NPKG = in.readInt();
13746         if (NPKG > 0) {
13747             mDailyPackageChanges = new ArrayList<>(NPKG);
13748             while (NPKG > 0) {
13749                 NPKG--;
13750                 PackageChange pc = new PackageChange();
13751                 pc.mPackageName = in.readString();
13752                 pc.mUpdate = in.readInt() != 0;
13753                 pc.mVersionCode = in.readLong();
13754                 mDailyPackageChanges.add(pc);
13755             }
13756         } else {
13757             mDailyPackageChanges = null;
13758         }
13759         mDailyStartTime = in.readLong();
13760         mNextMinDailyDeadline = in.readLong();
13761         mNextMaxDailyDeadline = in.readLong();
13762 
13763         mStartCount++;
13764 
13765         mScreenState = Display.STATE_UNKNOWN;
13766         mScreenOnTimer.readSummaryFromParcelLocked(in);
13767         mScreenDozeTimer.readSummaryFromParcelLocked(in);
13768         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
13769             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
13770         }
13771         mInteractive = false;
13772         mInteractiveTimer.readSummaryFromParcelLocked(in);
13773         mPhoneOn = false;
13774         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
13775         mLongestLightIdleTime = in.readLong();
13776         mLongestFullIdleTime = in.readLong();
13777         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
13778         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
13779         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
13780         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
13781         mPhoneOnTimer.readSummaryFromParcelLocked(in);
13782         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
13783             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13784         }
13785         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
13786         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
13787             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
13788         }
13789         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13790             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13791             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13792         }
13793         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13794         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
13795         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
13796         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
13797         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
13798         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
13799         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
13800         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13801         mWifiOn = false;
13802         mWifiOnTimer.readSummaryFromParcelLocked(in);
13803         mGlobalWifiRunning = false;
13804         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
13805         for (int i=0; i<NUM_WIFI_STATES; i++) {
13806             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
13807         }
13808         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
13809             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
13810         }
13811         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
13812             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13813         }
13814         mWifiActiveTimer.readSummaryFromParcelLocked(in);
13815         mWifiActivity.readSummaryFromParcel(in);
13816         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
13817             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
13818         }
13819         mBluetoothActivity.readSummaryFromParcel(in);
13820         mModemActivity.readSummaryFromParcel(in);
13821         mHasWifiReporting = in.readInt() != 0;
13822         mHasBluetoothReporting = in.readInt() != 0;
13823         mHasModemReporting = in.readInt() != 0;
13824 
13825         mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
13826         mFlashlightOnNesting = 0;
13827         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
13828         mCameraOnNesting = 0;
13829         mCameraOnTimer.readSummaryFromParcelLocked(in);
13830         mBluetoothScanNesting = 0;
13831         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
13832         mIsCellularTxPowerHigh = false;
13833 
13834         int NRPMS = in.readInt();
13835         if (NRPMS > 10000) {
13836             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
13837         }
13838         for (int irpm = 0; irpm < NRPMS; irpm++) {
13839             if (in.readInt() != 0) {
13840                 String rpmName = in.readString();
13841                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13842             }
13843         }
13844         int NSORPMS = in.readInt();
13845         if (NSORPMS > 10000) {
13846             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
13847         }
13848         for (int irpm = 0; irpm < NSORPMS; irpm++) {
13849             if (in.readInt() != 0) {
13850                 String rpmName = in.readString();
13851                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13852             }
13853         }
13854 
13855         int NKW = in.readInt();
13856         if (NKW > 10000) {
13857             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
13858         }
13859         for (int ikw = 0; ikw < NKW; ikw++) {
13860             if (in.readInt() != 0) {
13861                 String kwltName = in.readString();
13862                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
13863             }
13864         }
13865 
13866         int NWR = in.readInt();
13867         if (NWR > 10000) {
13868             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
13869         }
13870         for (int iwr = 0; iwr < NWR; iwr++) {
13871             if (in.readInt() != 0) {
13872                 String reasonName = in.readString();
13873                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
13874             }
13875         }
13876 
13877         int NMS = in.readInt();
13878         for (int ims = 0; ims < NMS; ims++) {
13879             if (in.readInt() != 0) {
13880                 long kmstName = in.readLong();
13881                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
13882             }
13883         }
13884 
13885         final int NU = in.readInt();
13886         if (NU > 10000) {
13887             throw new ParcelFormatException("File corrupt: too many uids " + NU);
13888         }
13889         for (int iu = 0; iu < NU; iu++) {
13890             int uid = in.readInt();
13891             Uid u = new Uid(this, uid);
13892             mUidStats.put(uid, u);
13893 
13894             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
13895             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
13896 
13897             u.mWifiRunning = false;
13898             if (in.readInt() != 0) {
13899                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
13900             }
13901             u.mFullWifiLockOut = false;
13902             if (in.readInt() != 0) {
13903                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
13904             }
13905             u.mWifiScanStarted = false;
13906             if (in.readInt() != 0) {
13907                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
13908             }
13909             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
13910             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
13911                 if (in.readInt() != 0) {
13912                     u.makeWifiBatchedScanBin(i, null);
13913                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
13914                 }
13915             }
13916             u.mWifiMulticastEnabled = false;
13917             if (in.readInt() != 0) {
13918                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
13919             }
13920             if (in.readInt() != 0) {
13921                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13922             }
13923             if (in.readInt() != 0) {
13924                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13925             }
13926             if (in.readInt() != 0) {
13927                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13928             }
13929             if (in.readInt() != 0) {
13930                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13931             }
13932             if (in.readInt() != 0) {
13933                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
13934             }
13935             if (in.readInt() != 0) {
13936                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
13937             }
13938             if (in.readInt() != 0) {
13939                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
13940             }
13941             if (in.readInt() != 0) {
13942                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
13943             }
13944             if (in.readInt() != 0) {
13945                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
13946             }
13947             if (in.readInt() != 0) {
13948                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
13949             }
13950             if (in.readInt() != 0) {
13951                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
13952             }
13953             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
13954             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
13955                 if (in.readInt() != 0) {
13956                     u.makeProcessState(i, null);
13957                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
13958                 }
13959             }
13960             if (in.readInt() != 0) {
13961                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
13962             }
13963 
13964             if (in.readInt() != 0) {
13965                 if (u.mUserActivityCounters == null) {
13966                     u.initUserActivityLocked();
13967                 }
13968                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
13969                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
13970                 }
13971             }
13972 
13973             if (in.readInt() != 0) {
13974                 if (u.mNetworkByteActivityCounters == null) {
13975                     u.initNetworkActivityLocked();
13976                 }
13977                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13978                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13979                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13980                 }
13981                 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
13982                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
13983             }
13984 
13985             u.mUserCpuTime.readSummaryFromParcelLocked(in);
13986             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
13987 
13988             if (in.readInt() != 0) {
13989                 final int numClusters = in.readInt();
13990                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
13991                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
13992                 }
13993 
13994                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13995                 for (int cluster = 0; cluster < numClusters; cluster++) {
13996                     if (in.readInt() != 0) {
13997                         final int NSB = in.readInt();
13998                         if (mPowerProfile != null &&
13999                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
14000                             throw new ParcelFormatException("File corrupt: too many speed bins " +
14001                                     NSB);
14002                         }
14003 
14004                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
14005                         for (int speed = 0; speed < NSB; speed++) {
14006                             if (in.readInt() != 0) {
14007                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
14008                                         mOnBatteryTimeBase);
14009                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
14010                             }
14011                         }
14012                     } else {
14013                         u.mCpuClusterSpeedTimesUs[cluster] = null;
14014                     }
14015                 }
14016             } else {
14017                 u.mCpuClusterSpeedTimesUs = null;
14018             }
14019 
14020             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
14021                     in, mOnBatteryTimeBase);
14022             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
14023                     in, mOnBatteryScreenOffTimeBase);
14024 
14025             u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
14026             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
14027 
14028             int length = in.readInt();
14029             if (length == Uid.NUM_PROCESS_STATE) {
14030                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
14031                 for (int procState = 0; procState < length; ++procState) {
14032                     u.mProcStateTimeMs[procState]
14033                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
14034                                     in, mOnBatteryTimeBase);
14035                 }
14036             } else {
14037                 u.mProcStateTimeMs = null;
14038             }
14039             length = in.readInt();
14040             if (length == Uid.NUM_PROCESS_STATE) {
14041                 u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
14042                 for (int procState = 0; procState < length; ++procState) {
14043                     u.mProcStateScreenOffTimeMs[procState]
14044                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
14045                                     in, mOnBatteryScreenOffTimeBase);
14046                 }
14047             } else {
14048                 u.mProcStateScreenOffTimeMs = null;
14049             }
14050 
14051             if (in.readInt() != 0) {
14052                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
14053                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
14054             } else {
14055                 u.mMobileRadioApWakeupCount = null;
14056             }
14057 
14058             if (in.readInt() != 0) {
14059                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
14060                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
14061             } else {
14062                 u.mWifiRadioApWakeupCount = null;
14063             }
14064 
14065             int NW = in.readInt();
14066             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
14067                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
14068             }
14069             for (int iw = 0; iw < NW; iw++) {
14070                 String wlName = in.readString();
14071                 u.readWakeSummaryFromParcelLocked(wlName, in);
14072             }
14073 
14074             int NS = in.readInt();
14075             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
14076                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
14077             }
14078             for (int is = 0; is < NS; is++) {
14079                 String name = in.readString();
14080                 u.readSyncSummaryFromParcelLocked(name, in);
14081             }
14082 
14083             int NJ = in.readInt();
14084             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
14085                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
14086             }
14087             for (int ij = 0; ij < NJ; ij++) {
14088                 String name = in.readString();
14089                 u.readJobSummaryFromParcelLocked(name, in);
14090             }
14091 
14092             u.readJobCompletionsFromParcelLocked(in);
14093 
14094             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
14095             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
14096             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
14097             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
14098                 if (in.readInt() != 0) {
14099                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
14100                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
14101                 }
14102             }
14103 
14104             int NP = in.readInt();
14105             if (NP > 1000) {
14106                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
14107             }
14108             for (int is = 0; is < NP; is++) {
14109                 int seNumber = in.readInt();
14110                 if (in.readInt() != 0) {
14111                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
14112                 }
14113             }
14114 
14115             NP = in.readInt();
14116             if (NP > 1000) {
14117                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
14118             }
14119             for (int ip = 0; ip < NP; ip++) {
14120                 String procName = in.readString();
14121                 Uid.Proc p = u.getProcessStatsLocked(procName);
14122                 p.mUserTime = p.mLoadedUserTime = in.readLong();
14123                 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
14124                 p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
14125                 p.mStarts = p.mLoadedStarts = in.readInt();
14126                 p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
14127                 p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
14128                 p.readExcessivePowerFromParcelLocked(in);
14129             }
14130 
14131             NP = in.readInt();
14132             if (NP > 10000) {
14133                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
14134             }
14135             for (int ip = 0; ip < NP; ip++) {
14136                 String pkgName = in.readString();
14137                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
14138                 final int NWA = in.readInt();
14139                 if (NWA > 1000) {
14140                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
14141                 }
14142                 p.mWakeupAlarms.clear();
14143                 for (int iwa=0; iwa<NWA; iwa++) {
14144                     String tag = in.readString();
14145                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
14146                     c.readSummaryFromParcelLocked(in);
14147                     p.mWakeupAlarms.put(tag, c);
14148                 }
14149                 NS = in.readInt();
14150                 if (NS > 1000) {
14151                     throw new ParcelFormatException("File corrupt: too many services " + NS);
14152                 }
14153                 for (int is = 0; is < NS; is++) {
14154                     String servName = in.readString();
14155                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
14156                     s.mStartTime = s.mLoadedStartTime = in.readLong();
14157                     s.mStarts = s.mLoadedStarts = in.readInt();
14158                     s.mLaunches = s.mLoadedLaunches = in.readInt();
14159                 }
14160             }
14161         }
14162     }
14163 
14164     /**
14165      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
14166      * disk.  This format does not allow a lossless round-trip.
14167      *
14168      * @param out the Parcel to be written to.
14169      */
writeSummaryToParcel(Parcel out, boolean inclHistory)14170     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
14171         pullPendingStateUpdatesLocked();
14172 
14173         // Pull the clock time.  This may update the time and make a new history entry
14174         // if we had originally pulled a time before the RTC was set.
14175         long startClockTime = getStartClockTime();
14176 
14177         final long NOW_SYS = mClocks.uptimeMillis() * 1000;
14178         final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
14179 
14180         out.writeInt(VERSION);
14181 
14182         writeHistory(out, inclHistory, true);
14183 
14184         out.writeInt(mStartCount);
14185         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
14186         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
14187         out.writeLong(startClockTime);
14188         out.writeString(mStartPlatformVersion);
14189         out.writeString(mEndPlatformVersion);
14190         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14191         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14192         out.writeInt(mDischargeUnplugLevel);
14193         out.writeInt(mDischargePlugLevel);
14194         out.writeInt(mDischargeCurrentLevel);
14195         out.writeInt(mCurrentBatteryLevel);
14196         out.writeInt(mEstimatedBatteryCapacity);
14197         out.writeInt(mMinLearnedBatteryCapacity);
14198         out.writeInt(mMaxLearnedBatteryCapacity);
14199         out.writeInt(getLowDischargeAmountSinceCharge());
14200         out.writeInt(getHighDischargeAmountSinceCharge());
14201         out.writeInt(getDischargeAmountScreenOnSinceCharge());
14202         out.writeInt(getDischargeAmountScreenOffSinceCharge());
14203         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
14204         mDischargeStepTracker.writeToParcel(out);
14205         mChargeStepTracker.writeToParcel(out);
14206         mDailyDischargeStepTracker.writeToParcel(out);
14207         mDailyChargeStepTracker.writeToParcel(out);
14208         mDischargeCounter.writeSummaryFromParcelLocked(out);
14209         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
14210         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
14211         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
14212         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
14213         if (mDailyPackageChanges != null) {
14214             final int NPKG = mDailyPackageChanges.size();
14215             out.writeInt(NPKG);
14216             for (int i=0; i<NPKG; i++) {
14217                 PackageChange pc = mDailyPackageChanges.get(i);
14218                 out.writeString(pc.mPackageName);
14219                 out.writeInt(pc.mUpdate ? 1 : 0);
14220                 out.writeLong(pc.mVersionCode);
14221             }
14222         } else {
14223             out.writeInt(0);
14224         }
14225         out.writeLong(mDailyStartTime);
14226         out.writeLong(mNextMinDailyDeadline);
14227         out.writeLong(mNextMaxDailyDeadline);
14228 
14229         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14230         mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14231         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14232             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14233         }
14234         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14235         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14236         out.writeLong(mLongestLightIdleTime);
14237         out.writeLong(mLongestFullIdleTime);
14238         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14239         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14240         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14241         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14242         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14243         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14244             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14245         }
14246         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14247         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14248             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14249         }
14250         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14251             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14252             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14253         }
14254         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14255         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14256         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
14257         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
14258         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
14259         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14260         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14261         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14262         for (int i=0; i<NUM_WIFI_STATES; i++) {
14263             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14264         }
14265         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14266             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14267         }
14268         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14269             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14270         }
14271         mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14272         mWifiActivity.writeSummaryToParcel(out);
14273         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14274             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14275         }
14276         mBluetoothActivity.writeSummaryToParcel(out);
14277         mModemActivity.writeSummaryToParcel(out);
14278         out.writeInt(mHasWifiReporting ? 1 : 0);
14279         out.writeInt(mHasBluetoothReporting ? 1 : 0);
14280         out.writeInt(mHasModemReporting ? 1 : 0);
14281 
14282         out.writeInt(mNumConnectivityChange);
14283         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14284         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14285         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14286 
14287         out.writeInt(mRpmStats.size());
14288         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
14289             Timer rpmt = ent.getValue();
14290             if (rpmt != null) {
14291                 out.writeInt(1);
14292                 out.writeString(ent.getKey());
14293                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14294             } else {
14295                 out.writeInt(0);
14296             }
14297         }
14298         out.writeInt(mScreenOffRpmStats.size());
14299         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
14300             Timer rpmt = ent.getValue();
14301             if (rpmt != null) {
14302                 out.writeInt(1);
14303                 out.writeString(ent.getKey());
14304                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14305             } else {
14306                 out.writeInt(0);
14307             }
14308         }
14309 
14310         out.writeInt(mKernelWakelockStats.size());
14311         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14312             Timer kwlt = ent.getValue();
14313             if (kwlt != null) {
14314                 out.writeInt(1);
14315                 out.writeString(ent.getKey());
14316                 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14317             } else {
14318                 out.writeInt(0);
14319             }
14320         }
14321 
14322         out.writeInt(mWakeupReasonStats.size());
14323         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
14324             SamplingTimer timer = ent.getValue();
14325             if (timer != null) {
14326                 out.writeInt(1);
14327                 out.writeString(ent.getKey());
14328                 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14329             } else {
14330                 out.writeInt(0);
14331             }
14332         }
14333 
14334         out.writeInt(mKernelMemoryStats.size());
14335         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
14336             Timer kmt = mKernelMemoryStats.valueAt(i);
14337             if (kmt != null) {
14338                 out.writeInt(1);
14339                 out.writeLong(mKernelMemoryStats.keyAt(i));
14340                 kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14341             } else {
14342                 out.writeInt(0);
14343             }
14344         }
14345 
14346         final int NU = mUidStats.size();
14347         out.writeInt(NU);
14348         for (int iu = 0; iu < NU; iu++) {
14349             out.writeInt(mUidStats.keyAt(iu));
14350             Uid u = mUidStats.valueAt(iu);
14351 
14352             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14353             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14354 
14355             if (u.mWifiRunningTimer != null) {
14356                 out.writeInt(1);
14357                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14358             } else {
14359                 out.writeInt(0);
14360             }
14361             if (u.mFullWifiLockTimer != null) {
14362                 out.writeInt(1);
14363                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14364             } else {
14365                 out.writeInt(0);
14366             }
14367             if (u.mWifiScanTimer != null) {
14368                 out.writeInt(1);
14369                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14370             } else {
14371                 out.writeInt(0);
14372             }
14373             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
14374                 if (u.mWifiBatchedScanTimer[i] != null) {
14375                     out.writeInt(1);
14376                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14377                 } else {
14378                     out.writeInt(0);
14379                 }
14380             }
14381             if (u.mWifiMulticastTimer != null) {
14382                 out.writeInt(1);
14383                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14384             } else {
14385                 out.writeInt(0);
14386             }
14387             if (u.mAudioTurnedOnTimer != null) {
14388                 out.writeInt(1);
14389                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14390             } else {
14391                 out.writeInt(0);
14392             }
14393             if (u.mVideoTurnedOnTimer != null) {
14394                 out.writeInt(1);
14395                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14396             } else {
14397                 out.writeInt(0);
14398             }
14399             if (u.mFlashlightTurnedOnTimer != null) {
14400                 out.writeInt(1);
14401                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14402             } else {
14403                 out.writeInt(0);
14404             }
14405             if (u.mCameraTurnedOnTimer != null) {
14406                 out.writeInt(1);
14407                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14408             } else {
14409                 out.writeInt(0);
14410             }
14411             if (u.mForegroundActivityTimer != null) {
14412                 out.writeInt(1);
14413                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14414             } else {
14415                 out.writeInt(0);
14416             }
14417             if (u.mForegroundServiceTimer != null) {
14418                 out.writeInt(1);
14419                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14420             } else {
14421                 out.writeInt(0);
14422             }
14423             if (u.mAggregatedPartialWakelockTimer != null) {
14424                 out.writeInt(1);
14425                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14426             } else {
14427                 out.writeInt(0);
14428             }
14429             if (u.mBluetoothScanTimer != null) {
14430                 out.writeInt(1);
14431                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14432             } else {
14433                 out.writeInt(0);
14434             }
14435             if (u.mBluetoothUnoptimizedScanTimer != null) {
14436                 out.writeInt(1);
14437                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14438             } else {
14439                 out.writeInt(0);
14440             }
14441             if (u.mBluetoothScanResultCounter != null) {
14442                 out.writeInt(1);
14443                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
14444             } else {
14445                 out.writeInt(0);
14446             }
14447             if (u.mBluetoothScanResultBgCounter != null) {
14448                 out.writeInt(1);
14449                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
14450             } else {
14451                 out.writeInt(0);
14452             }
14453             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
14454                 if (u.mProcessStateTimer[i] != null) {
14455                     out.writeInt(1);
14456                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14457                 } else {
14458                     out.writeInt(0);
14459                 }
14460             }
14461             if (u.mVibratorOnTimer != null) {
14462                 out.writeInt(1);
14463                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14464             } else {
14465                 out.writeInt(0);
14466             }
14467 
14468             if (u.mUserActivityCounters == null) {
14469                 out.writeInt(0);
14470             } else {
14471                 out.writeInt(1);
14472                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
14473                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
14474                 }
14475             }
14476 
14477             if (u.mNetworkByteActivityCounters == null) {
14478                 out.writeInt(0);
14479             } else {
14480                 out.writeInt(1);
14481                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14482                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14483                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14484                 }
14485                 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
14486                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
14487             }
14488 
14489             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
14490             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
14491 
14492             if (u.mCpuClusterSpeedTimesUs != null) {
14493                 out.writeInt(1);
14494                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
14495                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
14496                     if (cpuSpeeds != null) {
14497                         out.writeInt(1);
14498                         out.writeInt(cpuSpeeds.length);
14499                         for (LongSamplingCounter c : cpuSpeeds) {
14500                             if (c != null) {
14501                                 out.writeInt(1);
14502                                 c.writeSummaryFromParcelLocked(out);
14503                             } else {
14504                                 out.writeInt(0);
14505                             }
14506                         }
14507                     } else {
14508                         out.writeInt(0);
14509                     }
14510                 }
14511             } else {
14512                 out.writeInt(0);
14513             }
14514 
14515             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
14516             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
14517 
14518             u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
14519             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
14520 
14521             if (u.mProcStateTimeMs != null) {
14522                 out.writeInt(u.mProcStateTimeMs.length);
14523                 for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
14524                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14525                 }
14526             } else {
14527                 out.writeInt(0);
14528             }
14529             if (u.mProcStateScreenOffTimeMs != null) {
14530                 out.writeInt(u.mProcStateScreenOffTimeMs.length);
14531                 for (LongSamplingCounterArray counters : u.mProcStateScreenOffTimeMs) {
14532                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14533                 }
14534             } else {
14535                 out.writeInt(0);
14536             }
14537 
14538             if (u.mMobileRadioApWakeupCount != null) {
14539                 out.writeInt(1);
14540                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14541             } else {
14542                 out.writeInt(0);
14543             }
14544 
14545             if (u.mWifiRadioApWakeupCount != null) {
14546                 out.writeInt(1);
14547                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14548             } else {
14549                 out.writeInt(0);
14550             }
14551 
14552             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
14553             int NW = wakeStats.size();
14554             out.writeInt(NW);
14555             for (int iw=0; iw<NW; iw++) {
14556                 out.writeString(wakeStats.keyAt(iw));
14557                 Uid.Wakelock wl = wakeStats.valueAt(iw);
14558                 if (wl.mTimerFull != null) {
14559                     out.writeInt(1);
14560                     wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14561                 } else {
14562                     out.writeInt(0);
14563                 }
14564                 if (wl.mTimerPartial != null) {
14565                     out.writeInt(1);
14566                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14567                 } else {
14568                     out.writeInt(0);
14569                 }
14570                 if (wl.mTimerWindow != null) {
14571                     out.writeInt(1);
14572                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14573                 } else {
14574                     out.writeInt(0);
14575                 }
14576                 if (wl.mTimerDraw != null) {
14577                     out.writeInt(1);
14578                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14579                 } else {
14580                     out.writeInt(0);
14581                 }
14582             }
14583 
14584             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
14585             int NS = syncStats.size();
14586             out.writeInt(NS);
14587             for (int is=0; is<NS; is++) {
14588                 out.writeString(syncStats.keyAt(is));
14589                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14590             }
14591 
14592             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
14593             int NJ = jobStats.size();
14594             out.writeInt(NJ);
14595             for (int ij=0; ij<NJ; ij++) {
14596                 out.writeString(jobStats.keyAt(ij));
14597                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14598             }
14599 
14600             u.writeJobCompletionsToParcelLocked(out);
14601 
14602             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
14603             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
14604             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
14605             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
14606                 if (u.mJobsFreshnessBuckets[i] != null) {
14607                     out.writeInt(1);
14608                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
14609                 } else {
14610                     out.writeInt(0);
14611                 }
14612             }
14613 
14614             int NSE = u.mSensorStats.size();
14615             out.writeInt(NSE);
14616             for (int ise=0; ise<NSE; ise++) {
14617                 out.writeInt(u.mSensorStats.keyAt(ise));
14618                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
14619                 if (se.mTimer != null) {
14620                     out.writeInt(1);
14621                     se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14622                 } else {
14623                     out.writeInt(0);
14624                 }
14625             }
14626 
14627             int NP = u.mProcessStats.size();
14628             out.writeInt(NP);
14629             for (int ip=0; ip<NP; ip++) {
14630                 out.writeString(u.mProcessStats.keyAt(ip));
14631                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
14632                 out.writeLong(ps.mUserTime);
14633                 out.writeLong(ps.mSystemTime);
14634                 out.writeLong(ps.mForegroundTime);
14635                 out.writeInt(ps.mStarts);
14636                 out.writeInt(ps.mNumCrashes);
14637                 out.writeInt(ps.mNumAnrs);
14638                 ps.writeExcessivePowerToParcelLocked(out);
14639             }
14640 
14641             NP = u.mPackageStats.size();
14642             out.writeInt(NP);
14643             if (NP > 0) {
14644                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
14645                     : u.mPackageStats.entrySet()) {
14646                     out.writeString(ent.getKey());
14647                     Uid.Pkg ps = ent.getValue();
14648                     final int NWA = ps.mWakeupAlarms.size();
14649                     out.writeInt(NWA);
14650                     for (int iwa=0; iwa<NWA; iwa++) {
14651                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
14652                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
14653                     }
14654                     NS = ps.mServiceStats.size();
14655                     out.writeInt(NS);
14656                     for (int is=0; is<NS; is++) {
14657                         out.writeString(ps.mServiceStats.keyAt(is));
14658                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
14659                         long time = ss.getStartTimeToNowLocked(
14660                                 mOnBatteryTimeBase.getUptime(NOW_SYS));
14661                         out.writeLong(time);
14662                         out.writeInt(ss.mStarts);
14663                         out.writeInt(ss.mLaunches);
14664                     }
14665                 }
14666             }
14667         }
14668     }
14669 
readFromParcel(Parcel in)14670     public void readFromParcel(Parcel in) {
14671         readFromParcelLocked(in);
14672     }
14673 
readFromParcelLocked(Parcel in)14674     void readFromParcelLocked(Parcel in) {
14675         int magic = in.readInt();
14676         if (magic != MAGIC) {
14677             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
14678         }
14679 
14680         readHistory(in, false);
14681 
14682         mStartCount = in.readInt();
14683         mStartClockTime = in.readLong();
14684         mStartPlatformVersion = in.readString();
14685         mEndPlatformVersion = in.readString();
14686         mUptime = in.readLong();
14687         mUptimeStart = in.readLong();
14688         mRealtime = in.readLong();
14689         mRealtimeStart = in.readLong();
14690         mOnBattery = in.readInt() != 0;
14691         mEstimatedBatteryCapacity = in.readInt();
14692         mMinLearnedBatteryCapacity = in.readInt();
14693         mMaxLearnedBatteryCapacity = in.readInt();
14694         mOnBatteryInternal = false; // we are no longer really running.
14695         mOnBatteryTimeBase.readFromParcel(in);
14696         mOnBatteryScreenOffTimeBase.readFromParcel(in);
14697 
14698         mScreenState = Display.STATE_UNKNOWN;
14699         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14700         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14701         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14702             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
14703                     mOnBatteryTimeBase, in);
14704         }
14705         mInteractive = false;
14706         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
14707         mPhoneOn = false;
14708         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
14709                 mOnBatteryTimeBase, in);
14710         mLongestLightIdleTime = in.readLong();
14711         mLongestFullIdleTime = in.readLong();
14712         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
14713                 mOnBatteryTimeBase, in);
14714         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
14715                 mOnBatteryTimeBase, in);
14716         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
14717                 mOnBatteryTimeBase, in);
14718         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
14719         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
14720         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14721             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
14722                     null, mOnBatteryTimeBase, in);
14723         }
14724         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
14725                 mOnBatteryTimeBase, in);
14726         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14727             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
14728                     null, mOnBatteryTimeBase, in);
14729         }
14730         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14731             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14732             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14733         }
14734         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14735         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
14736                 mOnBatteryTimeBase, in);
14737         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
14738                 mOnBatteryTimeBase, in);
14739         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14740         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14741         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
14742         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null, -4, null,
14743                 mOnBatteryTimeBase, in);
14744         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14745         mWifiOn = false;
14746         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
14747         mGlobalWifiRunning = false;
14748         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
14749                 mOnBatteryTimeBase, in);
14750         for (int i=0; i<NUM_WIFI_STATES; i++) {
14751             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
14752                     null, mOnBatteryTimeBase, in);
14753         }
14754         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14755             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
14756                     null, mOnBatteryTimeBase, in);
14757         }
14758         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14759             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
14760                     null, mOnBatteryTimeBase, in);
14761         }
14762         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null,
14763             mOnBatteryTimeBase, in);
14764         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14765                 NUM_WIFI_TX_LEVELS, in);
14766         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14767             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
14768                 null, mOnBatteryTimeBase, in);
14769         }
14770         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14771                 NUM_BT_TX_LEVELS, in);
14772         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14773                 ModemActivityInfo.TX_POWER_LEVELS, in);
14774         mHasWifiReporting = in.readInt() != 0;
14775         mHasBluetoothReporting = in.readInt() != 0;
14776         mHasModemReporting = in.readInt() != 0;
14777 
14778         mNumConnectivityChange = in.readInt();
14779         mLoadedNumConnectivityChange = in.readInt();
14780         mUnpluggedNumConnectivityChange = in.readInt();
14781         mAudioOnNesting = 0;
14782         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
14783         mVideoOnNesting = 0;
14784         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
14785         mFlashlightOnNesting = 0;
14786         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
14787         mCameraOnNesting = 0;
14788         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
14789         mBluetoothScanNesting = 0;
14790         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
14791         mIsCellularTxPowerHigh = false;
14792         mDischargeUnplugLevel = in.readInt();
14793         mDischargePlugLevel = in.readInt();
14794         mDischargeCurrentLevel = in.readInt();
14795         mCurrentBatteryLevel = in.readInt();
14796         mLowDischargeAmountSinceCharge = in.readInt();
14797         mHighDischargeAmountSinceCharge = in.readInt();
14798         mDischargeAmountScreenOn = in.readInt();
14799         mDischargeAmountScreenOnSinceCharge = in.readInt();
14800         mDischargeAmountScreenOff = in.readInt();
14801         mDischargeAmountScreenOffSinceCharge = in.readInt();
14802         mDischargeAmountScreenDoze = in.readInt();
14803         mDischargeAmountScreenDozeSinceCharge = in.readInt();
14804         mDischargeStepTracker.readFromParcel(in);
14805         mChargeStepTracker.readFromParcel(in);
14806         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14807         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
14808         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14809         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14810         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14811         mLastWriteTime = in.readLong();
14812 
14813         mRpmStats.clear();
14814         int NRPMS = in.readInt();
14815         for (int irpm = 0; irpm < NRPMS; irpm++) {
14816             if (in.readInt() != 0) {
14817                 String rpmName = in.readString();
14818                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14819                 mRpmStats.put(rpmName, rpmt);
14820             }
14821         }
14822         mScreenOffRpmStats.clear();
14823         int NSORPMS = in.readInt();
14824         for (int irpm = 0; irpm < NSORPMS; irpm++) {
14825             if (in.readInt() != 0) {
14826                 String rpmName = in.readString();
14827                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14828                 mScreenOffRpmStats.put(rpmName, rpmt);
14829             }
14830         }
14831 
14832         mKernelWakelockStats.clear();
14833         int NKW = in.readInt();
14834         for (int ikw = 0; ikw < NKW; ikw++) {
14835             if (in.readInt() != 0) {
14836                 String wakelockName = in.readString();
14837                 SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14838                 mKernelWakelockStats.put(wakelockName, kwlt);
14839             }
14840         }
14841 
14842         mWakeupReasonStats.clear();
14843         int NWR = in.readInt();
14844         for (int iwr = 0; iwr < NWR; iwr++) {
14845             if (in.readInt() != 0) {
14846                 String reasonName = in.readString();
14847                 SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14848                 mWakeupReasonStats.put(reasonName, timer);
14849             }
14850         }
14851 
14852         mKernelMemoryStats.clear();
14853         int nmt = in.readInt();
14854         for (int imt = 0; imt < nmt; imt++) {
14855             if (in.readInt() != 0) {
14856                 Long bucket = in.readLong();
14857                 SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14858                 mKernelMemoryStats.put(bucket, kmt);
14859             }
14860         }
14861 
14862         mPartialTimers.clear();
14863         mFullTimers.clear();
14864         mWindowTimers.clear();
14865         mWifiRunningTimers.clear();
14866         mFullWifiLockTimers.clear();
14867         mWifiScanTimers.clear();
14868         mWifiBatchedScanTimers.clear();
14869         mWifiMulticastTimers.clear();
14870         mAudioTurnedOnTimers.clear();
14871         mVideoTurnedOnTimers.clear();
14872         mFlashlightTurnedOnTimers.clear();
14873         mCameraTurnedOnTimers.clear();
14874 
14875         int numUids = in.readInt();
14876         mUidStats.clear();
14877         for (int i = 0; i < numUids; i++) {
14878             int uid = in.readInt();
14879             Uid u = new Uid(this, uid);
14880             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
14881             mUidStats.append(uid, u);
14882         }
14883     }
14884 
writeToParcel(Parcel out, int flags)14885     public void writeToParcel(Parcel out, int flags) {
14886         writeToParcelLocked(out, true, flags);
14887     }
14888 
writeToParcelWithoutUids(Parcel out, int flags)14889     public void writeToParcelWithoutUids(Parcel out, int flags) {
14890         writeToParcelLocked(out, false, flags);
14891     }
14892 
14893     @SuppressWarnings("unused")
writeToParcelLocked(Parcel out, boolean inclUids, int flags)14894     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
14895         // Need to update with current kernel wake lock counts.
14896         pullPendingStateUpdatesLocked();
14897 
14898         // Pull the clock time.  This may update the time and make a new history entry
14899         // if we had originally pulled a time before the RTC was set.
14900         long startClockTime = getStartClockTime();
14901 
14902         final long uSecUptime = mClocks.uptimeMillis() * 1000;
14903         final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
14904         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
14905         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
14906 
14907         out.writeInt(MAGIC);
14908 
14909         writeHistory(out, true, false);
14910 
14911         out.writeInt(mStartCount);
14912         out.writeLong(startClockTime);
14913         out.writeString(mStartPlatformVersion);
14914         out.writeString(mEndPlatformVersion);
14915         out.writeLong(mUptime);
14916         out.writeLong(mUptimeStart);
14917         out.writeLong(mRealtime);
14918         out.writeLong(mRealtimeStart);
14919         out.writeInt(mOnBattery ? 1 : 0);
14920         out.writeInt(mEstimatedBatteryCapacity);
14921         out.writeInt(mMinLearnedBatteryCapacity);
14922         out.writeInt(mMaxLearnedBatteryCapacity);
14923         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14924         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14925 
14926         mScreenOnTimer.writeToParcel(out, uSecRealtime);
14927         mScreenDozeTimer.writeToParcel(out, uSecRealtime);
14928         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14929             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
14930         }
14931         mInteractiveTimer.writeToParcel(out, uSecRealtime);
14932         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
14933         out.writeLong(mLongestLightIdleTime);
14934         out.writeLong(mLongestFullIdleTime);
14935         mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
14936         mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
14937         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
14938         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
14939         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
14940         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14941             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14942         }
14943         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
14944         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14945             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
14946         }
14947         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14948             mNetworkByteActivityCounters[i].writeToParcel(out);
14949             mNetworkPacketActivityCounters[i].writeToParcel(out);
14950         }
14951         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
14952         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
14953         mMobileRadioActiveAdjustedTime.writeToParcel(out);
14954         mMobileRadioActiveUnknownTime.writeToParcel(out);
14955         mMobileRadioActiveUnknownCount.writeToParcel(out);
14956         mWifiMulticastWakelockTimer.writeToParcel(out, uSecRealtime);
14957         mWifiOnTimer.writeToParcel(out, uSecRealtime);
14958         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
14959         for (int i=0; i<NUM_WIFI_STATES; i++) {
14960             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
14961         }
14962         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14963             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
14964         }
14965         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14966             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14967         }
14968         mWifiActiveTimer.writeToParcel(out, uSecRealtime);
14969         mWifiActivity.writeToParcel(out, 0);
14970         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14971             mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
14972         }
14973         mBluetoothActivity.writeToParcel(out, 0);
14974         mModemActivity.writeToParcel(out, 0);
14975         out.writeInt(mHasWifiReporting ? 1 : 0);
14976         out.writeInt(mHasBluetoothReporting ? 1 : 0);
14977         out.writeInt(mHasModemReporting ? 1 : 0);
14978 
14979         out.writeInt(mNumConnectivityChange);
14980         out.writeInt(mLoadedNumConnectivityChange);
14981         out.writeInt(mUnpluggedNumConnectivityChange);
14982         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
14983         mCameraOnTimer.writeToParcel(out, uSecRealtime);
14984         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
14985         out.writeInt(mDischargeUnplugLevel);
14986         out.writeInt(mDischargePlugLevel);
14987         out.writeInt(mDischargeCurrentLevel);
14988         out.writeInt(mCurrentBatteryLevel);
14989         out.writeInt(mLowDischargeAmountSinceCharge);
14990         out.writeInt(mHighDischargeAmountSinceCharge);
14991         out.writeInt(mDischargeAmountScreenOn);
14992         out.writeInt(mDischargeAmountScreenOnSinceCharge);
14993         out.writeInt(mDischargeAmountScreenOff);
14994         out.writeInt(mDischargeAmountScreenOffSinceCharge);
14995         out.writeInt(mDischargeAmountScreenDoze);
14996         out.writeInt(mDischargeAmountScreenDozeSinceCharge);
14997         mDischargeStepTracker.writeToParcel(out);
14998         mChargeStepTracker.writeToParcel(out);
14999         mDischargeCounter.writeToParcel(out);
15000         mDischargeScreenOffCounter.writeToParcel(out);
15001         mDischargeScreenDozeCounter.writeToParcel(out);
15002         mDischargeLightDozeCounter.writeToParcel(out);
15003         mDischargeDeepDozeCounter.writeToParcel(out);
15004         out.writeLong(mLastWriteTime);
15005 
15006         out.writeInt(mRpmStats.size());
15007         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
15008             SamplingTimer rpmt = ent.getValue();
15009             if (rpmt != null) {
15010                 out.writeInt(1);
15011                 out.writeString(ent.getKey());
15012                 rpmt.writeToParcel(out, uSecRealtime);
15013             } else {
15014                 out.writeInt(0);
15015             }
15016         }
15017         out.writeInt(mScreenOffRpmStats.size());
15018         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
15019             SamplingTimer rpmt = ent.getValue();
15020             if (rpmt != null) {
15021                 out.writeInt(1);
15022                 out.writeString(ent.getKey());
15023                 rpmt.writeToParcel(out, uSecRealtime);
15024             } else {
15025                 out.writeInt(0);
15026             }
15027         }
15028 
15029         if (inclUids) {
15030             out.writeInt(mKernelWakelockStats.size());
15031             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
15032                 SamplingTimer kwlt = ent.getValue();
15033                 if (kwlt != null) {
15034                     out.writeInt(1);
15035                     out.writeString(ent.getKey());
15036                     kwlt.writeToParcel(out, uSecRealtime);
15037                 } else {
15038                     out.writeInt(0);
15039                 }
15040             }
15041             out.writeInt(mWakeupReasonStats.size());
15042             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
15043                 SamplingTimer timer = ent.getValue();
15044                 if (timer != null) {
15045                     out.writeInt(1);
15046                     out.writeString(ent.getKey());
15047                     timer.writeToParcel(out, uSecRealtime);
15048                 } else {
15049                     out.writeInt(0);
15050                 }
15051             }
15052         } else {
15053             out.writeInt(0);
15054             out.writeInt(0);
15055         }
15056 
15057         out.writeInt(mKernelMemoryStats.size());
15058         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
15059             SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
15060             if (kmt != null) {
15061                 out.writeInt(1);
15062                 out.writeLong(mKernelMemoryStats.keyAt(i));
15063                 kmt.writeToParcel(out, uSecRealtime);
15064             } else {
15065                 out.writeInt(0);
15066             }
15067         }
15068 
15069         if (inclUids) {
15070             int size = mUidStats.size();
15071             out.writeInt(size);
15072             for (int i = 0; i < size; i++) {
15073                 out.writeInt(mUidStats.keyAt(i));
15074                 Uid uid = mUidStats.valueAt(i);
15075 
15076                 uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
15077             }
15078         } else {
15079             out.writeInt(0);
15080         }
15081     }
15082 
15083     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
15084         new Parcelable.Creator<BatteryStatsImpl>() {
15085         public BatteryStatsImpl createFromParcel(Parcel in) {
15086             return new BatteryStatsImpl(in);
15087         }
15088 
15089         public BatteryStatsImpl[] newArray(int size) {
15090             return new BatteryStatsImpl[size];
15091         }
15092     };
15093 
prepareForDumpLocked()15094     public void prepareForDumpLocked() {
15095         // Need to retrieve current kernel wake lock stats before printing.
15096         pullPendingStateUpdatesLocked();
15097 
15098         // Pull the clock time.  This may update the time and make a new history entry
15099         // if we had originally pulled a time before the RTC was set.
15100         getStartClockTime();
15101     }
15102 
dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart)15103     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
15104         if (DEBUG) {
15105             pw.println("mOnBatteryTimeBase:");
15106             mOnBatteryTimeBase.dump(pw, "  ");
15107             pw.println("mOnBatteryScreenOffTimeBase:");
15108             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
15109             Printer pr = new PrintWriterPrinter(pw);
15110             pr.println("*** Screen on timer:");
15111             mScreenOnTimer.logState(pr, "  ");
15112             pr.println("*** Screen doze timer:");
15113             mScreenDozeTimer.logState(pr, "  ");
15114             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
15115                 pr.println("*** Screen brightness #" + i + ":");
15116                 mScreenBrightnessTimer[i].logState(pr, "  ");
15117             }
15118             pr.println("*** Interactive timer:");
15119             mInteractiveTimer.logState(pr, "  ");
15120             pr.println("*** Power save mode timer:");
15121             mPowerSaveModeEnabledTimer.logState(pr, "  ");
15122             pr.println("*** Device idle mode light timer:");
15123             mDeviceIdleModeLightTimer.logState(pr, "  ");
15124             pr.println("*** Device idle mode full timer:");
15125             mDeviceIdleModeFullTimer.logState(pr, "  ");
15126             pr.println("*** Device light idling timer:");
15127             mDeviceLightIdlingTimer.logState(pr, "  ");
15128             pr.println("*** Device idling timer:");
15129             mDeviceIdlingTimer.logState(pr, "  ");
15130             pr.println("*** Phone timer:");
15131             mPhoneOnTimer.logState(pr, "  ");
15132             for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
15133                 pr.println("*** Phone signal strength #" + i + ":");
15134                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
15135             }
15136             pr.println("*** Signal scanning :");
15137             mPhoneSignalScanningTimer.logState(pr, "  ");
15138             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
15139                 pr.println("*** Data connection type #" + i + ":");
15140                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
15141             }
15142             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
15143             pr.println("*** Mobile network active timer:");
15144             mMobileRadioActiveTimer.logState(pr, "  ");
15145             pr.println("*** Mobile network active adjusted timer:");
15146             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
15147             pr.println("*** Wifi Multicast WakeLock Timer:");
15148             mWifiMulticastWakelockTimer.logState(pr, "  ");
15149             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
15150             pr.println("*** Wifi timer:");
15151             mWifiOnTimer.logState(pr, "  ");
15152             pr.println("*** WifiRunning timer:");
15153             mGlobalWifiRunningTimer.logState(pr, "  ");
15154             for (int i=0; i<NUM_WIFI_STATES; i++) {
15155                 pr.println("*** Wifi state #" + i + ":");
15156                 mWifiStateTimer[i].logState(pr, "  ");
15157             }
15158             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15159                 pr.println("*** Wifi suppl state #" + i + ":");
15160                 mWifiSupplStateTimer[i].logState(pr, "  ");
15161             }
15162             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15163                 pr.println("*** Wifi signal strength #" + i + ":");
15164                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
15165             }
15166             for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
15167                 pr.println("*** GPS signal quality #" + i + ":");
15168                 mGpsSignalQualityTimer[i].logState(pr, "  ");
15169             }
15170             pr.println("*** Flashlight timer:");
15171             mFlashlightOnTimer.logState(pr, "  ");
15172             pr.println("*** Camera timer:");
15173             mCameraOnTimer.logState(pr, "  ");
15174         }
15175         super.dumpLocked(context, pw, flags, reqUid, histStart);
15176         pw.print("Total cpu time reads: ");
15177         pw.println(mNumSingleUidCpuTimeReads);
15178         pw.print("Batched cpu time reads: ");
15179         pw.println(mNumBatchedSingleUidCpuTimeReads);
15180         pw.print("Batching Duration (min): ");
15181         pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTime) / (60 * 1000));
15182         pw.print("All UID cpu time reads since the later of device start or stats reset: ");
15183         pw.println(mNumAllUidCpuTimeReads);
15184         pw.print("UIDs removed since the later of device start or stats reset: ");
15185         pw.println(mNumUidsRemoved);
15186     }
15187 }
15188