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 static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
20 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
21 import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
22 import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
23 
24 import android.annotation.IntDef;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.app.ActivityManager;
28 import android.bluetooth.BluetoothActivityEnergyInfo;
29 import android.bluetooth.UidTraffic;
30 import android.compat.annotation.UnsupportedAppUsage;
31 import android.content.BroadcastReceiver;
32 import android.content.ContentResolver;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.IntentFilter;
36 import android.database.ContentObserver;
37 import android.hardware.usb.UsbManager;
38 import android.location.GnssSignalQuality;
39 import android.net.INetworkStatsService;
40 import android.net.NetworkStats;
41 import android.net.Uri;
42 import android.net.wifi.WifiManager;
43 import android.os.BatteryConsumer;
44 import android.os.BatteryManager;
45 import android.os.BatteryStats;
46 import android.os.Binder;
47 import android.os.Build;
48 import android.os.Handler;
49 import android.os.IBatteryPropertiesRegistrar;
50 import android.os.Looper;
51 import android.os.Message;
52 import android.os.OsProtoEnums;
53 import android.os.Parcel;
54 import android.os.ParcelFormatException;
55 import android.os.Parcelable;
56 import android.os.PowerManager;
57 import android.os.Process;
58 import android.os.RemoteException;
59 import android.os.ServiceManager;
60 import android.os.SystemClock;
61 import android.os.UserHandle;
62 import android.os.WorkSource;
63 import android.os.WorkSource.WorkChain;
64 import android.os.connectivity.CellularBatteryStats;
65 import android.os.connectivity.GpsBatteryStats;
66 import android.os.connectivity.WifiActivityEnergyInfo;
67 import android.os.connectivity.WifiBatteryStats;
68 import android.provider.Settings;
69 import android.telephony.CellSignalStrength;
70 import android.telephony.DataConnectionRealTimeInfo;
71 import android.telephony.ModemActivityInfo;
72 import android.telephony.ServiceState;
73 import android.telephony.SignalStrength;
74 import android.telephony.TelephonyManager;
75 import android.text.TextUtils;
76 import android.util.ArrayMap;
77 import android.util.ArraySet;
78 import android.util.AtomicFile;
79 import android.util.IndentingPrintWriter;
80 import android.util.IntArray;
81 import android.util.KeyValueListParser;
82 import android.util.Log;
83 import android.util.LongSparseArray;
84 import android.util.LongSparseLongArray;
85 import android.util.MutableInt;
86 import android.util.Pools;
87 import android.util.PrintWriterPrinter;
88 import android.util.Printer;
89 import android.util.Slog;
90 import android.util.SparseArray;
91 import android.util.SparseDoubleArray;
92 import android.util.SparseIntArray;
93 import android.util.SparseLongArray;
94 import android.util.TimeUtils;
95 import android.util.TypedXmlPullParser;
96 import android.util.TypedXmlSerializer;
97 import android.util.Xml;
98 import android.view.Display;
99 
100 import com.android.internal.annotations.GuardedBy;
101 import com.android.internal.annotations.VisibleForTesting;
102 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
103 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
104 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
105 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
106 import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
107 import com.android.internal.power.MeasuredEnergyStats;
108 import com.android.internal.power.MeasuredEnergyStats.StandardPowerBucket;
109 import com.android.internal.util.ArrayUtils;
110 import com.android.internal.util.FrameworkStatsLog;
111 import com.android.internal.util.XmlUtils;
112 import com.android.net.module.util.NetworkCapabilitiesUtils;
113 
114 import libcore.util.EmptyArray;
115 
116 import org.xmlpull.v1.XmlPullParser;
117 import org.xmlpull.v1.XmlPullParserException;
118 
119 import java.io.ByteArrayOutputStream;
120 import java.io.File;
121 import java.io.FileInputStream;
122 import java.io.FileNotFoundException;
123 import java.io.FileOutputStream;
124 import java.io.IOException;
125 import java.io.PrintWriter;
126 import java.lang.annotation.Retention;
127 import java.lang.annotation.RetentionPolicy;
128 import java.util.ArrayList;
129 import java.util.Arrays;
130 import java.util.Calendar;
131 import java.util.Collection;
132 import java.util.Comparator;
133 import java.util.HashMap;
134 import java.util.HashSet;
135 import java.util.Iterator;
136 import java.util.LinkedList;
137 import java.util.List;
138 import java.util.Map;
139 import java.util.Queue;
140 import java.util.concurrent.Future;
141 import java.util.concurrent.atomic.AtomicInteger;
142 import java.util.concurrent.locks.ReentrantLock;
143 
144 /**
145  * All information we are collecting about things that can happen that impact
146  * battery life.  All times are represented in microseconds except where indicated
147  * otherwise.
148  */
149 public class BatteryStatsImpl extends BatteryStats {
150     private static final String TAG = "BatteryStatsImpl";
151     private static final boolean DEBUG = false;
152     public static final boolean DEBUG_ENERGY = false;
153     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
154     private static final boolean DEBUG_BINDER_STATS = false;
155     private static final boolean DEBUG_MEMORY = false;
156     private static final boolean DEBUG_HISTORY = false;
157 
158     // TODO: remove "tcp" from network methods, since we measure total stats.
159 
160     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
161     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
162 
163     // Current on-disk Parcel version
164     static final int VERSION = 200;
165 
166     // The maximum number of names wakelocks we will keep track of
167     // per uid; once the limit is reached, we batch the remaining wakelocks
168     // in to one common name.
169     private static final int MAX_WAKELOCKS_PER_UID;
170 
171     static {
172         if (ActivityManager.isLowRamDeviceStatic()) {
173             MAX_WAKELOCKS_PER_UID = 40;
174         } else {
175             MAX_WAKELOCKS_PER_UID = 200;
176         }
177     }
178 
179     // Number of transmit power states the Wifi controller can be in.
180     private static final int NUM_WIFI_TX_LEVELS = 1;
181 
182     // Number of transmit power states the Bluetooth controller can be in.
183     private static final int NUM_BT_TX_LEVELS = 1;
184 
185     /**
186      * Holding a wakelock costs more than just using the cpu.
187      * Currently, we assign only half the cpu time to an app that is running but
188      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
189      * If no app is holding a wakelock, then the distribution is normal.
190      */
191     @VisibleForTesting
192     public static final int WAKE_LOCK_WEIGHT = 50;
193 
194     public static final int RESET_REASON_CORRUPT_FILE = 1;
195     public static final int RESET_REASON_ADB_COMMAND = 2;
196     public static final int RESET_REASON_FULL_CHARGE = 3;
197     public static final int RESET_REASON_MEASURED_ENERGY_BUCKETS_CHANGE = 4;
198 
199     protected Clocks mClocks;
200 
201     private final AtomicFile mStatsFile;
202     public final AtomicFile mCheckinFile;
203     public final AtomicFile mDailyFile;
204 
205     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
206     static final int MSG_REPORT_POWER_CHANGE = 2;
207     static final int MSG_REPORT_CHARGING = 3;
208     static final int MSG_REPORT_RESET_STATS = 4;
209     static final long DELAY_UPDATE_WAKELOCKS = 60 * 1000;
210 
211     private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
212     private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
213 
214     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
215     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
216 
217     @VisibleForTesting
218     protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
219             new KernelCpuUidUserSysTimeReader(true);
220     @VisibleForTesting
221     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
222     @VisibleForTesting
223     protected KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
224             new KernelCpuUidFreqTimeReader(true);
225     @VisibleForTesting
226     protected KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
227             new KernelCpuUidActiveTimeReader(true);
228     @VisibleForTesting
229     protected KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
230             new KernelCpuUidClusterTimeReader(true);
231     @VisibleForTesting
232     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
233     @VisibleForTesting
234     protected SystemServerCpuThreadReader mSystemServerCpuThreadReader =
235             SystemServerCpuThreadReader.create();
236 
237     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
238             = new KernelMemoryBandwidthStats();
239     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
240 
getKernelMemoryStats()241     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
242         return mKernelMemoryStats;
243     }
244 
245     @GuardedBy("this")
246     public boolean mPerProcStateCpuTimesAvailable = true;
247 
248     /**
249      * When per process state cpu times tracking is off, cpu times in KernelSingleUidTimeReader are
250      * not updated. So, when the setting is turned on later, we would end up with huge cpu time
251      * deltas. This flag tracks the case where tracking is turned on from off so that we won't
252      * end up attributing the huge deltas to wrong buckets.
253      */
254     @GuardedBy("this")
255     private boolean mIsPerProcessStateCpuDataStale;
256 
257     /**
258      * Uids for which per-procstate cpu times need to be updated.
259      *
260      * Contains uid -> procState mappings.
261      */
262     @GuardedBy("this")
263     @VisibleForTesting
264     protected final SparseIntArray mPendingUids = new SparseIntArray();
265 
266     @GuardedBy("this")
267     private long mNumSingleUidCpuTimeReads;
268     @GuardedBy("this")
269     private long mNumBatchedSingleUidCpuTimeReads;
270     @GuardedBy("this")
271     private long mCpuTimeReadsTrackingStartTimeMs = SystemClock.uptimeMillis();
272     @GuardedBy("this")
273     private int mNumUidsRemoved;
274     @GuardedBy("this")
275     private int mNumAllUidCpuTimeReads;
276 
277     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
278     private RpmStats mTmpRpmStats = null;
279     /** The soonest the RPM stats can be updated after it was last updated. */
280     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
281     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
282     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
283 
284     /** Container for Rail Energy Data stats. */
285     private final RailStats mTmpRailStats = new RailStats();
286 
287     /**
288      * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
289      * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
290      * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
291      *
292      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
293      * Batterystats both need to access UID cpu time. To resolve this race condition, only
294      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
295      * implemented so that STATSD can capture those UID times before they are deleted.
296      */
297     @GuardedBy("this")
298     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
299     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
300 
301     @VisibleForTesting
302     public final class UidToRemove {
303         int startUid;
304         int endUid;
305         long mTimeAddedInQueueMs;
306 
307         /** Remove just one UID */
UidToRemove(int uid, long timestamp)308         public UidToRemove(int uid, long timestamp) {
309             this(uid, uid, timestamp);
310         }
311 
312         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)313         public UidToRemove(int startUid, int endUid, long timestamp) {
314             this.startUid = startUid;
315             this.endUid = endUid;
316             mTimeAddedInQueueMs = timestamp;
317         }
318 
remove()319         void remove() {
320             if (startUid == endUid) {
321                 mCpuUidUserSysTimeReader.removeUid(startUid);
322                 mCpuUidFreqTimeReader.removeUid(startUid);
323                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
324                     mCpuUidActiveTimeReader.removeUid(startUid);
325                     mCpuUidClusterTimeReader.removeUid(startUid);
326                 }
327                 if (mKernelSingleUidTimeReader != null) {
328                     mKernelSingleUidTimeReader.removeUid(startUid);
329                 }
330                 mNumUidsRemoved++;
331             } else if (startUid < endUid) {
332                 mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
333                 mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
334                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
335                     mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
336                     mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
337                 }
338                 if (mKernelSingleUidTimeReader != null) {
339                     mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
340                 }
341                 // Treat as one. We don't know how many uids there are in between.
342                 mNumUidsRemoved++;
343             } else {
344                 Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
345             }
346         }
347     }
348 
349     /**
350      * Listener for the battery stats reset.
351      */
352     public interface BatteryResetListener {
353 
354         /**
355          * Callback invoked immediately prior to resetting battery stats.
356          * @param resetReason One of the RESET_REASON_* constants.
357          */
prepareForBatteryStatsReset(int resetReason)358         void prepareForBatteryStatsReset(int resetReason);
359     }
360 
361     private BatteryResetListener mBatteryResetListener;
362 
363     public interface BatteryCallback {
batteryNeedsCpuUpdate()364         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)365         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)366         public void batterySendBroadcast(Intent intent);
batteryStatsReset()367         public void batteryStatsReset();
368     }
369 
370     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)371         public void fillLowPowerStats(RpmStats rpmStats);
getSubsystemLowPowerStats()372         public String getSubsystemLowPowerStats();
373     }
374 
375     /** interface to update rail information for power monitor */
376     public interface MeasuredEnergyRetriever {
377         /** Function to fill the map for the rail data stats
378          * Used for power monitoring feature
379          * @param railStats
380          */
fillRailDataStats(RailStats railStats)381         void fillRailDataStats(RailStats railStats);
382     }
383 
384     public static abstract class UserInfoProvider {
385         private int[] userIds;
getUserIds()386         protected abstract @Nullable int[] getUserIds();
387         @VisibleForTesting
refreshUserIds()388         public final void refreshUserIds() {
389             userIds = getUserIds();
390         }
391         @VisibleForTesting
exists(int userId)392         public boolean exists(int userId) {
393             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
394         }
395     }
396 
397     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
398 
399     private final Runnable mDeferSetCharging = new Runnable() {
400         @Override
401         public void run() {
402             synchronized (BatteryStatsImpl.this) {
403                 if (mOnBattery) {
404                     // if the device gets unplugged in the time between this runnable being
405                     // executed and the lock being taken, we don't want to set charging state
406                     return;
407                 }
408                 boolean changed = setChargingLocked(true);
409                 if (changed) {
410                     final long uptimeMs = mClocks.uptimeMillis();
411                     final long elapsedRealtimeMs = mClocks.elapsedRealtime();
412                     addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
413                 }
414             }
415         }
416     };
417 
418     public final MeasuredEnergyRetriever mMeasuredEnergyRetriever;
419 
420     /**
421      * This handler is running on {@link BackgroundThread}.
422      */
423     final class MyHandler extends Handler {
MyHandler(Looper looper)424         public MyHandler(Looper looper) {
425             super(looper, null, true);
426         }
427 
428         @Override
handleMessage(Message msg)429         public void handleMessage(Message msg) {
430             BatteryCallback cb = mCallback;
431             switch (msg.what) {
432                 case MSG_REPORT_CPU_UPDATE_NEEDED:
433                     if (cb != null) {
434                         cb.batteryNeedsCpuUpdate();
435                     }
436                     break;
437                 case MSG_REPORT_POWER_CHANGE:
438                     if (cb != null) {
439                         cb.batteryPowerChanged(msg.arg1 != 0);
440                     }
441                     break;
442                 case MSG_REPORT_CHARGING:
443                     if (cb != null) {
444                         final String action;
445                         synchronized (BatteryStatsImpl.this) {
446                             action = mCharging ? BatteryManager.ACTION_CHARGING
447                                     : BatteryManager.ACTION_DISCHARGING;
448                         }
449                         Intent intent = new Intent(action);
450                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
451                         cb.batterySendBroadcast(intent);
452                     }
453                     break;
454                 case MSG_REPORT_RESET_STATS:
455                     if (cb != null) {
456                         cb.batteryStatsReset();
457                     }
458                 }
459         }
460     }
461 
postBatteryNeedsCpuUpdateMsg()462     public void postBatteryNeedsCpuUpdateMsg() {
463         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
464     }
465 
466     /**
467      * Update per-freq cpu times for all the uids in {@link #mPendingUids}.
468      */
updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff)469     public void updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
470         final SparseIntArray uidStates;
471         synchronized (BatteryStatsImpl.this) {
472             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
473                 return;
474             }
475             if(!initKernelSingleUidTimeReaderLocked()) {
476                 return;
477             }
478             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
479             // compute deltas since it might result in mis-attributing cpu times to wrong states.
480             if (mIsPerProcessStateCpuDataStale) {
481                 mPendingUids.clear();
482                 return;
483             }
484 
485             if (mPendingUids.size() == 0) {
486                 return;
487             }
488             uidStates = mPendingUids.clone();
489             mPendingUids.clear();
490         }
491         for (int i = uidStates.size() - 1; i >= 0; --i) {
492             final int uid = uidStates.keyAt(i);
493             final int procState = uidStates.valueAt(i);
494             final int[] isolatedUids;
495             final Uid u;
496             synchronized (BatteryStatsImpl.this) {
497                 // It's possible that uid no longer exists and any internal references have
498                 // already been deleted, so using {@link #getAvailableUidStatsLocked} to avoid
499                 // creating an UidStats object if it doesn't already exist.
500                 u = getAvailableUidStatsLocked(uid);
501                 if (u == null) {
502                     continue;
503                 }
504                 if (u.mChildUids == null) {
505                     isolatedUids = null;
506                 } else {
507                     isolatedUids = u.mChildUids.toArray();
508                     for (int j = isolatedUids.length - 1; j >= 0; --j) {
509                         isolatedUids[j] = u.mChildUids.get(j);
510                     }
511                 }
512             }
513             long[] cpuTimesMs = mKernelSingleUidTimeReader.readDeltaMs(uid);
514             if (isolatedUids != null) {
515                 for (int j = isolatedUids.length - 1; j >= 0; --j) {
516                     cpuTimesMs = addCpuTimes(cpuTimesMs,
517                             mKernelSingleUidTimeReader.readDeltaMs(isolatedUids[j]));
518                 }
519             }
520             if (onBattery && cpuTimesMs != null) {
521                 synchronized (BatteryStatsImpl.this) {
522                     u.addProcStateTimesMs(procState, cpuTimesMs, onBattery);
523                     u.addProcStateScreenOffTimesMs(procState, cpuTimesMs, onBatteryScreenOff);
524                 }
525             }
526         }
527     }
528 
clearPendingRemovedUids()529     public void clearPendingRemovedUids() {
530         long cutOffTimeMs = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
531         while (!mPendingRemovedUids.isEmpty()
532                 && mPendingRemovedUids.peek().mTimeAddedInQueueMs < cutOffTimeMs) {
533             mPendingRemovedUids.poll().remove();
534         }
535     }
536 
copyFromAllUidsCpuTimes()537     public void copyFromAllUidsCpuTimes() {
538         synchronized (BatteryStatsImpl.this) {
539             copyFromAllUidsCpuTimes(
540                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
541         }
542     }
543 
544     /**
545      * When the battery/screen state changes, we don't attribute the cpu times to any process
546      * but we still need to snapshots of all uids to get correct deltas later on. Since we
547      * already read this data for updating per-freq cpu times, we can use the same data for
548      * per-procstate cpu times.
549      */
copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)550     public void copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
551         synchronized (BatteryStatsImpl.this) {
552             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
553                 return;
554             }
555             if(!initKernelSingleUidTimeReaderLocked()) {
556                 return;
557             }
558 
559             final SparseArray<long[]> allUidCpuFreqTimesMs =
560                     mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
561             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
562             // compute deltas since it might result in mis-attributing cpu times to wrong states.
563             if (mIsPerProcessStateCpuDataStale) {
564                 mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
565                 mIsPerProcessStateCpuDataStale = false;
566                 mPendingUids.clear();
567                 return;
568             }
569             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
570                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
571                 final Uid u = getAvailableUidStatsLocked(mapUid(uid));
572                 if (u == null) {
573                     continue;
574                 }
575                 final long[] cpuTimesMs = allUidCpuFreqTimesMs.valueAt(i);
576                 if (cpuTimesMs == null) {
577                     continue;
578                 }
579                 final long[] deltaTimesMs = mKernelSingleUidTimeReader.computeDelta(
580                         uid, cpuTimesMs.clone());
581                 if (onBattery && deltaTimesMs != null) {
582                     final int procState;
583                     final int idx = mPendingUids.indexOfKey(uid);
584                     if (idx >= 0) {
585                         procState = mPendingUids.valueAt(idx);
586                         mPendingUids.removeAt(idx);
587                     } else {
588                         procState = u.mProcessState;
589                     }
590                     if (procState >= 0 && procState < Uid.NUM_PROCESS_STATE) {
591                         u.addProcStateTimesMs(procState, deltaTimesMs, onBattery);
592                         u.addProcStateScreenOffTimesMs(procState, deltaTimesMs, onBatteryScreenOff);
593                     }
594                 }
595             }
596         }
597     }
598 
599     @VisibleForTesting
addCpuTimes(long[] timesA, long[] timesB)600     public static long[] addCpuTimes(long[] timesA, long[] timesB) {
601         if (timesA != null && timesB != null) {
602             for (int i = timesA.length - 1; i >= 0; --i) {
603                 timesA[i] += timesB[i];
604             }
605             return timesA;
606         }
607         return timesA == null ? (timesB == null ? null : timesB) : timesA;
608     }
609 
610     @GuardedBy("this")
initKernelSingleUidTimeReaderLocked()611     private boolean initKernelSingleUidTimeReaderLocked() {
612         if (mKernelSingleUidTimeReader == null) {
613             if (mPowerProfile == null) {
614                 return false;
615             }
616             if (mCpuFreqs == null) {
617                 mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
618             }
619             if (mCpuFreqs != null) {
620                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
621             } else {
622                 mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable();
623                 return false;
624             }
625         }
626         mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable()
627                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
628         return true;
629     }
630 
631     public interface Clocks {
632         /** Elapsed Realtime, see SystemClock.elapsedRealtime() */
elapsedRealtime()633         long elapsedRealtime();
634 
635         /** Uptime, see SystemClock.uptimeMillis() */
uptimeMillis()636         long uptimeMillis();
637 
638         /** Wall-clock time as per System.currentTimeMillis() */
currentTimeMillis()639         long currentTimeMillis();
640     }
641 
642     public static class SystemClocks implements Clocks {
643 
644         @Override
elapsedRealtime()645         public long elapsedRealtime() {
646             return SystemClock.elapsedRealtime();
647         }
648 
649         @Override
uptimeMillis()650         public long uptimeMillis() {
651             return SystemClock.uptimeMillis();
652         }
653 
654         @Override
currentTimeMillis()655         public long currentTimeMillis() {
656             return System.currentTimeMillis();
657         }
658     }
659 
660     public interface ExternalStatsSync {
661         int UPDATE_CPU = 0x01;
662         int UPDATE_WIFI = 0x02;
663         int UPDATE_RADIO = 0x04;
664         int UPDATE_BT = 0x08;
665         int UPDATE_RPM = 0x10;
666         int UPDATE_DISPLAY = 0x20;
667         int UPDATE_ALL =
668                 UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY;
669 
670         @IntDef(flag = true, prefix = "UPDATE_", value = {
671                 UPDATE_CPU,
672                 UPDATE_WIFI,
673                 UPDATE_RADIO,
674                 UPDATE_BT,
675                 UPDATE_RPM,
676                 UPDATE_DISPLAY,
677                 UPDATE_ALL,
678         })
679         @Retention(RetentionPolicy.SOURCE)
680         public @interface ExternalUpdateFlag {
681         }
682 
scheduleSync(String reason, int flags)683         Future<?> scheduleSync(String reason, int flags);
scheduleCpuSyncDueToRemovedUid(int uid)684         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff, long delayMillis)685         Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff,
686                 long delayMillis);
scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)687         Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
scheduleCpuSyncDueToSettingChange()688         Future<?> scheduleCpuSyncDueToSettingChange();
689         /**
690          * Schedule a sync because of a screen state change.
691          */
scheduleSyncDueToScreenStateChange(int flags, boolean onBattery, boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates)692         Future<?> scheduleSyncDueToScreenStateChange(int flags, boolean onBattery,
693                 boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates);
scheduleCpuSyncDueToWakelockChange(long delayMillis)694         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
cancelCpuSyncDueToWakelockChange()695         void cancelCpuSyncDueToWakelockChange();
scheduleSyncDueToBatteryLevelChange(long delayMillis)696         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
697     }
698 
699     public Handler mHandler;
700     private ExternalStatsSync mExternalSync = null;
701     @VisibleForTesting
702     protected UserInfoProvider mUserInfoProvider = null;
703 
704     private BatteryCallback mCallback;
705 
706     /**
707      * Mapping isolated uids to the actual owning app uid.
708      */
709     final SparseIntArray mIsolatedUids = new SparseIntArray();
710     /**
711      * Internal reference count of isolated uids.
712      */
713     final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray();
714 
715     /**
716      * The statistics we have collected organized by uids.
717      */
718     final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
719 
720     // A set of pools of currently active timers.  When a timer is queried, we will divide the
721     // elapsed time by the number of active timers to arrive at that timer's share of the time.
722     // In order to do this, we must refresh each timer whenever the number of active timers
723     // changes.
724     @VisibleForTesting
725     @UnsupportedAppUsage
726     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
727     @UnsupportedAppUsage
728     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
729     @UnsupportedAppUsage
730     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
731     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
732     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
733     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
734     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
735     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
736     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
737     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
738     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
739     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
740     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
741     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
742     final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
743 
744     // Last partial timers we use for distributing CPU usage.
745     @VisibleForTesting
746     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
747 
748     // These are the objects that will want to do something when the device
749     // is unplugged from power.
750     protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
751 
752     // These are the objects that will want to do something when the device
753     // is unplugged from power *and* the screen is off or doze.
754     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
755 
756     // Set to true when we want to distribute CPU across wakelocks for the next
757     // CPU update, even if we aren't currently running wake locks.
758     boolean mDistributeWakelockCpu;
759 
760     private boolean mSystemReady;
761     boolean mShuttingDown;
762 
763     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
764 
765     long mHistoryBaseTimeMs;
766     protected boolean mHaveBatteryLevel = false;
767     protected boolean mRecordingHistory = false;
768     int mNumHistoryItems;
769 
770     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
771     final Parcel mHistoryBuffer = Parcel.obtain();
772     final HistoryItem mHistoryLastWritten = new HistoryItem();
773     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
774     final HistoryItem mHistoryAddTmp = new HistoryItem();
775     int mNextHistoryTagIdx = 0;
776     int mNumHistoryTagChars = 0;
777     int mHistoryBufferLastPos = -1;
778     int mActiveHistoryStates = 0xffffffff;
779     int mActiveHistoryStates2 = 0xffffffff;
780     long mLastHistoryElapsedRealtimeMs = 0;
781     long mTrackRunningHistoryElapsedRealtimeMs = 0;
782     long mTrackRunningHistoryUptimeMs = 0;
783 
784     @NonNull
785     final BatteryStatsHistory mBatteryStatsHistory;
786 
787     final HistoryItem mHistoryCur = new HistoryItem();
788 
789     HistoryItem mHistory;
790     HistoryItem mHistoryEnd;
791     HistoryItem mHistoryLastEnd;
792     HistoryItem mHistoryCache;
793 
794     // Used by computeHistoryStepDetails
795     HistoryStepDetails mLastHistoryStepDetails = null;
796     byte mLastHistoryStepLevel = 0;
797     final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
798     final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
799     final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
800 
801     /**
802      * Total time (in milliseconds) spent executing in user code.
803      */
804     long mLastStepCpuUserTimeMs;
805     long mCurStepCpuUserTimeMs;
806     /**
807      * Total time (in milliseconds) spent executing in kernel code.
808      */
809     long mLastStepCpuSystemTimeMs;
810     long mCurStepCpuSystemTimeMs;
811     /**
812      * Times from /proc/stat (but measured in milliseconds).
813      */
814     long mLastStepStatUserTimeMs;
815     long mLastStepStatSystemTimeMs;
816     long mLastStepStatIOWaitTimeMs;
817     long mLastStepStatIrqTimeMs;
818     long mLastStepStatSoftIrqTimeMs;
819     long mLastStepStatIdleTimeMs;
820     long mCurStepStatUserTimeMs;
821     long mCurStepStatSystemTimeMs;
822     long mCurStepStatIOWaitTimeMs;
823     long mCurStepStatIrqTimeMs;
824     long mCurStepStatSoftIrqTimeMs;
825     long mCurStepStatIdleTimeMs;
826 
827     private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator;
828     private HistoryItem mHistoryIterator;
829     private boolean mReadOverflow;
830 
831     int mStartCount;
832 
833     /**
834      * Set to true when a reset occurs, informing us that the next time BatteryExternalStatsWorker
835      * gives us data, we mustn't process it since this data includes pre-reset-period data.
836      */
837     @GuardedBy("this")
838     boolean mIgnoreNextExternalStats = false;
839 
840     long mStartClockTimeMs;
841     String mStartPlatformVersion;
842     String mEndPlatformVersion;
843 
844     long mUptimeUs;
845     long mUptimeStartUs;
846     long mRealtimeUs;
847     long mRealtimeStartUs;
848 
849     int mWakeLockNesting;
850     boolean mWakeLockImportant;
851     public boolean mRecordAllHistory;
852     boolean mNoAutoReset;
853 
854     /**
855      * Overall screen state. For multidisplay devices, this represents the current highest screen
856      * state of the displays.
857      */
858     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
859     protected int mScreenState = Display.STATE_UNKNOWN;
860     /**
861      * Overall screen on timer. For multidisplay devices, this represents the time spent with at
862      * least one display in the screen on state.
863      */
864     StopwatchTimer mScreenOnTimer;
865     /**
866      * Overall screen doze timer. For multidisplay devices, this represents the time spent with
867      * screen doze being the highest screen state.
868      */
869     StopwatchTimer mScreenDozeTimer;
870     /**
871      * Overall screen brightness bin. For multidisplay devices, this represents the current
872      * brightest screen.
873      */
874     int mScreenBrightnessBin = -1;
875     /**
876      * Overall screen brightness timers. For multidisplay devices, the {@link mScreenBrightnessBin}
877      * timer will be active at any given time
878      */
879     final StopwatchTimer[] mScreenBrightnessTimer =
880             new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
881 
882     boolean mPretendScreenOff;
883 
884     private static class DisplayBatteryStats {
885         /**
886          * Per display screen state.
887          */
888         public int screenState = Display.STATE_UNKNOWN;
889         /**
890          * Per display screen on timers.
891          */
892         public StopwatchTimer screenOnTimer;
893         /**
894          * Per display screen doze timers.
895          */
896         public StopwatchTimer screenDozeTimer;
897         /**
898          * Per display screen brightness bins.
899          */
900         public int screenBrightnessBin = -1;
901         /**
902          * Per display screen brightness timers.
903          */
904         public StopwatchTimer[] screenBrightnessTimers =
905                 new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
906         /**
907          * Per display screen state the last time {@link #updateDisplayMeasuredEnergyStatsLocked}
908          * was called.
909          */
910         public int screenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
911 
DisplayBatteryStats(Clocks clocks, TimeBase timeBase)912         DisplayBatteryStats(Clocks clocks, TimeBase timeBase) {
913             screenOnTimer = new StopwatchTimer(clocks, null, -1, null,
914                     timeBase);
915             screenDozeTimer = new StopwatchTimer(clocks, null, -1, null,
916                     timeBase);
917             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
918                 screenBrightnessTimers[i] = new StopwatchTimer(clocks, null, -100 - i, null,
919                         timeBase);
920             }
921         }
922 
923         /**
924          * Reset display timers.
925          */
reset(long elapsedRealtimeUs)926         public void reset(long elapsedRealtimeUs) {
927             screenOnTimer.reset(false, elapsedRealtimeUs);
928             screenDozeTimer.reset(false, elapsedRealtimeUs);
929             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
930                 screenBrightnessTimers[i].reset(false, elapsedRealtimeUs);
931             }
932         }
933     }
934 
935     DisplayBatteryStats[] mPerDisplayBatteryStats;
936 
937     private int mDisplayMismatchWtfCount = 0;
938 
939     boolean mInteractive;
940     StopwatchTimer mInteractiveTimer;
941 
942     boolean mPowerSaveModeEnabled;
943     StopwatchTimer mPowerSaveModeEnabledTimer;
944 
945     boolean mDeviceIdling;
946     StopwatchTimer mDeviceIdlingTimer;
947 
948     boolean mDeviceLightIdling;
949     StopwatchTimer mDeviceLightIdlingTimer;
950 
951     int mDeviceIdleMode;
952     long mLastIdleTimeStartMs;
953     long mLongestLightIdleTimeMs;
954     long mLongestFullIdleTimeMs;
955     StopwatchTimer mDeviceIdleModeLightTimer;
956     StopwatchTimer mDeviceIdleModeFullTimer;
957 
958     boolean mPhoneOn;
959     StopwatchTimer mPhoneOnTimer;
960 
961     int mAudioOnNesting;
962     StopwatchTimer mAudioOnTimer;
963 
964     int mVideoOnNesting;
965     StopwatchTimer mVideoOnTimer;
966 
967     int mFlashlightOnNesting;
968     StopwatchTimer mFlashlightOnTimer;
969 
970     int mCameraOnNesting;
971     StopwatchTimer mCameraOnTimer;
972 
973     private static final int USB_DATA_UNKNOWN = 0;
974     private static final int USB_DATA_DISCONNECTED = 1;
975     private static final int USB_DATA_CONNECTED = 2;
976     int mUsbDataState = USB_DATA_UNKNOWN;
977 
978     int mGpsSignalQualityBin = -1;
979     final StopwatchTimer[] mGpsSignalQualityTimer =
980         new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
981 
982     int mPhoneSignalStrengthBin = -1;
983     int mPhoneSignalStrengthBinRaw = -1;
984     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
985             new StopwatchTimer[CellSignalStrength.getNumSignalStrengthLevels()];
986 
987     StopwatchTimer mPhoneSignalScanningTimer;
988 
989     int mPhoneDataConnectionType = -1;
990     final StopwatchTimer[] mPhoneDataConnectionsTimer =
991             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
992 
993     final LongSamplingCounter[] mNetworkByteActivityCounters =
994             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
995 
996     final LongSamplingCounter[] mNetworkPacketActivityCounters =
997             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
998 
999     /**
1000      * The WiFi Overall wakelock timer
1001      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
1002      * since addition of per UID timers would not result in an accurate value due to overlapp of
1003      * per uid wakelock timers
1004      */
1005     StopwatchTimer mWifiMulticastWakelockTimer;
1006 
1007     /**
1008      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
1009      */
1010     ControllerActivityCounterImpl mWifiActivity;
1011 
1012     /**
1013      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
1014      */
1015     ControllerActivityCounterImpl mBluetoothActivity;
1016 
1017     /**
1018      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
1019      */
1020     ControllerActivityCounterImpl mModemActivity;
1021 
1022     /**
1023      * Whether the device supports WiFi controller energy reporting. This is set to true on
1024      * the first WiFi energy report. See {@link #mWifiActivity}.
1025      */
1026     boolean mHasWifiReporting = false;
1027 
1028     /**
1029      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
1030      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
1031      */
1032     boolean mHasBluetoothReporting = false;
1033 
1034     /**
1035      * Whether the device supports Modem controller energy reporting. This is set to true on
1036      * the first Modem energy report. See {@link #mModemActivity}.
1037      */
1038     boolean mHasModemReporting = false;
1039 
1040     boolean mWifiOn;
1041     StopwatchTimer mWifiOnTimer;
1042 
1043     boolean mGlobalWifiRunning;
1044     StopwatchTimer mGlobalWifiRunningTimer;
1045 
1046     int mWifiState = -1;
1047     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
1048 
1049     int mWifiSupplState = -1;
1050     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
1051 
1052     int mWifiSignalStrengthBin = -1;
1053     final StopwatchTimer[] mWifiSignalStrengthsTimer =
1054             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
1055 
1056     StopwatchTimer mWifiActiveTimer;
1057 
1058     int mBluetoothScanNesting;
1059     StopwatchTimer mBluetoothScanTimer;
1060 
1061     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1062     long mMobileRadioActiveStartTimeMs;
1063     StopwatchTimer mMobileRadioActiveTimer;
1064     StopwatchTimer mMobileRadioActivePerAppTimer;
1065     LongSamplingCounter mMobileRadioActiveAdjustedTime;
1066     LongSamplingCounter mMobileRadioActiveUnknownTime;
1067     LongSamplingCounter mMobileRadioActiveUnknownCount;
1068 
1069     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1070 
1071     /**
1072      * Accumulated global (generally, device-wide total) charge consumption of various consumers
1073      * while on battery.
1074      * Its '<b>custom</b> power buckets' correspond to the
1075      * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
1076      * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
1077      *
1078      * If energy consumer data is completely unavailable this will be null.
1079      */
1080     @GuardedBy("this")
1081     @VisibleForTesting
1082     protected @Nullable MeasuredEnergyStats mGlobalMeasuredEnergyStats;
1083     /** Bluetooth Power calculator for attributing measured bluetooth charge consumption to uids */
1084     @Nullable BluetoothPowerCalculator mBluetoothPowerCalculator = null;
1085     /** Cpu Power calculator for attributing measured cpu charge consumption to uids */
1086     @Nullable CpuPowerCalculator mCpuPowerCalculator = null;
1087     /** Mobile Radio Power calculator for attributing measured radio charge consumption to uids */
1088     @Nullable
1089     MobileRadioPowerCalculator mMobileRadioPowerCalculator = null;
1090     /** Wifi Power calculator for attributing measured wifi charge consumption to uids */
1091     @Nullable WifiPowerCalculator mWifiPowerCalculator = null;
1092 
1093     /**
1094      * These provide time bases that discount the time the device is plugged
1095      * in to power.
1096      */
1097     boolean mOnBattery;
1098     @VisibleForTesting
1099     protected boolean mOnBatteryInternal;
1100 
1101     /**
1102      * External reporting of whether the device is actually charging.
1103      */
1104     boolean mCharging = true;
1105     int mLastChargingStateLevel;
1106 
1107     /*
1108      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
1109      */
1110     int mDischargeStartLevel;
1111     int mDischargeUnplugLevel;
1112     int mDischargePlugLevel;
1113     int mDischargeCurrentLevel;
1114     int mCurrentBatteryLevel;
1115     int mLowDischargeAmountSinceCharge;
1116     int mHighDischargeAmountSinceCharge;
1117     int mDischargeScreenOnUnplugLevel;
1118     int mDischargeScreenOffUnplugLevel;
1119     int mDischargeScreenDozeUnplugLevel;
1120     int mDischargeAmountScreenOn;
1121     int mDischargeAmountScreenOnSinceCharge;
1122     int mDischargeAmountScreenOff;
1123     int mDischargeAmountScreenOffSinceCharge;
1124     int mDischargeAmountScreenDoze;
1125     int mDischargeAmountScreenDozeSinceCharge;
1126 
1127     private LongSamplingCounter mDischargeScreenOffCounter;
1128     private LongSamplingCounter mDischargeScreenDozeCounter;
1129     private LongSamplingCounter mDischargeCounter;
1130     private LongSamplingCounter mDischargeLightDozeCounter;
1131     private LongSamplingCounter mDischargeDeepDozeCounter;
1132 
1133     static final int MAX_LEVEL_STEPS = 200;
1134 
1135     int mInitStepMode = 0;
1136     int mCurStepMode = 0;
1137     int mModStepMode = 0;
1138 
1139     int mLastDischargeStepLevel;
1140     int mMinDischargeStepLevel;
1141     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1142     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1143     ArrayList<PackageChange> mDailyPackageChanges;
1144 
1145     int mLastChargeStepLevel;
1146     int mMaxChargeStepLevel;
1147     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1148     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1149 
1150     static final int MAX_DAILY_ITEMS = 10;
1151 
1152     long mDailyStartTimeMs = 0;
1153     long mNextMinDailyDeadlineMs = 0;
1154     long mNextMaxDailyDeadlineMs = 0;
1155 
1156     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
1157 
1158     long mLastWriteTimeMs = 0; // Milliseconds
1159 
1160     private int mPhoneServiceState = -1;
1161     private int mPhoneServiceStateRaw = -1;
1162     private int mPhoneSimStateRaw = -1;
1163 
1164     private int mNumConnectivityChange;
1165 
1166     private int mBatteryVoltageMv = -1;
1167     private int mEstimatedBatteryCapacityMah = -1;
1168 
1169     private int mLastLearnedBatteryCapacityUah = -1;
1170     private int mMinLearnedBatteryCapacityUah = -1;
1171     private int mMaxLearnedBatteryCapacityUah = -1;
1172 
1173     private long mBatteryTimeToFullSeconds = -1;
1174 
1175     private long[] mCpuFreqs;
1176 
1177     /**
1178      * Times spent by the system server threads handling incoming binder requests.
1179      */
1180     private LongSamplingCounterArray mBinderThreadCpuTimesUs;
1181 
1182     @VisibleForTesting
1183     protected PowerProfile mPowerProfile;
1184 
1185     @VisibleForTesting
1186     @GuardedBy("this")
1187     protected final Constants mConstants;
1188 
1189     /*
1190      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
1191      * recording their times when on-battery (regardless of screen state).
1192      */
1193     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
1194     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
1195     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
1196 
1197     @Override
getRpmStats()1198     public Map<String, ? extends Timer> getRpmStats() {
1199         return mRpmStats;
1200     }
1201 
1202     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
1203     @Override
getScreenOffRpmStats()1204     public Map<String, ? extends Timer> getScreenOffRpmStats() {
1205         return mScreenOffRpmStats;
1206     }
1207 
1208     /*
1209      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
1210      */
1211     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
1212 
1213     @UnsupportedAppUsage
getKernelWakelockStats()1214     public Map<String, ? extends Timer> getKernelWakelockStats() {
1215         return mKernelWakelockStats;
1216     }
1217 
1218     String mLastWakeupReason = null;
1219     long mLastWakeupUptimeMs = 0;
1220     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
1221 
getWakeupReasonStats()1222     public Map<String, ? extends Timer> getWakeupReasonStats() {
1223         return mWakeupReasonStats;
1224     }
1225 
1226     @Override
getUahDischarge(int which)1227     public long getUahDischarge(int which) {
1228         return mDischargeCounter.getCountLocked(which);
1229     }
1230 
1231     @Override
getUahDischargeScreenOff(int which)1232     public long getUahDischargeScreenOff(int which) {
1233         return mDischargeScreenOffCounter.getCountLocked(which);
1234     }
1235 
1236     @Override
getUahDischargeScreenDoze(int which)1237     public long getUahDischargeScreenDoze(int which) {
1238         return mDischargeScreenDozeCounter.getCountLocked(which);
1239     }
1240 
1241     @Override
getUahDischargeLightDoze(int which)1242     public long getUahDischargeLightDoze(int which) {
1243         return mDischargeLightDozeCounter.getCountLocked(which);
1244     }
1245 
1246     @Override
getUahDischargeDeepDoze(int which)1247     public long getUahDischargeDeepDoze(int which) {
1248         return mDischargeDeepDozeCounter.getCountLocked(which);
1249     }
1250 
1251     @Override
getEstimatedBatteryCapacity()1252     public int getEstimatedBatteryCapacity() {
1253         return mEstimatedBatteryCapacityMah;
1254     }
1255 
1256     @Override
getLearnedBatteryCapacity()1257     public int getLearnedBatteryCapacity() {
1258         return mLastLearnedBatteryCapacityUah;
1259     }
1260 
1261     @Override
getMinLearnedBatteryCapacity()1262     public int getMinLearnedBatteryCapacity() {
1263         return mMinLearnedBatteryCapacityUah;
1264     }
1265 
1266     @Override
getMaxLearnedBatteryCapacity()1267     public int getMaxLearnedBatteryCapacity() {
1268         return mMaxLearnedBatteryCapacityUah;
1269     }
1270 
BatteryStatsImpl()1271     public BatteryStatsImpl() {
1272         this(new SystemClocks());
1273     }
1274 
BatteryStatsImpl(Clocks clocks)1275     public BatteryStatsImpl(Clocks clocks) {
1276         init(clocks);
1277         mStartClockTimeMs = clocks.currentTimeMillis();
1278         mStatsFile = null;
1279         mCheckinFile = null;
1280         mDailyFile = null;
1281         mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
1282         mHandler = null;
1283         mPlatformIdleStateCallback = null;
1284         mMeasuredEnergyRetriever = null;
1285         mUserInfoProvider = null;
1286         mConstants = new Constants(mHandler);
1287         clearHistoryLocked();
1288     }
1289 
init(Clocks clocks)1290     private void init(Clocks clocks) {
1291         mClocks = clocks;
1292     }
1293 
1294     /**
1295      * TimeBase observer.
1296      */
1297     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1298         void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1299         void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
1300 
1301         /**
1302          * Reset the observer's state, returns true if the timer/counter is inactive
1303          * so it can be destroyed.
1304          * @param detachIfReset detach if true, no-op if false.
1305          * @return Returns true if the timer/counter is inactive and can be destroyed.
1306          */
reset(boolean detachIfReset)1307         default boolean reset(boolean detachIfReset) {
1308             return reset(detachIfReset, SystemClock.elapsedRealtime() * 1000);
1309         }
1310 
1311         /**
1312          * @see #reset(boolean)
1313          * @param detachIfReset detach if true, no-op if false.
1314          * @param elapsedRealtimeUs the timestamp when this reset is actually reequested
1315          * @return Returns true if the timer/counter is inactive and can be destroyed.
1316          */
reset(boolean detachIfReset, long elapsedRealtimeUs)1317         boolean reset(boolean detachIfReset, long elapsedRealtimeUs);
1318 
1319         /**
1320          * Detach the observer from TimeBase.
1321          */
detach()1322         void detach();
1323     }
1324 
1325     // methods are protected not private to be VisibleForTesting
1326     public static class TimeBase {
1327         protected final Collection<TimeBaseObs> mObservers;
1328 
1329         // All below time metrics are in microseconds.
1330         protected long mUptimeUs;
1331         protected long mRealtimeUs;
1332 
1333         protected boolean mRunning;
1334 
1335         protected long mPastUptimeUs;
1336         protected long mUptimeStartUs;
1337         protected long mPastRealtimeUs;
1338         protected long mRealtimeStartUs;
1339         protected long mUnpluggedUptimeUs;
1340         protected long mUnpluggedRealtimeUs;
1341 
dump(PrintWriter pw, String prefix)1342         public void dump(PrintWriter pw, String prefix) {
1343             StringBuilder sb = new StringBuilder(128);
1344             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
1345             sb.setLength(0);
1346             sb.append(prefix);
1347                     sb.append("mUptime=");
1348                     formatTimeMs(sb, mUptimeUs / 1000);
1349             pw.println(sb.toString());
1350             sb.setLength(0);
1351             sb.append(prefix);
1352                     sb.append("mRealtime=");
1353                     formatTimeMs(sb, mRealtimeUs / 1000);
1354             pw.println(sb.toString());
1355             sb.setLength(0);
1356             sb.append(prefix);
1357                     sb.append("mPastUptime=");
1358                     formatTimeMs(sb, mPastUptimeUs / 1000); sb.append("mUptimeStart=");
1359                     formatTimeMs(sb, mUptimeStartUs / 1000);
1360                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptimeUs / 1000);
1361             pw.println(sb.toString());
1362             sb.setLength(0);
1363             sb.append(prefix);
1364                     sb.append("mPastRealtime=");
1365                     formatTimeMs(sb, mPastRealtimeUs / 1000); sb.append("mRealtimeStart=");
1366                     formatTimeMs(sb, mRealtimeStartUs / 1000);
1367                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtimeUs / 1000);
1368             pw.println(sb.toString());
1369         }
1370         /**
1371          * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
1372          * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
1373          * entries.
1374          * mObservers must have good performance on add(), remove(), also be memory efficient.
1375          * This is why we provide isLongList parameter for long and short list user cases.
1376          * @param isLongList If true, use HashSet for mObservers list.
1377          *                   If false, use ArrayList for mObservers list.
1378         */
TimeBase(boolean isLongList)1379         public TimeBase(boolean isLongList) {
1380             mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
1381         }
1382 
TimeBase()1383         public TimeBase() {
1384             this(false);
1385         }
1386 
add(TimeBaseObs observer)1387         public void add(TimeBaseObs observer) {
1388             mObservers.add(observer);
1389         }
1390 
remove(TimeBaseObs observer)1391         public void remove(TimeBaseObs observer) {
1392             mObservers.remove(observer);
1393         }
1394 
hasObserver(TimeBaseObs observer)1395         public boolean hasObserver(TimeBaseObs observer) {
1396             return mObservers.contains(observer);
1397         }
1398 
init(long uptimeUs, long elapsedRealtimeUs)1399         public void init(long uptimeUs, long elapsedRealtimeUs) {
1400             mRealtimeUs = 0;
1401             mUptimeUs = 0;
1402             mPastUptimeUs = 0;
1403             mPastRealtimeUs = 0;
1404             mUptimeStartUs = uptimeUs;
1405             mRealtimeStartUs = elapsedRealtimeUs;
1406             mUnpluggedUptimeUs = getUptime(mUptimeStartUs);
1407             mUnpluggedRealtimeUs = getRealtime(mRealtimeStartUs);
1408         }
1409 
reset(long uptimeUs, long elapsedRealtimeUs)1410         public void reset(long uptimeUs, long elapsedRealtimeUs) {
1411             if (!mRunning) {
1412                 mPastUptimeUs = 0;
1413                 mPastRealtimeUs = 0;
1414             } else {
1415                 mUptimeStartUs = uptimeUs;
1416                 mRealtimeStartUs = elapsedRealtimeUs;
1417                 // TODO: Since mUptimeStartUs was just reset and we are running, getUptime will
1418                 // just return mPastUptimeUs. Also, are we sure we don't want to reset that?
1419                 mUnpluggedUptimeUs = getUptime(uptimeUs);
1420                 // TODO: likewise.
1421                 mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
1422             }
1423         }
1424 
computeUptime(long curTimeUs, int which)1425         public long computeUptime(long curTimeUs, int which) {
1426             return mUptimeUs + getUptime(curTimeUs);
1427         }
1428 
computeRealtime(long curTimeUs, int which)1429         public long computeRealtime(long curTimeUs, int which) {
1430             return mRealtimeUs + getRealtime(curTimeUs);
1431         }
1432 
getUptime(long curTimeUs)1433         public long getUptime(long curTimeUs) {
1434             long time = mPastUptimeUs;
1435             if (mRunning) {
1436                 time += curTimeUs - mUptimeStartUs;
1437             }
1438             return time;
1439         }
1440 
getRealtime(long curTimeUs)1441         public long getRealtime(long curTimeUs) {
1442             long time = mPastRealtimeUs;
1443             if (mRunning) {
1444                 time += curTimeUs - mRealtimeStartUs;
1445             }
1446             return time;
1447         }
1448 
getUptimeStart()1449         public long getUptimeStart() {
1450             return mUptimeStartUs;
1451         }
1452 
getRealtimeStart()1453         public long getRealtimeStart() {
1454             return mRealtimeStartUs;
1455         }
1456 
isRunning()1457         public boolean isRunning() {
1458             return mRunning;
1459         }
1460 
setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs)1461         public boolean setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs) {
1462             if (mRunning != running) {
1463                 mRunning = running;
1464                 if (running) {
1465                     mUptimeStartUs = uptimeUs;
1466                     mRealtimeStartUs = elapsedRealtimeUs;
1467                     long batteryUptimeUs = mUnpluggedUptimeUs = getUptime(uptimeUs);
1468                     long batteryRealtimeUs = mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
1469                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1470                     // Iterator object, here is an exception because mObservers' type is Collection
1471                     // instead of list.
1472                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1473                     while (iter.hasNext()) {
1474                         iter.next().onTimeStarted(
1475                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
1476                     }
1477                 } else {
1478                     mPastUptimeUs += uptimeUs - mUptimeStartUs;
1479                     mPastRealtimeUs += elapsedRealtimeUs - mRealtimeStartUs;
1480                     long batteryUptimeUs = getUptime(uptimeUs);
1481                     long batteryRealtimeUs = getRealtime(elapsedRealtimeUs);
1482                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1483                     // Iterator object, here is an exception because mObservers' type is Collection
1484                     // instead of list.
1485                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1486                     while (iter.hasNext()) {
1487                         iter.next().onTimeStopped(
1488                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
1489                     }
1490                 }
1491                 return true;
1492             }
1493             return false;
1494         }
1495 
readSummaryFromParcel(Parcel in)1496         public void readSummaryFromParcel(Parcel in) {
1497             mUptimeUs = in.readLong();
1498             mRealtimeUs = in.readLong();
1499         }
1500 
writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)1501         public void writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
1502             out.writeLong(computeUptime(uptimeUs, STATS_SINCE_CHARGED));
1503             out.writeLong(computeRealtime(elapsedRealtimeUs, STATS_SINCE_CHARGED));
1504         }
1505 
readFromParcel(Parcel in)1506         public void readFromParcel(Parcel in) {
1507             mRunning = false;
1508             mUptimeUs = in.readLong();
1509             mPastUptimeUs = in.readLong();
1510             mUptimeStartUs = in.readLong();
1511             mRealtimeUs = in.readLong();
1512             mPastRealtimeUs = in.readLong();
1513             mRealtimeStartUs = in.readLong();
1514             mUnpluggedUptimeUs = in.readLong();
1515             mUnpluggedRealtimeUs = in.readLong();
1516         }
1517 
writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)1518         public void writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
1519             final long runningUptime = getUptime(uptimeUs);
1520             final long runningRealtime = getRealtime(elapsedRealtimeUs);
1521             out.writeLong(mUptimeUs);
1522             out.writeLong(runningUptime);
1523             out.writeLong(mUptimeStartUs);
1524             out.writeLong(mRealtimeUs);
1525             out.writeLong(runningRealtime);
1526             out.writeLong(mRealtimeStartUs);
1527             out.writeLong(mUnpluggedUptimeUs);
1528             out.writeLong(mUnpluggedRealtimeUs);
1529         }
1530     }
1531 
1532     /**
1533      * State for keeping track of counting information.
1534      */
1535     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
1536         @UnsupportedAppUsage
1537         final AtomicInteger mCount = new AtomicInteger();
1538         final TimeBase mTimeBase;
1539 
Counter(TimeBase timeBase, Parcel in)1540         public Counter(TimeBase timeBase, Parcel in) {
1541             mTimeBase = timeBase;
1542             mCount.set(in.readInt());
1543             timeBase.add(this);
1544         }
1545 
Counter(TimeBase timeBase)1546         public Counter(TimeBase timeBase) {
1547             mTimeBase = timeBase;
1548             timeBase.add(this);
1549         }
1550 
writeToParcel(Parcel out)1551         public void writeToParcel(Parcel out) {
1552             out.writeInt(mCount.get());
1553         }
1554 
1555         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1556         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1557         }
1558 
1559         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1560         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1561         }
1562 
1563         /**
1564          * Writes a possibly null Counter to a Parcel.
1565          *
1566          * @param out the Parcel to be written to.
1567          * @param counter a Counter, or null.
1568          */
writeCounterToParcel(Parcel out, @Nullable Counter counter)1569         public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
1570             if (counter == null) {
1571                 out.writeInt(0); // indicates null
1572                 return;
1573             }
1574             out.writeInt(1); // indicates non-null
1575 
1576             counter.writeToParcel(out);
1577         }
1578 
1579         /**
1580          * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
1581          * @param timeBase the timebase to assign to the Counter
1582          * @param in the parcel to read from
1583          * @return the Counter or null.
1584          */
1585         @Nullable
readCounterFromParcel(TimeBase timeBase, Parcel in)1586         public static Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
1587             if (in.readInt() == 0) {
1588                 return null;
1589             }
1590             return new Counter(timeBase, in);
1591         }
1592 
1593         @Override
getCountLocked(int which)1594         public int getCountLocked(int which) {
1595             return mCount.get();
1596         }
1597 
logState(Printer pw, String prefix)1598         public void logState(Printer pw, String prefix) {
1599             pw.println(prefix + "mCount=" + mCount.get());
1600         }
1601 
1602         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()1603         public void stepAtomic() {
1604             if (mTimeBase.isRunning()) {
1605                 mCount.incrementAndGet();
1606             }
1607         }
1608 
addAtomic(int delta)1609         void addAtomic(int delta) {
1610             if (mTimeBase.isRunning()) {
1611                 mCount.addAndGet(delta);
1612             }
1613         }
1614 
1615         /**
1616          * Clear state of this counter.
1617          */
1618         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )1619         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
1620             mCount.set(0);
1621             if (detachIfReset) {
1622                 detach();
1623             }
1624             return true;
1625         }
1626 
1627         @Override
detach()1628         public void detach() {
1629             mTimeBase.remove(this);
1630         }
1631 
1632         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)1633         public void writeSummaryFromParcelLocked(Parcel out) {
1634             out.writeInt(mCount.get());
1635         }
1636 
1637         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)1638         public void readSummaryFromParcelLocked(Parcel in) {
1639             mCount.set(in.readInt());
1640         }
1641     }
1642 
1643     @VisibleForTesting
1644     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
1645         final TimeBase mTimeBase;
1646         public long[] mCounts;
1647 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)1648         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
1649             mTimeBase = timeBase;
1650             mCounts = in.createLongArray();
1651             timeBase.add(this);
1652         }
1653 
LongSamplingCounterArray(TimeBase timeBase)1654         public LongSamplingCounterArray(TimeBase timeBase) {
1655             mTimeBase = timeBase;
1656             timeBase.add(this);
1657         }
1658 
writeToParcel(Parcel out)1659         private void writeToParcel(Parcel out) {
1660             out.writeLongArray(mCounts);
1661         }
1662 
1663         @Override
onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs)1664         public void onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs) {
1665         }
1666 
1667         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1668         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1669         }
1670 
1671         @Override
getCountsLocked(int which)1672         public long[] getCountsLocked(int which) {
1673             return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
1674         }
1675 
1676         @Override
logState(Printer pw, String prefix)1677         public void logState(Printer pw, String prefix) {
1678             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
1679         }
1680 
addCountLocked(long[] counts)1681         public void addCountLocked(long[] counts) {
1682             addCountLocked(counts, mTimeBase.isRunning());
1683         }
1684 
addCountLocked(long[] counts, boolean isRunning)1685         public void addCountLocked(long[] counts, boolean isRunning) {
1686             if (counts == null) {
1687                 return;
1688             }
1689             if (isRunning) {
1690                 if (mCounts == null) {
1691                     mCounts = new long[counts.length];
1692                 }
1693                 for (int i = 0; i < counts.length; ++i) {
1694                     mCounts[i] += counts[i];
1695                 }
1696             }
1697         }
1698 
getSize()1699         public int getSize() {
1700             return mCounts == null ? 0 : mCounts.length;
1701         }
1702 
1703         /**
1704          * Clear state of this counter.
1705          */
1706         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )1707         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
1708             if (mCounts != null) {
1709                 Arrays.fill(mCounts, 0);
1710             }
1711             if (detachIfReset) {
1712                 detach();
1713             }
1714             return true;
1715         }
1716 
1717         @Override
detach()1718         public void detach() {
1719             mTimeBase.remove(this);
1720         }
1721 
writeSummaryToParcelLocked(Parcel out)1722         private void writeSummaryToParcelLocked(Parcel out) {
1723             out.writeLongArray(mCounts);
1724         }
1725 
readSummaryFromParcelLocked(Parcel in)1726         private void readSummaryFromParcelLocked(Parcel in) {
1727             mCounts = in.createLongArray();
1728         }
1729 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)1730         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
1731             if (counterArray != null) {
1732                 out.writeInt(1);
1733                 counterArray.writeToParcel(out);
1734             } else {
1735                 out.writeInt(0);
1736             }
1737         }
1738 
readFromParcel(Parcel in, TimeBase timeBase)1739         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
1740             if (in.readInt() != 0) {
1741                 return new LongSamplingCounterArray(timeBase, in);
1742             } else {
1743                 return null;
1744             }
1745         }
1746 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)1747         public static void writeSummaryToParcelLocked(Parcel out,
1748                 LongSamplingCounterArray counterArray) {
1749             if (counterArray != null) {
1750                 out.writeInt(1);
1751                 counterArray.writeSummaryToParcelLocked(out);
1752             } else {
1753                 out.writeInt(0);
1754             }
1755         }
1756 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)1757         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
1758                 TimeBase timeBase) {
1759             if (in.readInt() != 0) {
1760                 final LongSamplingCounterArray counterArray
1761                         = new LongSamplingCounterArray(timeBase);
1762                 counterArray.readSummaryFromParcelLocked(in);
1763                 return counterArray;
1764             } else {
1765                 return null;
1766             }
1767         }
1768     }
1769 
1770     @VisibleForTesting
1771     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
1772         final TimeBase mTimeBase;
1773         private long mCount;
1774 
LongSamplingCounter(TimeBase timeBase, Parcel in)1775         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
1776             mTimeBase = timeBase;
1777             mCount = in.readLong();
1778             timeBase.add(this);
1779         }
1780 
LongSamplingCounter(TimeBase timeBase)1781         public LongSamplingCounter(TimeBase timeBase) {
1782             mTimeBase = timeBase;
1783             timeBase.add(this);
1784         }
1785 
writeToParcel(Parcel out)1786         public void writeToParcel(Parcel out) {
1787             out.writeLong(mCount);
1788         }
1789 
1790         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1791         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1792         }
1793 
1794         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1795         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1796         }
1797 
getCountLocked(int which)1798         public long getCountLocked(int which) {
1799             return mCount;
1800         }
1801 
1802         @Override
logState(Printer pw, String prefix)1803         public void logState(Printer pw, String prefix) {
1804             pw.println(prefix + "mCount=" + mCount);
1805         }
1806 
addCountLocked(long count)1807         public void addCountLocked(long count) {
1808             addCountLocked(count, mTimeBase.isRunning());
1809         }
1810 
addCountLocked(long count, boolean isRunning)1811         public void addCountLocked(long count, boolean isRunning) {
1812             if (isRunning) {
1813                 mCount += count;
1814             }
1815         }
1816 
1817         /**
1818          * Clear state of this counter.
1819          */
1820         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )1821         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
1822             mCount = 0;
1823             if (detachIfReset) {
1824                 detach();
1825             }
1826             return true;
1827         }
1828 
1829         @Override
detach()1830         public void detach() {
1831             mTimeBase.remove(this);
1832         }
1833 
writeSummaryFromParcelLocked(Parcel out)1834         public void writeSummaryFromParcelLocked(Parcel out) {
1835             out.writeLong(mCount);
1836         }
1837 
readSummaryFromParcelLocked(Parcel in)1838         public void readSummaryFromParcelLocked(Parcel in) {
1839             mCount = in.readLong();
1840         }
1841     }
1842 
1843     /**
1844      * State for keeping track of timing information.
1845      */
1846     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
1847         protected final Clocks mClocks;
1848         protected final int mType;
1849         protected final TimeBase mTimeBase;
1850 
1851         protected int mCount;
1852 
1853         // Times are in microseconds for better accuracy when dividing by the
1854         // lock count, and are in "battery realtime" units.
1855 
1856         /**
1857          * The total time we have accumulated since the start of the original
1858          * boot, to the last time something interesting happened in the
1859          * current run.
1860          */
1861         protected long mTotalTimeUs;
1862 
1863         /**
1864          * The total time this timer has been running until the latest mark has been set.
1865          * Subtract this from mTotalTimeUs to get the time spent running since the mark was set.
1866          */
1867         protected long mTimeBeforeMarkUs;
1868 
1869         /**
1870          * Constructs from a parcel.
1871          * @param type
1872          * @param timeBase
1873          * @param in
1874          */
Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in)1875         public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
1876             mClocks = clocks;
1877             mType = type;
1878             mTimeBase = timeBase;
1879 
1880             mCount = in.readInt();
1881             mTotalTimeUs = in.readLong();
1882             mTimeBeforeMarkUs = in.readLong();
1883             timeBase.add(this);
1884             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTimeUs);
1885         }
1886 
Timer(Clocks clocks, int type, TimeBase timeBase)1887         public Timer(Clocks clocks, int type, TimeBase timeBase) {
1888             mClocks = clocks;
1889             mType = type;
1890             mTimeBase = timeBase;
1891             timeBase.add(this);
1892         }
1893 
writeToParcel(Parcel out, long elapsedRealtimeUs)1894         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1895             if (DEBUG) {
1896                 Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
1897                         + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
1898                                 elapsedRealtimeUs));
1899             }
1900             out.writeInt(computeCurrentCountLocked());
1901             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
1902                         elapsedRealtimeUs));
1903             out.writeLong(mTimeBeforeMarkUs);
1904         }
1905 
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)1906         protected abstract long computeRunTimeLocked(long curBatteryRealtime,
1907                 long elapsedRealtimeUs);
1908 
computeCurrentCountLocked()1909         protected abstract int computeCurrentCountLocked();
1910 
1911         /**
1912          * Clear state of this timer.  Returns true if the timer is inactive
1913          * so can be completely dropped.
1914          */
1915         @Override
reset(boolean detachIfReset)1916         public boolean reset(boolean detachIfReset) {
1917             return reset(detachIfReset, mClocks.elapsedRealtime() * 1000);
1918         }
1919 
1920         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )1921         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
1922             mTotalTimeUs = mTimeBeforeMarkUs = 0;
1923             mCount = 0;
1924             if (detachIfReset) {
1925                 detach();
1926             }
1927             return true;
1928         }
1929 
1930         @Override
detach()1931         public void detach() {
1932             mTimeBase.remove(this);
1933         }
1934 
1935         @Override
onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs, long baseRealtimeUs)1936         public void onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs,
1937                 long baseRealtimeUs) {
1938         }
1939 
1940         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1941         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1942             if (DEBUG && mType < 0) {
1943                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtimeUs
1944                         + " old mTotalTime=" + mTotalTimeUs);
1945             }
1946             mTotalTimeUs = computeRunTimeLocked(baseRealtimeUs, elapsedRealtimeUs);
1947             mCount = computeCurrentCountLocked();
1948             if (DEBUG && mType < 0) {
1949                 Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTimeUs);
1950             }
1951         }
1952 
1953         /**
1954          * Writes a possibly null Timer to a Parcel.
1955          *
1956          * @param out the Parcel to be written to.
1957          * @param timer a Timer, or null.
1958          */
1959         @UnsupportedAppUsage
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)1960         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
1961             if (timer == null) {
1962                 out.writeInt(0); // indicates null
1963                 return;
1964             }
1965             out.writeInt(1); // indicates non-null
1966             timer.writeToParcel(out, elapsedRealtimeUs);
1967         }
1968 
1969         @Override
1970         @UnsupportedAppUsage
getTotalTimeLocked(long elapsedRealtimeUs, int which)1971         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
1972             return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
1973                     elapsedRealtimeUs);
1974         }
1975 
1976         @Override
1977         @UnsupportedAppUsage
getCountLocked(int which)1978         public int getCountLocked(int which) {
1979             return computeCurrentCountLocked();
1980         }
1981 
1982         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)1983         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
1984             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
1985                     elapsedRealtimeUs);
1986             return val - mTimeBeforeMarkUs;
1987         }
1988 
1989         @Override
logState(Printer pw, String prefix)1990         public void logState(Printer pw, String prefix) {
1991             pw.println(prefix + "mCount=" + mCount);
1992             pw.println(prefix + "mTotalTime=" + mTotalTimeUs);
1993         }
1994 
1995 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)1996         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1997             long runTimeUs = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
1998                     elapsedRealtimeUs);
1999             out.writeLong(runTimeUs);
2000             out.writeInt(computeCurrentCountLocked());
2001         }
2002 
readSummaryFromParcelLocked(Parcel in)2003         public void readSummaryFromParcelLocked(Parcel in) {
2004             // Multiply by 1000 for backwards compatibility
2005             mTotalTimeUs = in.readLong();
2006             mCount = in.readInt();
2007             // When reading the summary, we set the mark to be the latest information.
2008             mTimeBeforeMarkUs = mTotalTimeUs;
2009         }
2010     }
2011 
2012     /**
2013      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
2014      * method. The state of the timer according to its {@link TimeBase} will determine how much
2015      * of the value is recorded.
2016      *
2017      * If the value being recorded resets, {@link #endSample()} can be called in order to
2018      * account for the change. If the value passed in to {@link #update(long, int)} decreased
2019      * between calls, the {@link #endSample()} is automatically called and the new value is
2020      * expected to increase monotonically from that point on.
2021      */
2022     public static class SamplingTimer extends Timer {
2023 
2024         /**
2025          * The most recent reported count from /proc/wakelocks.
2026          */
2027         int mCurrentReportedCount;
2028 
2029         /**
2030          * The reported count from /proc/wakelocks when unplug() was last
2031          * called.
2032          */
2033         int mUnpluggedReportedCount;
2034 
2035         /**
2036          * The most recent reported total_time from /proc/wakelocks.
2037          */
2038         long mCurrentReportedTotalTimeUs;
2039 
2040 
2041         /**
2042          * The reported total_time from /proc/wakelocks when unplug() was last
2043          * called.
2044          */
2045         long mUnpluggedReportedTotalTimeUs;
2046 
2047         /**
2048          * Whether we are currently in a discharge cycle.
2049          */
2050         boolean mTimeBaseRunning;
2051 
2052         /**
2053          * Whether we are currently recording reported values.
2054          */
2055         boolean mTrackingReportedValues;
2056 
2057         /*
2058          * A sequence counter, incremented once for each update of the stats.
2059          */
2060         int mUpdateVersion;
2061 
2062         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in)2063         public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
2064             super(clocks, 0, timeBase, in);
2065             mCurrentReportedCount = in.readInt();
2066             mUnpluggedReportedCount = in.readInt();
2067             mCurrentReportedTotalTimeUs = in.readLong();
2068             mUnpluggedReportedTotalTimeUs = in.readLong();
2069             mTrackingReportedValues = in.readInt() == 1;
2070             mTimeBaseRunning = timeBase.isRunning();
2071         }
2072 
2073         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase)2074         public SamplingTimer(Clocks clocks, TimeBase timeBase) {
2075             super(clocks, 0, timeBase);
2076             mTrackingReportedValues = false;
2077             mTimeBaseRunning = timeBase.isRunning();
2078         }
2079 
2080         /**
2081          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
2082          * be less than the values used for a previous invocation.
2083          */
endSample()2084         public void endSample() {
2085             endSample(mClocks.elapsedRealtime() * 1000);
2086         }
2087 
2088         /**
2089          * @see #endSample()
2090          */
endSample(long elapsedRealtimeUs)2091         public void endSample(long elapsedRealtimeUs) {
2092             mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs);
2093             mCount = computeCurrentCountLocked();
2094             mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0;
2095             mUnpluggedReportedCount = mCurrentReportedCount = 0;
2096             mTrackingReportedValues = false;
2097         }
2098 
setUpdateVersion(int version)2099         public void setUpdateVersion(int version) {
2100             mUpdateVersion = version;
2101         }
2102 
getUpdateVersion()2103         public int getUpdateVersion() {
2104             return mUpdateVersion;
2105         }
2106 
2107         /**
2108          * Updates the current recorded values. These are meant to be monotonically increasing
2109          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
2110          *
2111          * If the values being recorded have been reset, the monotonically increasing requirement
2112          * will be broken. In this case, {@link #endSample()} is automatically called and
2113          * the total value of totalTimeUs and count are recorded, starting a new monotonically
2114          * increasing sample.
2115          *
2116          * @param totalTimeUs total time of sample in microseconds.
2117          * @param count total number of times the event being sampled occurred.
2118          */
updated(long totalTimeUs, int count)2119         public void updated(long totalTimeUs, int count) {
2120             update(totalTimeUs, count, mClocks.elapsedRealtime() * 1000);
2121         }
2122 
2123         /**
2124          * @see #update(long, int)
2125          */
update(long totalTimeUs, int count, long elapsedRealtimeUs)2126         public void update(long totalTimeUs, int count, long elapsedRealtimeUs) {
2127             if (mTimeBaseRunning && !mTrackingReportedValues) {
2128                 // Updating the reported value for the first time.
2129                 mUnpluggedReportedTotalTimeUs = totalTimeUs;
2130                 mUnpluggedReportedCount = count;
2131             }
2132 
2133             mTrackingReportedValues = true;
2134 
2135             if (totalTimeUs < mCurrentReportedTotalTimeUs || count < mCurrentReportedCount) {
2136                 endSample(elapsedRealtimeUs);
2137             }
2138 
2139             mCurrentReportedTotalTimeUs = totalTimeUs;
2140             mCurrentReportedCount = count;
2141         }
2142 
2143         /**
2144          * Adds deltaTime and deltaCount to the current sample.
2145          *
2146          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
2147          * @param deltaCount additional number of times the event being sampled occurred.
2148          */
add(long deltaTimeUs, int deltaCount)2149         public void add(long deltaTimeUs, int deltaCount) {
2150             add(deltaTimeUs, deltaCount, mClocks.elapsedRealtime() * 1000);
2151         }
2152 
2153         /**
2154          * @see #add(long, int)
2155          */
add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs)2156         public void add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs) {
2157             update(mCurrentReportedTotalTimeUs + deltaTimeUs, mCurrentReportedCount + deltaCount,
2158                     elapsedRealtimeUs);
2159         }
2160 
2161         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2162         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2163             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2164             if (mTrackingReportedValues) {
2165                 mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs;
2166                 mUnpluggedReportedCount = mCurrentReportedCount;
2167             }
2168             mTimeBaseRunning = true;
2169         }
2170 
2171         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2172         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2173             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2174             mTimeBaseRunning = false;
2175         }
2176 
2177         @Override
logState(Printer pw, String prefix)2178         public void logState(Printer pw, String prefix) {
2179             super.logState(pw, prefix);
2180             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
2181                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
2182                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs
2183                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTimeUs);
2184         }
2185 
2186         @Override
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)2187         protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) {
2188             return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues
2189                     ? mCurrentReportedTotalTimeUs - mUnpluggedReportedTotalTimeUs : 0);
2190         }
2191 
2192         @Override
computeCurrentCountLocked()2193         protected int computeCurrentCountLocked() {
2194             return mCount + (mTimeBaseRunning && mTrackingReportedValues
2195                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
2196         }
2197 
2198         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2199         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2200             super.writeToParcel(out, elapsedRealtimeUs);
2201             out.writeInt(mCurrentReportedCount);
2202             out.writeInt(mUnpluggedReportedCount);
2203             out.writeLong(mCurrentReportedTotalTimeUs);
2204             out.writeLong(mUnpluggedReportedTotalTimeUs);
2205             out.writeInt(mTrackingReportedValues ? 1 : 0);
2206         }
2207 
2208         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2209         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2210             super.reset(detachIfReset, elapsedRealtimeUs);
2211             mTrackingReportedValues = false;
2212             mUnpluggedReportedTotalTimeUs = 0;
2213             mUnpluggedReportedCount = 0;
2214             return true;
2215         }
2216     }
2217 
2218     /**
2219      * A timer that increments in batches.  It does not run for durations, but just jumps
2220      * for a pre-determined amount.
2221      */
2222     public static class BatchTimer extends Timer {
2223         final Uid mUid;
2224 
2225         /**
2226          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
2227          */
2228         long mLastAddedTimeUs;
2229 
2230         /**
2231          * The last duration that we added to the timer.  This is in microseconds.
2232          */
2233         long mLastAddedDurationUs;
2234 
2235         /**
2236          * Whether we are currently in a discharge cycle.
2237          */
2238         boolean mInDischarge;
2239 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in)2240         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
2241             super(clocks, type, timeBase, in);
2242             mUid = uid;
2243             mLastAddedTimeUs = in.readLong();
2244             mLastAddedDurationUs = in.readLong();
2245             mInDischarge = timeBase.isRunning();
2246         }
2247 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase)2248         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
2249             super(clocks, type, timeBase);
2250             mUid = uid;
2251             mInDischarge = timeBase.isRunning();
2252         }
2253 
2254         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2255         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2256             super.writeToParcel(out, elapsedRealtimeUs);
2257             out.writeLong(mLastAddedTimeUs);
2258             out.writeLong(mLastAddedDurationUs);
2259         }
2260 
2261         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2262         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2263             recomputeLastDuration(elapsedRealtimeUs, false);
2264             mInDischarge = false;
2265             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2266         }
2267 
2268         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2269         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2270             recomputeLastDuration(elapsedRealtimeUs, false);
2271             mInDischarge = true;
2272             // If we are still within the last added duration, then re-added whatever remains.
2273             if (mLastAddedTimeUs == elapsedRealtimeUs) {
2274                 mTotalTimeUs += mLastAddedDurationUs;
2275             }
2276             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2277         }
2278 
2279         @Override
logState(Printer pw, String prefix)2280         public void logState(Printer pw, String prefix) {
2281             super.logState(pw, prefix);
2282             pw.println(prefix + "mLastAddedTime=" + mLastAddedTimeUs
2283                     + " mLastAddedDuration=" + mLastAddedDurationUs);
2284         }
2285 
computeOverage(long curTimeUs)2286         private long computeOverage(long curTimeUs) {
2287             if (mLastAddedTimeUs > 0) {
2288                 return mLastAddedDurationUs - curTimeUs;
2289             }
2290             return 0;
2291         }
2292 
recomputeLastDuration(long curTimeUs, boolean abort)2293         private void recomputeLastDuration(long curTimeUs, boolean abort) {
2294             final long overage = computeOverage(curTimeUs);
2295             if (overage > 0) {
2296                 // Aborting before the duration ran out -- roll back the remaining
2297                 // duration.  Only do this if currently discharging; otherwise we didn't
2298                 // actually add the time.
2299                 if (mInDischarge) {
2300                     mTotalTimeUs -= overage;
2301                 }
2302                 if (abort) {
2303                     mLastAddedTimeUs = 0;
2304                 } else {
2305                     mLastAddedTimeUs = curTimeUs;
2306                     mLastAddedDurationUs -= overage;
2307                 }
2308             }
2309         }
2310 
addDuration(BatteryStatsImpl stats, long durationMs)2311         public void addDuration(BatteryStatsImpl stats, long durationMs) {
2312             addDuration(stats, durationMs, mClocks.elapsedRealtime());
2313         }
2314 
addDuration(BatteryStatsImpl stats, long durationMs, long elapsedRealtimeMs)2315         public void addDuration(BatteryStatsImpl stats, long durationMs, long elapsedRealtimeMs) {
2316             final long nowUs = elapsedRealtimeMs * 1000;
2317             recomputeLastDuration(nowUs, true);
2318             mLastAddedTimeUs = nowUs;
2319             mLastAddedDurationUs = durationMs * 1000;
2320             if (mInDischarge) {
2321                 mTotalTimeUs += mLastAddedDurationUs;
2322                 mCount++;
2323             }
2324         }
2325 
abortLastDuration(BatteryStatsImpl stats)2326         public void abortLastDuration(BatteryStatsImpl stats) {
2327             abortLastDuration(stats, mClocks.elapsedRealtime());
2328         }
2329 
abortLastDuration(BatteryStatsImpl stats, long elapsedRealtimeMs)2330         public void abortLastDuration(BatteryStatsImpl stats, long elapsedRealtimeMs) {
2331             final long nowUs = elapsedRealtimeMs * 1000;
2332             recomputeLastDuration(nowUs, true);
2333         }
2334 
2335         @Override
computeCurrentCountLocked()2336         protected int computeCurrentCountLocked() {
2337             return mCount;
2338         }
2339 
2340         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)2341         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
2342             final long overage = computeOverage(elapsedRealtimeUs);
2343             if (overage > 0) {
2344                 return mTotalTimeUs = overage;
2345             }
2346             return mTotalTimeUs;
2347         }
2348 
2349         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2350         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2351             recomputeLastDuration(elapsedRealtimeUs, true);
2352             boolean stillActive = mLastAddedTimeUs == elapsedRealtimeUs;
2353             super.reset(!stillActive && detachIfReset, elapsedRealtimeUs);
2354             return !stillActive;
2355         }
2356     }
2357 
2358 
2359     /**
2360      * A StopwatchTimer that also tracks the total and max individual
2361      * time spent active according to the given timebase.  Whereas
2362      * StopwatchTimer apportions the time amongst all in the pool,
2363      * the total and max durations are not apportioned.
2364      */
2365     public static class DurationTimer extends StopwatchTimer {
2366         /**
2367          * The time (in ms) that the timer was last acquired or the time base
2368          * last (re-)started. Increasing the nesting depth does not reset this time.
2369          *
2370          * -1 if the timer is currently not running or the time base is not running.
2371          *
2372          * If written to a parcel, the start time is reset, as is mNesting in the base class
2373          * StopwatchTimer.
2374          */
2375         long mStartTimeMs = -1;
2376 
2377         /**
2378          * The longest time period (in ms) that the timer has been active. Not pooled.
2379          */
2380         long mMaxDurationMs;
2381 
2382         /**
2383          * The time (in ms) that that the timer has been active since most recent
2384          * stopRunningLocked() or reset(). Not pooled.
2385          */
2386         long mCurrentDurationMs;
2387 
2388         /**
2389          * The total time (in ms) that that the timer has been active since most recent reset()
2390          * prior to the current startRunningLocked. This is the sum of all past currentDurations
2391          * (but not including the present currentDuration) since reset. Not pooled.
2392          */
2393         long mTotalDurationMs;
2394 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2395         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2396                 TimeBase timeBase, Parcel in) {
2397             super(clocks, uid, type, timerPool, timeBase, in);
2398             mMaxDurationMs = in.readLong();
2399             mTotalDurationMs = in.readLong();
2400             mCurrentDurationMs = in.readLong();
2401         }
2402 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2403         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2404                 TimeBase timeBase) {
2405             super(clocks, uid, type, timerPool, timeBase);
2406         }
2407 
2408         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2409         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2410             super.writeToParcel(out, elapsedRealtimeUs);
2411             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2412             out.writeLong(mTotalDurationMs);
2413             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
2414         }
2415 
2416         /**
2417          * Write the summary to the parcel.
2418          *
2419          * Since the time base is probably meaningless after we come back, reading
2420          * from this will have the effect of stopping the timer. So here all we write
2421          * is the max and total durations.
2422          */
2423         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2424         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2425             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2426             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2427             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
2428         }
2429 
2430         /**
2431          * Read the summary parcel.
2432          *
2433          * Has the side effect of stopping the timer.
2434          */
2435         @Override
readSummaryFromParcelLocked(Parcel in)2436         public void readSummaryFromParcelLocked(Parcel in) {
2437             super.readSummaryFromParcelLocked(in);
2438             mMaxDurationMs = in.readLong();
2439             mTotalDurationMs = in.readLong();
2440             mStartTimeMs = -1;
2441             mCurrentDurationMs = 0;
2442         }
2443 
2444         /**
2445          * The TimeBase time started (again).
2446          *
2447          * If the timer is also running, store the start time.
2448          */
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2449         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2450             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2451             if (mNesting > 0) {
2452                 mStartTimeMs = baseRealtimeUs / 1000;
2453             }
2454         }
2455 
2456         /**
2457          * The TimeBase stopped running.
2458          *
2459          * If the timer is running, add the duration into mCurrentDurationMs.
2460          */
2461         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2462         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2463             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2464             if (mNesting > 0) {
2465                 // baseRealtimeUs has already been converted to the timebase's realtime.
2466                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
2467             }
2468             mStartTimeMs = -1;
2469         }
2470 
2471         @Override
logState(Printer pw, String prefix)2472         public void logState(Printer pw, String prefix) {
2473             super.logState(pw, prefix);
2474         }
2475 
2476         @Override
startRunningLocked(long elapsedRealtimeMs)2477         public void startRunningLocked(long elapsedRealtimeMs) {
2478             super.startRunningLocked(elapsedRealtimeMs);
2479             if (mNesting == 1 && mTimeBase.isRunning()) {
2480                 // Just started
2481                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
2482             }
2483         }
2484 
2485         /**
2486          * Decrements the mNesting ref-count on this timer.
2487          *
2488          * If it actually stopped (mNesting went to 0), then possibly update
2489          * mMaxDuration if the current duration was the longest ever.
2490          */
2491         @Override
stopRunningLocked(long elapsedRealtimeMs)2492         public void stopRunningLocked(long elapsedRealtimeMs) {
2493             if (mNesting == 1) {
2494                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2495                 mTotalDurationMs += durationMs;
2496                 if (durationMs > mMaxDurationMs) {
2497                     mMaxDurationMs = durationMs;
2498                 }
2499                 mStartTimeMs = -1;
2500                 mCurrentDurationMs = 0;
2501             }
2502             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
2503             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
2504             super.stopRunningLocked(elapsedRealtimeMs);
2505         }
2506 
2507         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2508         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2509             boolean result = super.reset(detachIfReset, elapsedRealtimeUs);
2510             mMaxDurationMs = 0;
2511             mTotalDurationMs = 0;
2512             mCurrentDurationMs = 0;
2513             if (mNesting > 0) {
2514                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeUs) / 1000;
2515             } else {
2516                 mStartTimeMs = -1;
2517             }
2518             return result;
2519         }
2520 
2521         /**
2522          * Returns the max duration that this timer has ever seen.
2523          *
2524          * Note that this time is NOT split between the timers in the timer group that
2525          * this timer is attached to.  It is the TOTAL time.
2526          */
2527         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)2528         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
2529             if (mNesting > 0) {
2530                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2531                 if (durationMs > mMaxDurationMs) {
2532                     return durationMs;
2533                 }
2534             }
2535             return mMaxDurationMs;
2536         }
2537 
2538         /**
2539          * Returns the time since the timer was started.
2540          * Returns 0 if the timer is not currently running.
2541          *
2542          * Note that this time is NOT split between the timers in the timer group that
2543          * this timer is attached to.  It is the TOTAL time.
2544          *
2545          * Note that if running timer is parceled and unparceled, this method will return
2546          * current duration value at the time of parceling even though timer may not be
2547          * currently running.
2548          */
2549         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)2550         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
2551             long durationMs = mCurrentDurationMs;
2552             if (mNesting > 0 && mTimeBase.isRunning()) {
2553                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
2554                         - mStartTimeMs;
2555             }
2556             return durationMs;
2557         }
2558 
2559         /**
2560          * Returns the total cumulative duration that this timer has been on since reset().
2561          * If mTimerPool == null, this should be the same
2562          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
2563          *
2564          * Note that this time is NOT split between the timers in the timer group that
2565          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
2566          * the result will not be equivalent to getTotalTimeLocked.
2567          */
2568         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)2569         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
2570             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
2571         }
2572     }
2573 
2574     /**
2575      * State for keeping track of timing information.
2576      */
2577     public static class StopwatchTimer extends Timer {
2578         final Uid mUid;
2579         final ArrayList<StopwatchTimer> mTimerPool;
2580 
2581         int mNesting;
2582 
2583         /**
2584          * The last time at which we updated the timer.  If mNesting is > 0,
2585          * subtract this from the current battery time to find the amount of
2586          * time we have been running since we last computed an update.
2587          */
2588         long mUpdateTimeUs;
2589 
2590         /**
2591          * The total time at which the timer was acquired, to determine if it
2592          * was actually held for an interesting duration. If time base was not running when timer
2593          * was acquired, will be -1.
2594          */
2595         long mAcquireTimeUs = -1;
2596 
2597         long mTimeoutUs;
2598 
2599         /**
2600          * For partial wake locks, keep track of whether we are in the list
2601          * to consume CPU cycles.
2602          */
2603         @VisibleForTesting
2604         public boolean mInList;
2605 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2606         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2607                 TimeBase timeBase, Parcel in) {
2608             super(clocks, type, timeBase, in);
2609             mUid = uid;
2610             mTimerPool = timerPool;
2611             mUpdateTimeUs = in.readLong();
2612         }
2613 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2614         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2615                 TimeBase timeBase) {
2616             super(clocks, type, timeBase);
2617             mUid = uid;
2618             mTimerPool = timerPool;
2619         }
2620 
setTimeout(long timeoutUs)2621         public void setTimeout(long timeoutUs) {
2622             mTimeoutUs = timeoutUs;
2623         }
2624 
writeToParcel(Parcel out, long elapsedRealtimeUs)2625         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2626             super.writeToParcel(out, elapsedRealtimeUs);
2627             out.writeLong(mUpdateTimeUs);
2628         }
2629 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2630         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2631             if (mNesting > 0) {
2632                 if (DEBUG && mType < 0) {
2633                     Log.v(TAG, "old mUpdateTime=" + mUpdateTimeUs);
2634                 }
2635                 super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2636                 mUpdateTimeUs = baseRealtimeUs;
2637                 if (DEBUG && mType < 0) {
2638                     Log.v(TAG, "new mUpdateTime=" + mUpdateTimeUs);
2639                 }
2640             }
2641         }
2642 
logState(Printer pw, String prefix)2643         public void logState(Printer pw, String prefix) {
2644             super.logState(pw, prefix);
2645             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTimeUs
2646                     + " mAcquireTime=" + mAcquireTimeUs);
2647         }
2648 
startRunningLocked(long elapsedRealtimeMs)2649         public void startRunningLocked(long elapsedRealtimeMs) {
2650             if (mNesting++ == 0) {
2651                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2652                 mUpdateTimeUs = batteryRealtimeUs;
2653                 if (mTimerPool != null) {
2654                     // Accumulate time to all currently active timers before adding
2655                     // this new one to the pool.
2656                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
2657                     // Add this timer to the active pool
2658                     mTimerPool.add(this);
2659                 }
2660                 if (mTimeBase.isRunning()) {
2661                     // Increment the count
2662                     mCount++;
2663                     mAcquireTimeUs = mTotalTimeUs;
2664                 } else {
2665                     mAcquireTimeUs = -1;
2666                 }
2667                 if (DEBUG && mType < 0) {
2668                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTimeUs
2669                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
2670                             + " mAcquireTime=" + mAcquireTimeUs);
2671                 }
2672             }
2673         }
2674 
isRunningLocked()2675         public boolean isRunningLocked() {
2676             return mNesting > 0;
2677         }
2678 
stopRunningLocked(long elapsedRealtimeMs)2679         public void stopRunningLocked(long elapsedRealtimeMs) {
2680             // Ignore attempt to stop a timer that isn't running
2681             if (mNesting == 0) {
2682                 return;
2683             }
2684             if (--mNesting == 0) {
2685                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2686                 if (mTimerPool != null) {
2687                     // Accumulate time to all active counters, scaled by the total
2688                     // active in the pool, before taking this one out of the pool.
2689                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
2690                     // Remove this timer from the active pool
2691                     mTimerPool.remove(this);
2692                 } else {
2693                     mNesting = 1;
2694                     mTotalTimeUs = computeRunTimeLocked(batteryRealtimeUs,
2695                             elapsedRealtimeMs * 1000);
2696                     mNesting = 0;
2697                 }
2698 
2699                 if (DEBUG && mType < 0) {
2700                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTimeUs
2701                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
2702                             + " mAcquireTime=" + mAcquireTimeUs);
2703                 }
2704 
2705                 if (mAcquireTimeUs >= 0 && mTotalTimeUs == mAcquireTimeUs) {
2706                     // If there was no change in the time, then discard this
2707                     // count.  A somewhat cheezy strategy, but hey.
2708                     mCount--;
2709                 }
2710             }
2711         }
2712 
stopAllRunningLocked(long elapsedRealtimeMs)2713         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2714             if (mNesting > 0) {
2715                 mNesting = 1;
2716                 stopRunningLocked(elapsedRealtimeMs);
2717             }
2718         }
2719 
2720         // Update the total time for all other running Timers with the same type as this Timer
2721         // due to a change in timer count
refreshTimersLocked(long batteryRealtimeUs, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)2722         private static long refreshTimersLocked(long batteryRealtimeUs,
2723                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
2724             long selfTimeUs = 0;
2725             final int N = pool.size();
2726             for (int i=N-1; i>= 0; i--) {
2727                 final StopwatchTimer t = pool.get(i);
2728                 long heldTimeUs = batteryRealtimeUs - t.mUpdateTimeUs;
2729                 if (heldTimeUs > 0) {
2730                     final long myTimeUs = heldTimeUs / N;
2731                     if (t == self) {
2732                         selfTimeUs = myTimeUs;
2733                     }
2734                     t.mTotalTimeUs += myTimeUs;
2735                 }
2736                 t.mUpdateTimeUs = batteryRealtimeUs;
2737             }
2738             return selfTimeUs;
2739         }
2740 
2741         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)2742         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
2743             if (mTimeoutUs > 0 && curBatteryRealtimeUs > mUpdateTimeUs + mTimeoutUs) {
2744                 curBatteryRealtimeUs = mUpdateTimeUs + mTimeoutUs;
2745             }
2746             return mTotalTimeUs + (mNesting > 0
2747                     ? (curBatteryRealtimeUs - mUpdateTimeUs)
2748                             / (mTimerPool != null ? mTimerPool.size() : 1)
2749                     : 0);
2750         }
2751 
2752         @Override
computeCurrentCountLocked()2753         protected int computeCurrentCountLocked() {
2754             return mCount;
2755         }
2756 
2757         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2758         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2759             boolean canDetach = mNesting <= 0;
2760             super.reset(canDetach && detachIfReset, elapsedRealtimeUs);
2761             if (mNesting > 0) {
2762                 mUpdateTimeUs = mTimeBase.getRealtime(elapsedRealtimeUs);
2763             }
2764             // To ensure mCount isn't decreased to -1 if timer is stopped later.
2765             mAcquireTimeUs = -1;
2766             return canDetach;
2767         }
2768 
2769         @Override
2770         @UnsupportedAppUsage
detach()2771         public void detach() {
2772             super.detach();
2773             if (mTimerPool != null) {
2774                 mTimerPool.remove(this);
2775             }
2776         }
2777 
2778         @Override
readSummaryFromParcelLocked(Parcel in)2779         public void readSummaryFromParcelLocked(Parcel in) {
2780             super.readSummaryFromParcelLocked(in);
2781             mNesting = 0;
2782         }
2783 
2784         /**
2785          * Set the mark so that we can query later for the total time the timer has
2786          * accumulated since this point. The timer can be running or not.
2787          *
2788          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
2789          */
setMark(long elapsedRealtimeMs)2790         public void setMark(long elapsedRealtimeMs) {
2791             final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2792             if (mNesting > 0) {
2793                 // We are running.
2794                 if (mTimerPool != null) {
2795                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, this);
2796                 } else {
2797                     mTotalTimeUs += batteryRealtimeUs - mUpdateTimeUs;
2798                     mUpdateTimeUs = batteryRealtimeUs;
2799                 }
2800             }
2801             mTimeBeforeMarkUs = mTotalTimeUs;
2802         }
2803     }
2804 
2805     /**
2806      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
2807      * TimeBase is effectively a subset of the other.
2808      */
2809     public static class DualTimer extends DurationTimer {
2810         // This class both is a DurationTimer and also holds a second DurationTimer.
2811         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
2812         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
2813         // STATS_SINCE_CHARGED).
2814         // mSubTimer typically tracks only part of the total time, such as background time, as
2815         // determined by a subTimeBase. It is NOT pooled.
2816         private final DurationTimer mSubTimer;
2817 
2818         /**
2819          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2820          * The main timer (this) is based on the given timeBase and timerPool.
2821          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2822          * the main timer is.
2823          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)2824         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2825                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
2826             super(clocks, uid, type, timerPool, timeBase, in);
2827             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase, in);
2828         }
2829 
2830         /**
2831          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2832          * The main timer (this) is based on the given timeBase and timerPool.
2833          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2834          * the main timer is.
2835          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)2836         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2837                 TimeBase timeBase, TimeBase subTimeBase) {
2838             super(clocks, uid, type, timerPool, timeBase);
2839             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase);
2840         }
2841 
2842         /** Get the secondary timer. */
2843         @Override
getSubTimer()2844         public DurationTimer getSubTimer() {
2845             return mSubTimer;
2846         }
2847 
2848         @Override
startRunningLocked(long elapsedRealtimeMs)2849         public void startRunningLocked(long elapsedRealtimeMs) {
2850             super.startRunningLocked(elapsedRealtimeMs);
2851             mSubTimer.startRunningLocked(elapsedRealtimeMs);
2852         }
2853 
2854         @Override
stopRunningLocked(long elapsedRealtimeMs)2855         public void stopRunningLocked(long elapsedRealtimeMs) {
2856             super.stopRunningLocked(elapsedRealtimeMs);
2857             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
2858         }
2859 
2860         @Override
stopAllRunningLocked(long elapsedRealtimeMs)2861         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2862             super.stopAllRunningLocked(elapsedRealtimeMs);
2863             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
2864         }
2865 
2866         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2867         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2868             boolean active = false;
2869             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
2870             active |= !mSubTimer.reset(false, elapsedRealtimeUs);
2871             active |= !super.reset(detachIfReset, elapsedRealtimeUs);
2872             return !active;
2873         }
2874 
2875         @Override
detach()2876         public void detach() {
2877             mSubTimer.detach();
2878             super.detach();
2879         }
2880 
2881         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2882         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2883             super.writeToParcel(out, elapsedRealtimeUs);
2884             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
2885         }
2886 
2887         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2888         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2889             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2890             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2891         }
2892 
2893         @Override
readSummaryFromParcelLocked(Parcel in)2894         public void readSummaryFromParcelLocked(Parcel in) {
2895             super.readSummaryFromParcelLocked(in);
2896             mSubTimer.readSummaryFromParcelLocked(in);
2897         }
2898     }
2899 
2900 
2901     public abstract class OverflowArrayMap<T> {
2902         private static final String OVERFLOW_NAME = "*overflow*";
2903 
2904         final int mUid;
2905         final ArrayMap<String, T> mMap = new ArrayMap<>();
2906         T mCurOverflow;
2907         ArrayMap<String, MutableInt> mActiveOverflow;
2908         long mLastOverflowTimeMs;
2909         long mLastOverflowFinishTimeMs;
2910         long mLastClearTimeMs;
2911         long mLastCleanupTimeMs;
2912 
OverflowArrayMap(int uid)2913         public OverflowArrayMap(int uid) {
2914             mUid = uid;
2915         }
2916 
getMap()2917         public ArrayMap<String, T> getMap() {
2918             return mMap;
2919         }
2920 
clear()2921         public void clear() {
2922             mLastClearTimeMs = SystemClock.elapsedRealtime();
2923             mMap.clear();
2924             mCurOverflow = null;
2925             mActiveOverflow = null;
2926         }
2927 
add(String name, T obj)2928         public void add(String name, T obj) {
2929             if (name == null) {
2930                 name = "";
2931             }
2932             mMap.put(name, obj);
2933             if (OVERFLOW_NAME.equals(name)) {
2934                 mCurOverflow = obj;
2935             }
2936         }
2937 
cleanup(long elapsedRealtimeMs)2938         public void cleanup(long elapsedRealtimeMs) {
2939             mLastCleanupTimeMs = elapsedRealtimeMs;
2940             if (mActiveOverflow != null) {
2941                 if (mActiveOverflow.size() == 0) {
2942                     mActiveOverflow = null;
2943                 }
2944             }
2945             if (mActiveOverflow == null) {
2946                 // There is no currently active overflow, so we should no longer have
2947                 // an overflow entry.
2948                 if (mMap.containsKey(OVERFLOW_NAME)) {
2949                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
2950                             + mMap.get(OVERFLOW_NAME));
2951                     mMap.remove(OVERFLOW_NAME);
2952                 }
2953                 mCurOverflow = null;
2954             } else {
2955                 // There is currently active overflow, so we should still have an overflow entry.
2956                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
2957                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
2958                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
2959                 }
2960             }
2961         }
2962 
startObject(String name, long elapsedRealtimeMs)2963         public T startObject(String name, long elapsedRealtimeMs) {
2964             if (name == null) {
2965                 name = "";
2966             }
2967             T obj = mMap.get(name);
2968             if (obj != null) {
2969                 return obj;
2970             }
2971 
2972             // No object exists for the given name, but do we currently have it
2973             // running as part of the overflow?
2974             if (mActiveOverflow != null) {
2975                 MutableInt over = mActiveOverflow.get(name);
2976                 if (over != null) {
2977                     // We are already actively counting this name in the overflow object.
2978                     obj = mCurOverflow;
2979                     if (obj == null) {
2980                         // Shouldn't be here, but we'll try to recover.
2981                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
2982                         obj = mCurOverflow = instantiateObject();
2983                         mMap.put(OVERFLOW_NAME, obj);
2984                     }
2985                     over.value++;
2986                     return obj;
2987                 }
2988             }
2989 
2990             // No object exists for given name nor in the overflow; we need to make
2991             // a new one.
2992             final int N = mMap.size();
2993             if (N >= MAX_WAKELOCKS_PER_UID) {
2994                 // Went over the limit on number of objects to track; this one goes
2995                 // in to the overflow.
2996                 obj = mCurOverflow;
2997                 if (obj == null) {
2998                     // Need to start overflow now...
2999                     obj = mCurOverflow = instantiateObject();
3000                     mMap.put(OVERFLOW_NAME, obj);
3001                 }
3002                 if (mActiveOverflow == null) {
3003                     mActiveOverflow = new ArrayMap<>();
3004                 }
3005                 mActiveOverflow.put(name, new MutableInt(1));
3006                 mLastOverflowTimeMs = elapsedRealtimeMs;
3007                 return obj;
3008             }
3009 
3010             // Normal case where we just need to make a new object.
3011             obj = instantiateObject();
3012             mMap.put(name, obj);
3013             return obj;
3014         }
3015 
stopObject(String name, long elapsedRealtimeMs)3016         public T stopObject(String name, long elapsedRealtimeMs) {
3017             if (name == null) {
3018                 name = "";
3019             }
3020             T obj = mMap.get(name);
3021             if (obj != null) {
3022                 return obj;
3023             }
3024 
3025             // No object exists for the given name, but do we currently have it
3026             // running as part of the overflow?
3027             if (mActiveOverflow != null) {
3028                 MutableInt over = mActiveOverflow.get(name);
3029                 if (over != null) {
3030                     // We are already actively counting this name in the overflow object.
3031                     obj = mCurOverflow;
3032                     if (obj != null) {
3033                         over.value--;
3034                         if (over.value <= 0) {
3035                             mActiveOverflow.remove(name);
3036                             mLastOverflowFinishTimeMs = elapsedRealtimeMs;
3037                         }
3038                         return obj;
3039                     }
3040                 }
3041             }
3042 
3043             // Huh, they are stopping an active operation but we can't find one!
3044             // That's not good.
3045             StringBuilder sb = new StringBuilder();
3046             sb.append("Unable to find object for ");
3047             sb.append(name);
3048             sb.append(" in uid ");
3049             sb.append(mUid);
3050             sb.append(" mapsize=");
3051             sb.append(mMap.size());
3052             sb.append(" activeoverflow=");
3053             sb.append(mActiveOverflow);
3054             sb.append(" curoverflow=");
3055             sb.append(mCurOverflow);
3056             long now = elapsedRealtimeMs;
3057             if (mLastOverflowTimeMs != 0) {
3058                 sb.append(" lastOverflowTime=");
3059                 TimeUtils.formatDuration(mLastOverflowTimeMs - now, sb);
3060             }
3061             if (mLastOverflowFinishTimeMs != 0) {
3062                 sb.append(" lastOverflowFinishTime=");
3063                 TimeUtils.formatDuration(mLastOverflowFinishTimeMs - now, sb);
3064             }
3065             if (mLastClearTimeMs != 0) {
3066                 sb.append(" lastClearTime=");
3067                 TimeUtils.formatDuration(mLastClearTimeMs - now, sb);
3068             }
3069             if (mLastCleanupTimeMs != 0) {
3070                 sb.append(" lastCleanupTime=");
3071                 TimeUtils.formatDuration(mLastCleanupTimeMs - now, sb);
3072             }
3073             Slog.wtf(TAG, sb.toString());
3074             return null;
3075         }
3076 
instantiateObject()3077         public abstract T instantiateObject();
3078     }
3079 
3080     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
3081             implements Parcelable {
3082         private final LongSamplingCounter mIdleTimeMillis;
3083         private final LongSamplingCounter mScanTimeMillis;
3084         private final LongSamplingCounter mSleepTimeMillis;
3085         private final LongSamplingCounter mRxTimeMillis;
3086         private final LongSamplingCounter[] mTxTimeMillis;
3087         private final LongSamplingCounter mPowerDrainMaMs;
3088         private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs;
3089 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates)3090         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
3091             mIdleTimeMillis = new LongSamplingCounter(timeBase);
3092             mScanTimeMillis = new LongSamplingCounter(timeBase);
3093             mSleepTimeMillis = new LongSamplingCounter(timeBase);
3094             mRxTimeMillis = new LongSamplingCounter(timeBase);
3095             mTxTimeMillis = new LongSamplingCounter[numTxStates];
3096             for (int i = 0; i < numTxStates; i++) {
3097                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
3098             }
3099             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
3100             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase);
3101         }
3102 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in)3103         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
3104             mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
3105             mScanTimeMillis = new LongSamplingCounter(timeBase, in);
3106             mSleepTimeMillis = new LongSamplingCounter(timeBase, in);
3107             mRxTimeMillis = new LongSamplingCounter(timeBase, in);
3108             final int recordedTxStates = in.readInt();
3109             if (recordedTxStates != numTxStates) {
3110                 throw new ParcelFormatException("inconsistent tx state lengths");
3111             }
3112 
3113             mTxTimeMillis = new LongSamplingCounter[numTxStates];
3114             for (int i = 0; i < numTxStates; i++) {
3115                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
3116             }
3117             mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
3118             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase, in);
3119         }
3120 
readSummaryFromParcel(Parcel in)3121         public void readSummaryFromParcel(Parcel in) {
3122             mIdleTimeMillis.readSummaryFromParcelLocked(in);
3123             mScanTimeMillis.readSummaryFromParcelLocked(in);
3124             mSleepTimeMillis.readSummaryFromParcelLocked(in);
3125             mRxTimeMillis.readSummaryFromParcelLocked(in);
3126             final int recordedTxStates = in.readInt();
3127             if (recordedTxStates != mTxTimeMillis.length) {
3128                 throw new ParcelFormatException("inconsistent tx state lengths");
3129             }
3130             for (LongSamplingCounter counter : mTxTimeMillis) {
3131                 counter.readSummaryFromParcelLocked(in);
3132             }
3133             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
3134             mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in);
3135         }
3136 
3137         @Override
describeContents()3138         public int describeContents() {
3139             return 0;
3140         }
3141 
writeSummaryToParcel(Parcel dest)3142         public void writeSummaryToParcel(Parcel dest) {
3143             mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
3144             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
3145             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
3146             mRxTimeMillis.writeSummaryFromParcelLocked(dest);
3147             dest.writeInt(mTxTimeMillis.length);
3148             for (LongSamplingCounter counter : mTxTimeMillis) {
3149                 counter.writeSummaryFromParcelLocked(dest);
3150             }
3151             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
3152             mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest);
3153         }
3154 
3155         @Override
writeToParcel(Parcel dest, int flags)3156         public void writeToParcel(Parcel dest, int flags) {
3157             mIdleTimeMillis.writeToParcel(dest);
3158             mScanTimeMillis.writeToParcel(dest);
3159             mSleepTimeMillis.writeToParcel(dest);
3160             mRxTimeMillis.writeToParcel(dest);
3161             dest.writeInt(mTxTimeMillis.length);
3162             for (LongSamplingCounter counter : mTxTimeMillis) {
3163                 counter.writeToParcel(dest);
3164             }
3165             mPowerDrainMaMs.writeToParcel(dest);
3166             mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
3167         }
3168 
reset(boolean detachIfReset, long elapsedRealtimeUs)3169         public void reset(boolean detachIfReset, long elapsedRealtimeUs) {
3170             mIdleTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3171             mScanTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3172             mSleepTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3173             mRxTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3174             for (LongSamplingCounter counter : mTxTimeMillis) {
3175                 counter.reset(detachIfReset, elapsedRealtimeUs);
3176             }
3177             mPowerDrainMaMs.reset(detachIfReset, elapsedRealtimeUs);
3178             mMonitoredRailChargeConsumedMaMs.reset(detachIfReset, elapsedRealtimeUs);
3179         }
3180 
detach()3181         public void detach() {
3182             mIdleTimeMillis.detach();
3183             mScanTimeMillis.detach();
3184             mSleepTimeMillis.detach();
3185             mRxTimeMillis.detach();
3186             for (LongSamplingCounter counter : mTxTimeMillis) {
3187                 counter.detach();
3188             }
3189             mPowerDrainMaMs.detach();
3190             mMonitoredRailChargeConsumedMaMs.detach();
3191         }
3192 
3193         /**
3194          * @return a LongSamplingCounter, measuring time spent in the idle state in
3195          * milliseconds.
3196          */
3197         @Override
getIdleTimeCounter()3198         public LongSamplingCounter getIdleTimeCounter() {
3199             return mIdleTimeMillis;
3200         }
3201 
3202         /**
3203          * @return a LongSamplingCounter, measuring time spent in the scan state in
3204          * milliseconds.
3205          */
3206         @Override
getScanTimeCounter()3207         public LongSamplingCounter getScanTimeCounter() {
3208             return mScanTimeMillis;
3209         }
3210 
3211         /**
3212          * @return a LongSamplingCounter, measuring time spent in the sleep state in
3213          * milliseconds.
3214          */
3215         @Override
getSleepTimeCounter()3216         public LongSamplingCounter getSleepTimeCounter() {
3217             return mSleepTimeMillis;
3218         }
3219 
3220         /**
3221          * @return a LongSamplingCounter, measuring time spent in the receive state in
3222          * milliseconds.
3223          */
3224         @Override
getRxTimeCounter()3225         public LongSamplingCounter getRxTimeCounter() {
3226             return mRxTimeMillis;
3227         }
3228 
3229         /**
3230          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
3231          * milliseconds.
3232          */
3233         @Override
getTxTimeCounters()3234         public LongSamplingCounter[] getTxTimeCounters() {
3235             return mTxTimeMillis;
3236         }
3237 
3238         /**
3239          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
3240          */
3241         @Override
getPowerCounter()3242         public LongSamplingCounter getPowerCounter() {
3243             return mPowerDrainMaMs;
3244         }
3245 
3246         /**
3247          * @return a LongSamplingCounter, measuring actual monitored rail energy consumed
3248          * milli-ampere milli-seconds (mAmS).
3249          */
3250         @Override
getMonitoredRailChargeConsumedMaMs()3251         public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() {
3252             return mMonitoredRailChargeConsumedMaMs;
3253         }
3254     }
3255 
3256     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)3257     public SamplingTimer getRpmTimerLocked(String name) {
3258         SamplingTimer rpmt = mRpmStats.get(name);
3259         if (rpmt == null) {
3260             rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3261             mRpmStats.put(name, rpmt);
3262         }
3263         return rpmt;
3264     }
3265 
3266     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)3267     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
3268         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
3269         if (rpmt == null) {
3270             rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3271             mScreenOffRpmStats.put(name, rpmt);
3272         }
3273         return rpmt;
3274     }
3275 
3276     /*
3277      * Get the wakeup reason counter, and create a new one if one
3278      * doesn't already exist.
3279      */
getWakeupReasonTimerLocked(String name)3280     public SamplingTimer getWakeupReasonTimerLocked(String name) {
3281         SamplingTimer timer = mWakeupReasonStats.get(name);
3282         if (timer == null) {
3283             timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3284             mWakeupReasonStats.put(name, timer);
3285         }
3286         return timer;
3287     }
3288 
3289     /*
3290      * Get the KernelWakelockTimer associated with name, and create a new one if one
3291      * doesn't already exist.
3292      */
getKernelWakelockTimerLocked(String name)3293     public SamplingTimer getKernelWakelockTimerLocked(String name) {
3294         SamplingTimer kwlt = mKernelWakelockStats.get(name);
3295         if (kwlt == null) {
3296             kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3297             mKernelWakelockStats.put(name, kwlt);
3298         }
3299         return kwlt;
3300     }
3301 
getKernelMemoryTimerLocked(long bucket)3302     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
3303         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
3304         if (kmt == null) {
3305             kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3306             mKernelMemoryStats.put(bucket, kmt);
3307         }
3308         return kmt;
3309     }
3310 
writeHistoryTag(HistoryTag tag)3311     private int writeHistoryTag(HistoryTag tag) {
3312         Integer idxObj = mHistoryTagPool.get(tag);
3313         int idx;
3314         if (idxObj != null) {
3315             idx = idxObj;
3316         } else {
3317             idx = mNextHistoryTagIdx;
3318             HistoryTag key = new HistoryTag();
3319             key.setTo(tag);
3320             tag.poolIdx = idx;
3321             mHistoryTagPool.put(key, idx);
3322             mNextHistoryTagIdx++;
3323             mNumHistoryTagChars += key.string.length() + 1;
3324         }
3325         return idx;
3326     }
3327 
3328     /*
3329         The history delta format uses flags to denote further data in subsequent ints in the parcel.
3330 
3331         There is always the first token, which may contain the delta time, or an indicator of
3332         the length of the time (int or long) following this token.
3333 
3334         First token: always present,
3335         31              23              15               7             0
3336         █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█
3337 
3338         T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
3339            follows containing the time, and 0x7ffff indicates a long immediately follows with the
3340            delta time.
3341         A: battery level changed and an int follows with battery data.
3342         B: state changed and an int follows with state change data.
3343         C: state2 has changed and an int follows with state2 change data.
3344         D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
3345         E: event data has changed and an event struct follows.
3346         F: battery charge in coulombs has changed and an int with the charge follows.
3347         G: state flag denoting that the mobile radio was active.
3348         H: state flag denoting that the wifi radio was active.
3349         I: state flag denoting that a wifi scan occurred.
3350         J: state flag denoting that a wifi full lock was held.
3351         K: state flag denoting that the gps was on.
3352         L: state flag denoting that a wakelock was held.
3353         M: state flag denoting that the cpu was running.
3354 
3355         Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
3356         with the time delta.
3357 
3358         Battery level int: if A in the first token is set,
3359         31              23              15               7             0
3360         █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█
3361 
3362         D: indicates that extra history details follow.
3363         V: the battery voltage.
3364         T: the battery temperature.
3365         L: the battery level (out of 100).
3366 
3367         State change int: if B in the first token is set,
3368         31              23              15               7             0
3369         █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
3370 
3371         A: wifi multicast was on.
3372         B: battery was plugged in.
3373         C: screen was on.
3374         D: phone was scanning for signal.
3375         E: audio was on.
3376         F: a sensor was active.
3377 
3378         State2 change int: if C in the first token is set,
3379         31              23              15               7             0
3380         █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
3381 
3382         A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
3383         B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
3384         C: a bluetooth scan was active.
3385         D: the camera was active.
3386         E: bluetooth was on.
3387         F: a phone call was active.
3388         G: the device was charging.
3389         H: 2 bits indicating the device-idle (doze) state: off, light, full
3390         I: the flashlight was on.
3391         J: wifi was on.
3392         K: wifi was running.
3393         L: video was playing.
3394         M: power save mode was on.
3395 
3396         Wakelock/wakereason struct: if D in the first token is set,
3397         TODO(adamlesinski): describe wakelock/wakereason struct.
3398 
3399         Event struct: if E in the first token is set,
3400         TODO(adamlesinski): describe the event struct.
3401 
3402         History step details struct: if D in the battery level int is set,
3403         TODO(adamlesinski): describe the history step details struct.
3404 
3405         Battery charge int: if F in the first token is set, an int representing the battery charge
3406         in coulombs follows.
3407      */
3408 
3409     // Part of initial delta int that specifies the time delta.
3410     static final int DELTA_TIME_MASK = 0x7ffff;
3411     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
3412     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
3413     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
3414     // Flag in delta int: a new battery level int follows.
3415     static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
3416     // Flag in delta int: a new full state and battery status int follows.
3417     static final int DELTA_STATE_FLAG                       = 0x00100000;
3418     // Flag in delta int: a new full state2 int follows.
3419     static final int DELTA_STATE2_FLAG                      = 0x00200000;
3420     // Flag in delta int: contains a wakelock or wakeReason tag.
3421     static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
3422     // Flag in delta int: contains an event description.
3423     static final int DELTA_EVENT_FLAG                       = 0x00800000;
3424     // Flag in delta int: contains the battery charge count in uAh.
3425     static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
3426     // These upper bits are the frequently changing state bits.
3427     static final int DELTA_STATE_MASK                       = 0xfe000000;
3428 
3429     // These are the pieces of battery state that are packed in to the upper bits of
3430     // the state int that have been packed in to the first delta int.  They must fit
3431     // in STATE_BATTERY_MASK.
3432     static final int STATE_BATTERY_MASK         = 0xff000000;
3433     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
3434     static final int STATE_BATTERY_STATUS_SHIFT = 29;
3435     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
3436     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
3437     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
3438     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
3439 
3440     // We use the low bit of the battery state int to indicate that we have full details
3441     // from a battery level change.
3442     static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
3443 
writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last)3444     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
3445         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
3446             dest.writeInt(DELTA_TIME_ABS);
3447             cur.writeToParcel(dest, 0);
3448             return;
3449         }
3450 
3451         final long deltaTime = cur.time - last.time;
3452         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
3453         final int lastStateInt = buildStateInt(last);
3454 
3455         int deltaTimeToken;
3456         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
3457             deltaTimeToken = DELTA_TIME_LONG;
3458         } else if (deltaTime >= DELTA_TIME_ABS) {
3459             deltaTimeToken = DELTA_TIME_INT;
3460         } else {
3461             deltaTimeToken = (int)deltaTime;
3462         }
3463         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
3464         final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
3465                 ? BATTERY_DELTA_LEVEL_FLAG : 0;
3466         final boolean computeStepDetails = includeStepDetails != 0
3467                 || mLastHistoryStepDetails == null;
3468         final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
3469         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
3470         if (batteryLevelIntChanged) {
3471             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
3472         }
3473         final int stateInt = buildStateInt(cur);
3474         final boolean stateIntChanged = stateInt != lastStateInt;
3475         if (stateIntChanged) {
3476             firstToken |= DELTA_STATE_FLAG;
3477         }
3478         final boolean state2IntChanged = cur.states2 != last.states2;
3479         if (state2IntChanged) {
3480             firstToken |= DELTA_STATE2_FLAG;
3481         }
3482         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3483             firstToken |= DELTA_WAKELOCK_FLAG;
3484         }
3485         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3486             firstToken |= DELTA_EVENT_FLAG;
3487         }
3488 
3489         final boolean batteryChargeChanged = cur.batteryChargeUah != last.batteryChargeUah;
3490         if (batteryChargeChanged) {
3491             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
3492         }
3493         dest.writeInt(firstToken);
3494         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3495                 + " deltaTime=" + deltaTime);
3496 
3497         if (deltaTimeToken >= DELTA_TIME_INT) {
3498             if (deltaTimeToken == DELTA_TIME_INT) {
3499                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
3500                 dest.writeInt((int)deltaTime);
3501             } else {
3502                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
3503                 dest.writeLong(deltaTime);
3504             }
3505         }
3506         if (batteryLevelIntChanged) {
3507             dest.writeInt(batteryLevelInt);
3508             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
3509                     + Integer.toHexString(batteryLevelInt)
3510                     + " batteryLevel=" + cur.batteryLevel
3511                     + " batteryTemp=" + cur.batteryTemperature
3512                     + " batteryVolt=" + (int)cur.batteryVoltage);
3513         }
3514         if (stateIntChanged) {
3515             dest.writeInt(stateInt);
3516             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
3517                     + Integer.toHexString(stateInt)
3518                     + " batteryStatus=" + cur.batteryStatus
3519                     + " batteryHealth=" + cur.batteryHealth
3520                     + " batteryPlugType=" + cur.batteryPlugType
3521                     + " states=0x" + Integer.toHexString(cur.states));
3522         }
3523         if (state2IntChanged) {
3524             dest.writeInt(cur.states2);
3525             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
3526                     + Integer.toHexString(cur.states2));
3527         }
3528         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3529             int wakeLockIndex;
3530             int wakeReasonIndex;
3531             if (cur.wakelockTag != null) {
3532                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
3533                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3534                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3535             } else {
3536                 wakeLockIndex = 0xffff;
3537             }
3538             if (cur.wakeReasonTag != null) {
3539                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
3540                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3541                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3542             } else {
3543                 wakeReasonIndex = 0xffff;
3544             }
3545             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
3546         }
3547         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3548             int index = writeHistoryTag(cur.eventTag);
3549             int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
3550             dest.writeInt(codeAndIndex);
3551             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
3552                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3553                     + cur.eventTag.string);
3554         }
3555         if (computeStepDetails) {
3556             if (mPlatformIdleStateCallback != null) {
3557                 mCurHistoryStepDetails.statSubsystemPowerState =
3558                         mPlatformIdleStateCallback.getSubsystemLowPowerStats();
3559                 if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
3560                         mCurHistoryStepDetails.statSubsystemPowerState);
3561 
3562             }
3563             computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
3564             if (includeStepDetails != 0) {
3565                 mCurHistoryStepDetails.writeToParcel(dest);
3566             }
3567             cur.stepDetails = mCurHistoryStepDetails;
3568             mLastHistoryStepDetails = mCurHistoryStepDetails;
3569         } else {
3570             cur.stepDetails = null;
3571         }
3572         if (mLastHistoryStepLevel < cur.batteryLevel) {
3573             mLastHistoryStepDetails = null;
3574         }
3575         mLastHistoryStepLevel = cur.batteryLevel;
3576 
3577         if (batteryChargeChanged) {
3578             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUah=" + cur.batteryChargeUah);
3579             dest.writeInt(cur.batteryChargeUah);
3580         }
3581         dest.writeDouble(cur.modemRailChargeMah);
3582         dest.writeDouble(cur.wifiRailChargeMah);
3583     }
3584 
buildBatteryLevelInt(HistoryItem h)3585     private int buildBatteryLevelInt(HistoryItem h) {
3586         return ((((int)h.batteryLevel)<<25)&0xfe000000)
3587                 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
3588                 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
3589     }
3590 
readBatteryLevelInt(int batteryLevelInt, HistoryItem out)3591     private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
3592         out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
3593         out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
3594         out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
3595     }
3596 
buildStateInt(HistoryItem h)3597     private int buildStateInt(HistoryItem h) {
3598         int plugType = 0;
3599         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
3600             plugType = 1;
3601         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
3602             plugType = 2;
3603         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
3604             plugType = 3;
3605         }
3606         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
3607                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
3608                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
3609                 | (h.states&(~STATE_BATTERY_MASK));
3610     }
3611 
computeHistoryStepDetails(final HistoryStepDetails out, final HistoryStepDetails last)3612     private void computeHistoryStepDetails(final HistoryStepDetails out,
3613             final HistoryStepDetails last) {
3614         final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
3615 
3616         // Perform a CPU update right after we do this collection, so we have started
3617         // collecting good data for the next step.
3618         requestImmediateCpuUpdate();
3619 
3620         if (last == null) {
3621             // We are not generating a delta, so all we need to do is reset the stats
3622             // we will later be doing a delta from.
3623             final int NU = mUidStats.size();
3624             for (int i=0; i<NU; i++) {
3625                 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3626                 uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
3627                 uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
3628             }
3629             mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
3630             mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
3631             mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
3632             mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
3633             mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
3634             mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
3635             mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
3636             mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
3637             tmp.clear();
3638             return;
3639         }
3640         if (DEBUG) {
3641             Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
3642                     + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
3643                     + " irq=" + mLastStepStatIrqTimeMs + " sirq="
3644                     + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
3645             Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
3646                     + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
3647                     + " irq=" + mCurStepStatIrqTimeMs + " sirq="
3648                     + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
3649         }
3650         out.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
3651         out.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
3652         out.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
3653         out.statSystemTime = (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
3654         out.statIOWaitTime = (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
3655         out.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
3656         out.statSoftIrqTime = (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
3657         out.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
3658         out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
3659         out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
3660         out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
3661         final int NU = mUidStats.size();
3662         for (int i=0; i<NU; i++) {
3663             final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3664             final int totalUTimeMs = (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
3665             final int totalSTimeMs = (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
3666             final int totalTimeMs = totalUTimeMs + totalSTimeMs;
3667             uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
3668             uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
3669             if (totalTimeMs <= (out.appCpuUTime3 + out.appCpuSTime3)) {
3670                 continue;
3671             }
3672             if (totalTimeMs <= (out.appCpuUTime2 + out.appCpuSTime2)) {
3673                 out.appCpuUid3 = uid.mUid;
3674                 out.appCpuUTime3 = totalUTimeMs;
3675                 out.appCpuSTime3 = totalSTimeMs;
3676             } else {
3677                 out.appCpuUid3 = out.appCpuUid2;
3678                 out.appCpuUTime3 = out.appCpuUTime2;
3679                 out.appCpuSTime3 = out.appCpuSTime2;
3680                 if (totalTimeMs <= (out.appCpuUTime1 + out.appCpuSTime1)) {
3681                     out.appCpuUid2 = uid.mUid;
3682                     out.appCpuUTime2 = totalUTimeMs;
3683                     out.appCpuSTime2 = totalSTimeMs;
3684                 } else {
3685                     out.appCpuUid2 = out.appCpuUid1;
3686                     out.appCpuUTime2 = out.appCpuUTime1;
3687                     out.appCpuSTime2 = out.appCpuSTime1;
3688                     out.appCpuUid1 = uid.mUid;
3689                     out.appCpuUTime1 = totalUTimeMs;
3690                     out.appCpuSTime1 = totalSTimeMs;
3691                 }
3692             }
3693         }
3694         mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
3695         mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
3696         mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
3697         mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
3698         mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
3699         mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
3700         mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
3701         mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
3702     }
3703 
3704     @Override
commitCurrentHistoryBatchLocked()3705     public void commitCurrentHistoryBatchLocked() {
3706         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
3707     }
3708 
createFakeHistoryEvents(long numEvents)3709     public void createFakeHistoryEvents(long numEvents) {
3710         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
3711         final long uptimeMs = mClocks.uptimeMillis();
3712         for(long i = 0; i < numEvents; i++) {
3713             noteLongPartialWakelockStart("name1", "historyName1", 1000,
3714                     elapsedRealtimeMs, uptimeMs);
3715             noteLongPartialWakelockFinish("name1", "historyName1", 1000,
3716                     elapsedRealtimeMs, uptimeMs);
3717         }
3718     }
3719 
addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur)3720     void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
3721         if (!mHaveBatteryLevel || !mRecordingHistory) {
3722             return;
3723         }
3724 
3725         final long timeDiffMs = (mHistoryBaseTimeMs + elapsedRealtimeMs) - mHistoryLastWritten.time;
3726         final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
3727         final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
3728         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
3729         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
3730         if (DEBUG) {
3731             Slog.i(TAG, "ADD: tdelta=" + timeDiffMs + " diff="
3732                     + Integer.toHexString(diffStates) + " lastDiff="
3733                     + Integer.toHexString(lastDiffStates) + " diff2="
3734                     + Integer.toHexString(diffStates2) + " lastDiff2="
3735                     + Integer.toHexString(lastDiffStates2));
3736         }
3737         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
3738                 && timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0
3739                 && (diffStates2&lastDiffStates2) == 0
3740                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
3741                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
3742                 && mHistoryLastWritten.stepDetails == null
3743                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
3744                         || cur.eventCode == HistoryItem.EVENT_NONE)
3745                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
3746                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
3747                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
3748                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
3749                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
3750                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
3751             // We can merge this new change in with the last one.  Merging is
3752             // allowed as long as only the states have changed, and within those states
3753             // as long as no bit has changed both between now and the last entry, as
3754             // well as the last entry and the one before it (so we capture any toggles).
3755             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
3756             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
3757             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
3758             mHistoryBufferLastPos = -1;
3759             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTimeMs;
3760             // If the last written history had a wakelock tag, we need to retain it.
3761             // Note that the condition above made sure that we aren't in a case where
3762             // both it and the current history item have a wakelock tag.
3763             if (mHistoryLastWritten.wakelockTag != null) {
3764                 cur.wakelockTag = cur.localWakelockTag;
3765                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
3766             }
3767             // If the last written history had a wake reason tag, we need to retain it.
3768             // Note that the condition above made sure that we aren't in a case where
3769             // both it and the current history item have a wakelock tag.
3770             if (mHistoryLastWritten.wakeReasonTag != null) {
3771                 cur.wakeReasonTag = cur.localWakeReasonTag;
3772                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
3773             }
3774             // If the last written history had an event, we need to retain it.
3775             // Note that the condition above made sure that we aren't in a case where
3776             // both it and the current history item have an event.
3777             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
3778                 cur.eventCode = mHistoryLastWritten.eventCode;
3779                 cur.eventTag = cur.localEventTag;
3780                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
3781             }
3782             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
3783         }
3784         final int dataSize = mHistoryBuffer.dataSize();
3785 
3786         if (dataSize >= mConstants.MAX_HISTORY_BUFFER) {
3787             //open a new history file.
3788             final long start = SystemClock.uptimeMillis();
3789             writeHistoryLocked(true);
3790             if (DEBUG) {
3791                 Slog.d(TAG, "addHistoryBufferLocked writeHistoryLocked takes ms:"
3792                         + (SystemClock.uptimeMillis() - start));
3793             }
3794             mBatteryStatsHistory.startNextFile();
3795             mHistoryBuffer.setDataSize(0);
3796             mHistoryBuffer.setDataPosition(0);
3797             mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
3798             mHistoryBufferLastPos = -1;
3799             HistoryItem newItem = new HistoryItem();
3800             newItem.setTo(cur);
3801             startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
3802             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem);
3803             return;
3804         }
3805 
3806         if (dataSize == 0) {
3807             // The history is currently empty; we need it to start with a time stamp.
3808             cur.currentTime = mClocks.currentTimeMillis();
3809             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
3810         }
3811         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3812     }
3813 
addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur)3814     private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
3815         if (mBatteryStatsHistoryIterator != null) {
3816             throw new IllegalStateException("Can't do this while iterating history!");
3817         }
3818         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
3819         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
3820         mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
3821         mHistoryLastWritten.states &= mActiveHistoryStates;
3822         mHistoryLastWritten.states2 &= mActiveHistoryStates2;
3823         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
3824         mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
3825         cur.wakelockTag = null;
3826         cur.wakeReasonTag = null;
3827         cur.eventCode = HistoryItem.EVENT_NONE;
3828         cur.eventTag = null;
3829         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
3830                 + " now " + mHistoryBuffer.dataPosition()
3831                 + " size is now " + mHistoryBuffer.dataSize());
3832     }
3833 
3834     int mChangedStates = 0;
3835     int mChangedStates2 = 0;
3836 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs)3837     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
3838         if (mTrackRunningHistoryElapsedRealtimeMs != 0) {
3839             final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
3840             final long diffUptimeMs = uptimeMs - mTrackRunningHistoryUptimeMs;
3841             if (diffUptimeMs < (diffElapsedMs - 20)) {
3842                 final long wakeElapsedTimeMs = elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs);
3843                 mHistoryAddTmp.setTo(mHistoryLastWritten);
3844                 mHistoryAddTmp.wakelockTag = null;
3845                 mHistoryAddTmp.wakeReasonTag = null;
3846                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
3847                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
3848                 addHistoryRecordInnerLocked(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp);
3849             }
3850         }
3851         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
3852         mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs;
3853         mTrackRunningHistoryUptimeMs = uptimeMs;
3854         addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
3855     }
3856 
addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur)3857     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
3858         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
3859     }
3860 
addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)3861     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
3862             String name, int uid) {
3863         mHistoryCur.eventCode = code;
3864         mHistoryCur.eventTag = mHistoryCur.localEventTag;
3865         mHistoryCur.eventTag.string = name;
3866         mHistoryCur.eventTag.uid = uid;
3867         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
3868     }
3869 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur)3870     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
3871         HistoryItem rec = mHistoryCache;
3872         if (rec != null) {
3873             mHistoryCache = rec.next;
3874         } else {
3875             rec = new HistoryItem();
3876         }
3877         rec.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
3878 
3879         addHistoryRecordLocked(rec);
3880     }
3881 
addHistoryRecordLocked(HistoryItem rec)3882     void addHistoryRecordLocked(HistoryItem rec) {
3883         mNumHistoryItems++;
3884         rec.next = null;
3885         mHistoryLastEnd = mHistoryEnd;
3886         if (mHistoryEnd != null) {
3887             mHistoryEnd.next = rec;
3888             mHistoryEnd = rec;
3889         } else {
3890             mHistory = mHistoryEnd = rec;
3891         }
3892     }
3893 
clearHistoryLocked()3894     void clearHistoryLocked() {
3895         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
3896         mHistoryBaseTimeMs = 0;
3897         mLastHistoryElapsedRealtimeMs = 0;
3898         mTrackRunningHistoryElapsedRealtimeMs = 0;
3899         mTrackRunningHistoryUptimeMs = 0;
3900 
3901         mHistoryBuffer.setDataSize(0);
3902         mHistoryBuffer.setDataPosition(0);
3903         mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
3904         mHistoryLastLastWritten.clear();
3905         mHistoryLastWritten.clear();
3906         mHistoryTagPool.clear();
3907         mNextHistoryTagIdx = 0;
3908         mNumHistoryTagChars = 0;
3909         mHistoryBufferLastPos = -1;
3910         mActiveHistoryStates = 0xffffffff;
3911         mActiveHistoryStates2 = 0xffffffff;
3912     }
3913 
3914     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs, long realtimeUs)3915     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs,
3916             long realtimeUs) {
3917         final boolean screenOff = !Display.isOnState(screenState);
3918         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
3919         final boolean updateOnBatteryScreenOffTimeBase =
3920                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
3921 
3922         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
3923             if (updateOnBatteryScreenOffTimeBase) {
3924                 updateKernelWakelocksLocked(realtimeUs);
3925                 updateBatteryPropertiesLocked();
3926             }
3927             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
3928             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
3929             // improved, remove the surrounding if{}.
3930             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
3931                 // if either OnBattery or OnBatteryScreenOfftimebase changes.
3932                 updateRpmStatsLocked(realtimeUs);
3933             }
3934             if (DEBUG_ENERGY_CPU) {
3935                 Slog.d(TAG, "Updating cpu time because screen is now "
3936                         + Display.stateToString(screenState)
3937                         + " and battery is " + (unplugged ? "on" : "off"));
3938             }
3939 
3940             mOnBatteryTimeBase.setRunning(unplugged, uptimeUs, realtimeUs);
3941             if (updateOnBatteryTimeBase) {
3942                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3943                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptimeUs, realtimeUs);
3944                 }
3945             }
3946             if (updateOnBatteryScreenOffTimeBase) {
3947                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff,
3948                         uptimeUs, realtimeUs);
3949                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3950                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptimeUs, realtimeUs);
3951                 }
3952             }
3953         }
3954     }
3955 
updateBatteryPropertiesLocked()3956     private void updateBatteryPropertiesLocked() {
3957         try {
3958             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
3959                     ServiceManager.getService("batteryproperties"));
3960             if (registrar != null) {
3961                 registrar.scheduleUpdate();
3962             }
3963         } catch (RemoteException e) {
3964             // Ignore.
3965         }
3966     }
3967 
addIsolatedUidLocked(int isolatedUid, int appUid)3968     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
3969         addIsolatedUidLocked(isolatedUid, appUid,
3970                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
3971     }
3972 
addIsolatedUidLocked(int isolatedUid, int appUid, long elapsedRealtimeMs, long uptimeMs)3973     public void addIsolatedUidLocked(int isolatedUid, int appUid,
3974             long elapsedRealtimeMs, long uptimeMs) {
3975         mIsolatedUids.put(isolatedUid, appUid);
3976         mIsolatedUidRefCounts.put(isolatedUid, 1);
3977         final Uid u = getUidStatsLocked(appUid, elapsedRealtimeMs, uptimeMs);
3978         u.addIsolatedUid(isolatedUid);
3979     }
3980 
3981     /**
3982      * Schedules a read of the latest cpu times before removing the isolated UID.
3983      * @see #removeIsolatedUidLocked(int, int, int)
3984      */
scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid)3985     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
3986         int curUid = mIsolatedUids.get(isolatedUid, -1);
3987         if (curUid == appUid) {
3988             if (mExternalSync != null) {
3989                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
3990             }
3991         }
3992     }
3993 
3994     /**
3995      * Isolated uid should only be removed after all wakelocks associated with the uid are stopped
3996      * and the cpu time-in-state has been read one last time for the uid.
3997      *
3998      * @see #scheduleRemoveIsolatedUidLocked(int, int)
3999      *
4000      * @return true if the isolated uid is actually removed.
4001      */
4002     @GuardedBy("this")
maybeRemoveIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs)4003     public boolean maybeRemoveIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs,
4004             long uptimeMs) {
4005         final int refCount = mIsolatedUidRefCounts.get(isolatedUid, 0) - 1;
4006         if (refCount > 0) {
4007             // Isolated uid is still being tracked
4008             mIsolatedUidRefCounts.put(isolatedUid, refCount);
4009             return false;
4010         }
4011 
4012         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
4013         if (idx >= 0) {
4014             final int ownerUid = mIsolatedUids.valueAt(idx);
4015             final Uid u = getUidStatsLocked(ownerUid, elapsedRealtimeMs, uptimeMs);
4016             u.removeIsolatedUid(isolatedUid);
4017             mIsolatedUids.removeAt(idx);
4018             mIsolatedUidRefCounts.delete(isolatedUid);
4019         } else {
4020             Slog.w(TAG, "Attempted to remove untracked isolated uid (" + isolatedUid + ")");
4021         }
4022         mPendingRemovedUids.add(new UidToRemove(isolatedUid, elapsedRealtimeMs));
4023 
4024         return true;
4025     }
4026 
4027     /**
4028      * Increment the ref count for an isolated uid.
4029      * call #maybeRemoveIsolatedUidLocked to decrement.
4030      */
incrementIsolatedUidRefCount(int uid)4031     public void incrementIsolatedUidRefCount(int uid) {
4032         final int refCount = mIsolatedUidRefCounts.get(uid, 0);
4033         if (refCount <= 0) {
4034             // Uid is not mapped or referenced
4035             Slog.w(TAG,
4036                     "Attempted to increment ref counted of untracked isolated uid (" + uid + ")");
4037             return;
4038         }
4039         mIsolatedUidRefCounts.put(uid, refCount + 1);
4040     }
4041 
mapUid(int uid)4042     public int mapUid(int uid) {
4043         int isolated = mIsolatedUids.get(uid, -1);
4044         return isolated > 0 ? isolated : uid;
4045     }
4046 
noteEventLocked(int code, String name, int uid)4047     public void noteEventLocked(int code, String name, int uid) {
4048         noteEventLocked(code, name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4049     }
4050 
noteEventLocked(int code, String name, int uid, long elapsedRealtimeMs, long uptimeMs)4051     public void noteEventLocked(int code, String name, int uid,
4052             long elapsedRealtimeMs, long uptimeMs) {
4053         uid = mapUid(uid);
4054         if (!mActiveEvents.updateState(code, name, uid, 0)) {
4055             return;
4056         }
4057         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid);
4058     }
4059 
noteCurrentTimeChangedLocked()4060     public void noteCurrentTimeChangedLocked() {
4061         final long currentTime = mClocks.currentTimeMillis();
4062         final long elapsedRealtime = mClocks.elapsedRealtime();
4063         final long uptime = mClocks.uptimeMillis();
4064         noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime);
4065     }
4066 
noteCurrentTimeChangedLocked(long currentTimeMs, long elapsedRealtimeMs, long uptimeMs)4067     public void noteCurrentTimeChangedLocked(long currentTimeMs,
4068             long elapsedRealtimeMs, long uptimeMs) {
4069         recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs);
4070     }
4071 
noteProcessStartLocked(String name, int uid)4072     public void noteProcessStartLocked(String name, int uid) {
4073         noteProcessStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4074     }
4075 
noteProcessStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4076     public void noteProcessStartLocked(String name, int uid,
4077             long elapsedRealtimeMs, long uptimeMs) {
4078         uid = mapUid(uid);
4079         if (isOnBattery()) {
4080             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4081             u.getProcessStatsLocked(name).incStartsLocked();
4082         }
4083         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
4084             return;
4085         }
4086         if (!mRecordAllHistory) {
4087             return;
4088         }
4089         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
4090     }
4091 
noteProcessCrashLocked(String name, int uid)4092     public void noteProcessCrashLocked(String name, int uid) {
4093         noteProcessCrashLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4094     }
4095 
noteProcessCrashLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4096     public void noteProcessCrashLocked(String name, int uid,
4097             long elapsedRealtimeMs, long uptimeMs) {
4098         uid = mapUid(uid);
4099         if (isOnBattery()) {
4100             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4101             u.getProcessStatsLocked(name).incNumCrashesLocked();
4102         }
4103     }
4104 
noteProcessAnrLocked(String name, int uid)4105     public void noteProcessAnrLocked(String name, int uid) {
4106         noteProcessAnrLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4107     }
4108 
noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4109     public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4110         uid = mapUid(uid);
4111         if (isOnBattery()) {
4112             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4113             u.getProcessStatsLocked(name).incNumAnrsLocked();
4114         }
4115     }
4116 
noteUidProcessStateLocked(int uid, int state)4117     public void noteUidProcessStateLocked(int uid, int state) {
4118         noteUidProcessStateLocked(uid, state, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4119     }
4120 
noteUidProcessStateLocked(int uid, int state, long elapsedRealtimeMs, long uptimeMs)4121     public void noteUidProcessStateLocked(int uid, int state,
4122             long elapsedRealtimeMs, long uptimeMs) {
4123         int parentUid = mapUid(uid);
4124         if (uid != parentUid) {
4125             // Isolated UIDs process state is already rolled up into parent, so no need to track
4126             // Otherwise the parent's process state will get downgraded incorrectly
4127             return;
4128         }
4129         // TODO(b/155216561): It is possible for isolated uids to be in a higher
4130         // state than its parent uid. We should track the highest state within the union of host
4131         // and isolated uids rather than only the parent uid.
4132         FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
4133                 ActivityManager.processStateAmToProto(state));
4134         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4135                 .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs);
4136     }
4137 
noteProcessFinishLocked(String name, int uid)4138     public void noteProcessFinishLocked(String name, int uid) {
4139         noteProcessFinishLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4140     }
4141 
noteProcessFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4142     public void noteProcessFinishLocked(String name, int uid,
4143             long elapsedRealtimeMs, long uptimeMs) {
4144         uid = mapUid(uid);
4145         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4146             return;
4147         }
4148         if (!mRecordAllHistory) {
4149             return;
4150         }
4151         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH,
4152                 name, uid);
4153     }
4154 
noteSyncStartLocked(String name, int uid)4155     public void noteSyncStartLocked(String name, int uid) {
4156         noteSyncStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4157     }
4158 
noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4159     public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4160         uid = mapUid(uid);
4161         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4162                 .noteStartSyncLocked(name, elapsedRealtimeMs);
4163         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4164             return;
4165         }
4166         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
4167     }
4168 
noteSyncFinishLocked(String name, int uid)4169     public void noteSyncFinishLocked(String name, int uid) {
4170         noteSyncFinishLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4171     }
4172 
noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4173     public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4174         uid = mapUid(uid);
4175         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4176                 .noteStopSyncLocked(name, elapsedRealtimeMs);
4177         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4178             return;
4179         }
4180         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH,
4181                 name, uid);
4182     }
4183 
noteJobStartLocked(String name, int uid)4184     public void noteJobStartLocked(String name, int uid) {
4185         noteJobStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4186     }
4187 
noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4188     public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4189         uid = mapUid(uid);
4190         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4191                 .noteStartJobLocked(name, elapsedRealtimeMs);
4192         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4193             return;
4194         }
4195         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
4196     }
4197 
noteJobFinishLocked(String name, int uid, int stopReason)4198     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4199         noteJobFinishLocked(name, uid, stopReason,
4200                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4201     }
4202 
noteJobFinishLocked(String name, int uid, int stopReason, long elapsedRealtimeMs, long uptimeMs)4203     public void noteJobFinishLocked(String name, int uid, int stopReason,
4204             long elapsedRealtimeMs, long uptimeMs) {
4205         uid = mapUid(uid);
4206         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4207                 .noteStopJobLocked(name, elapsedRealtimeMs, stopReason);
4208         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4209             return;
4210         }
4211         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
4212     }
4213 
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast)4214     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
4215         noteJobsDeferredLocked(uid, numDeferred, sinceLast,
4216                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4217     }
4218 
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast, long elapsedRealtimeMs, long uptimeMs)4219     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast,
4220             long elapsedRealtimeMs, long uptimeMs) {
4221         uid = mapUid(uid);
4222         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4223                 .noteJobsDeferredLocked(numDeferred, sinceLast);
4224     }
4225 
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4226     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4227         noteAlarmStartLocked(name, workSource, uid,
4228                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4229     }
4230 
noteAlarmStartLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4231     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid,
4232             long elapsedRealtimeMs, long uptimeMs) {
4233         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid,
4234                 elapsedRealtimeMs, uptimeMs);
4235     }
4236 
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)4237     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4238         noteAlarmFinishLocked(name, workSource, uid,
4239                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4240     }
4241 
noteAlarmFinishLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4242     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid,
4243             long elapsedRealtimeMs, long uptimeMs) {
4244         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid,
4245                 elapsedRealtimeMs, uptimeMs);
4246     }
4247 
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid)4248     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4249             int uid) {
4250         noteAlarmStartOrFinishLocked(historyItem, name, workSource, uid,
4251                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4252     }
4253 
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4254     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4255             int uid, long elapsedRealtimeMs, long uptimeMs) {
4256         if (!mRecordAllHistory) {
4257             return;
4258         }
4259 
4260         if (workSource != null) {
4261             for (int i = 0; i < workSource.size(); ++i) {
4262                 uid = mapUid(workSource.getUid(i));
4263                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4264                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4265                 }
4266             }
4267 
4268             List<WorkChain> workChains = workSource.getWorkChains();
4269             if (workChains != null) {
4270                 for (int i = 0; i < workChains.size(); ++i) {
4271                     uid = mapUid(workChains.get(i).getAttributionUid());
4272                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4273                         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4274                     }
4275                 }
4276             }
4277         } else {
4278             uid = mapUid(uid);
4279 
4280             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4281                 addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4282             }
4283         }
4284     }
4285 
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)4286     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4287             String tag) {
4288         noteWakupAlarmLocked(packageName, uid, workSource, tag,
4289                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4290     }
4291 
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag, long elapsedRealtimeMs, long uptimeMs)4292     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4293             String tag, long elapsedRealtimeMs, long uptimeMs) {
4294         if (workSource != null) {
4295             for (int i = 0; i < workSource.size(); ++i) {
4296                 uid = workSource.getUid(i);
4297                 final String workSourceName = workSource.getPackageName(i);
4298 
4299                 if (isOnBattery()) {
4300                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4301                             workSourceName != null ? workSourceName : packageName,
4302                             elapsedRealtimeMs, uptimeMs);
4303                     pkg.noteWakeupAlarmLocked(tag);
4304                 }
4305             }
4306 
4307             List<WorkChain> workChains = workSource.getWorkChains();
4308             if (workChains != null) {
4309                 for (int i = 0; i < workChains.size(); ++i) {
4310                     final WorkChain wc = workChains.get(i);
4311                     uid = wc.getAttributionUid();
4312 
4313                     if (isOnBattery()) {
4314                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4315                                 elapsedRealtimeMs, uptimeMs);
4316                         pkg.noteWakeupAlarmLocked(tag);
4317                     }
4318                 }
4319             }
4320         } else {
4321             if (isOnBattery()) {
4322                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4323                         elapsedRealtimeMs, uptimeMs);
4324                 pkg.noteWakeupAlarmLocked(tag);
4325             }
4326         }
4327     }
4328 
requestWakelockCpuUpdate()4329     private void requestWakelockCpuUpdate() {
4330         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4331     }
4332 
requestImmediateCpuUpdate()4333     private void requestImmediateCpuUpdate() {
4334         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4335     }
4336 
setRecordAllHistoryLocked(boolean enabled)4337     public void setRecordAllHistoryLocked(boolean enabled) {
4338         mRecordAllHistory = enabled;
4339         if (!enabled) {
4340             // Clear out any existing state.
4341             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4342             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4343             // Record the currently running processes as stopping, now that we are no
4344             // longer tracking them.
4345             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4346                     HistoryItem.EVENT_PROC);
4347             if (active != null) {
4348                 long mSecRealtime = mClocks.elapsedRealtime();
4349                 final long mSecUptime = mClocks.uptimeMillis();
4350                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4351                     SparseIntArray uids = ent.getValue();
4352                     for (int j=0; j<uids.size(); j++) {
4353                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4354                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4355                     }
4356                 }
4357             }
4358         } else {
4359             // Record the currently running processes as starting, now that we are tracking them.
4360             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4361                     HistoryItem.EVENT_PROC);
4362             if (active != null) {
4363                 long mSecRealtime = mClocks.elapsedRealtime();
4364                 final long mSecUptime = mClocks.uptimeMillis();
4365                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4366                     SparseIntArray uids = ent.getValue();
4367                     for (int j=0; j<uids.size(); j++) {
4368                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4369                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
4370                     }
4371                 }
4372             }
4373         }
4374     }
4375 
setNoAutoReset(boolean enabled)4376     public void setNoAutoReset(boolean enabled) {
4377         mNoAutoReset = enabled;
4378     }
4379 
setPretendScreenOff(boolean pretendScreenOff)4380     public void setPretendScreenOff(boolean pretendScreenOff) {
4381         if (mPretendScreenOff != pretendScreenOff) {
4382             mPretendScreenOff = pretendScreenOff;
4383             final int primaryScreenState = mPerDisplayBatteryStats[0].screenState;
4384             noteScreenStateLocked(0, primaryScreenState,
4385                     mClocks.elapsedRealtime(), mClocks.uptimeMillis(),
4386                     mClocks.currentTimeMillis());
4387         }
4388     }
4389 
4390     private String mInitialAcquireWakeName;
4391     private int mInitialAcquireWakeUid = -1;
4392 
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging)4393     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4394             int type, boolean unimportantForLogging) {
4395         noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging,
4396                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4397     }
4398 
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)4399     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4400             int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) {
4401         final int mappedUid = mapUid(uid);
4402         if (type == WAKE_TYPE_PARTIAL) {
4403             // Only care about partial wake locks, since full wake locks
4404             // will be canceled when the user puts the screen to sleep.
4405             aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
4406             if (historyName == null) {
4407                 historyName = name;
4408             }
4409             if (mRecordAllHistory) {
4410                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
4411                         mappedUid, 0)) {
4412                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
4413                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, mappedUid);
4414                 }
4415             }
4416             if (mWakeLockNesting == 0) {
4417                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
4418                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
4419                         + Integer.toHexString(mHistoryCur.states));
4420                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4421                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4422                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = mappedUid;
4423                 mWakeLockImportant = !unimportantForLogging;
4424                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4425             } else if (!mWakeLockImportant && !unimportantForLogging
4426                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
4427                 if (mHistoryLastWritten.wakelockTag != null) {
4428                     // We'll try to update the last tag.
4429                     mHistoryLastWritten.wakelockTag = null;
4430                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4431                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4432                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = mappedUid;
4433                     addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4434                 }
4435                 mWakeLockImportant = true;
4436             }
4437             mWakeLockNesting++;
4438         }
4439         if (mappedUid >= 0) {
4440             if (mappedUid != uid) {
4441                 // Prevent the isolated uid mapping from being removed while the wakelock is
4442                 // being held.
4443                 incrementIsolatedUidRefCount(uid);
4444             }
4445             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4446                 // We only update the cpu time when a wake lock is acquired if the screen is off.
4447                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
4448                 if (DEBUG_ENERGY_CPU) {
4449                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
4450                 }
4451                 requestWakelockCpuUpdate();
4452             }
4453 
4454             getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs)
4455                     .noteStartWakeLocked(pid, name, type, elapsedRealtimeMs);
4456 
4457             if (wc != null) {
4458                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
4459                         wc.getTags(), getPowerManagerWakeLockLevel(type), name,
4460                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4461             } else {
4462                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED,
4463                         mappedUid, null, getPowerManagerWakeLockLevel(type), name,
4464                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4465             }
4466         }
4467     }
4468 
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type)4469     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4470             int type) {
4471         noteStopWakeLocked(uid, pid, wc, name, historyName, type,
4472                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4473     }
4474 
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)4475     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4476             int type, long elapsedRealtimeMs, long uptimeMs) {
4477         final int mappedUid = mapUid(uid);
4478         if (type == WAKE_TYPE_PARTIAL) {
4479             mWakeLockNesting--;
4480             if (mRecordAllHistory) {
4481                 if (historyName == null) {
4482                     historyName = name;
4483                 }
4484                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
4485                         mappedUid, 0)) {
4486                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
4487                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid);
4488                 }
4489             }
4490             if (mWakeLockNesting == 0) {
4491                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
4492                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
4493                         + Integer.toHexString(mHistoryCur.states));
4494                 mInitialAcquireWakeName = null;
4495                 mInitialAcquireWakeUid = -1;
4496                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4497             }
4498         }
4499         if (mappedUid >= 0) {
4500             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4501                 if (DEBUG_ENERGY_CPU) {
4502                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
4503                 }
4504                 requestWakelockCpuUpdate();
4505             }
4506 
4507             getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs)
4508                     .noteStopWakeLocked(pid, name, type, elapsedRealtimeMs);
4509             if (wc != null) {
4510                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
4511                         wc.getTags(), getPowerManagerWakeLockLevel(type), name,
4512                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4513             } else {
4514                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED,
4515                         mappedUid, null, getPowerManagerWakeLockLevel(type), name,
4516                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4517             }
4518 
4519             if (mappedUid != uid) {
4520                 // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
4521                 maybeRemoveIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
4522             }
4523         }
4524     }
4525 
4526     /**
4527      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
4528      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
4529      * These are estimations, since batterystats loses some of the original data.
4530      * TODO: Delete this. Instead, FrameworkStatsLog.write should be called from
4531      * PowerManager's Notifier.
4532      */
getPowerManagerWakeLockLevel(int battertStatsWakelockType)4533     private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
4534         switch (battertStatsWakelockType) {
4535             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
4536             case BatteryStats.WAKE_TYPE_PARTIAL:
4537                 return PowerManager.PARTIAL_WAKE_LOCK;
4538 
4539             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
4540             case BatteryStats.WAKE_TYPE_FULL:
4541                 return PowerManager.FULL_WAKE_LOCK;
4542 
4543             case BatteryStats.WAKE_TYPE_DRAW:
4544                 return PowerManager.DRAW_WAKE_LOCK;
4545 
4546             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
4547             case BatteryStats.WAKE_TYPE_WINDOW:
4548                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
4549                 return -1;
4550 
4551             default:
4552                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
4553                 return -1;
4554         }
4555     }
4556 
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging)4557     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4558             String historyName, int type, boolean unimportantForLogging) {
4559         noteStartWakeFromSourceLocked(ws, pid, name, historyName, type, unimportantForLogging,
4560                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4561     }
4562 
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)4563     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4564             String historyName, int type, boolean unimportantForLogging,
4565             long elapsedRealtimeMs, long uptimeMs) {
4566         final int N = ws.size();
4567         for (int i=0; i<N; i++) {
4568             noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
4569                     unimportantForLogging, elapsedRealtimeMs, uptimeMs);
4570         }
4571 
4572         List<WorkChain> wcs = ws.getWorkChains();
4573         if (wcs != null) {
4574             for (int i = 0; i < wcs.size(); ++i) {
4575                 final WorkChain wc = wcs.get(i);
4576                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4577                         unimportantForLogging, elapsedRealtimeMs, uptimeMs);
4578             }
4579         }
4580     }
4581 
noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging)4582     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4583             String historyName, int type, WorkSource newWs, int newPid, String newName,
4584             String newHistoryName, int newType, boolean newUnimportantForLogging) {
4585         noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type, newWs, newPid,
4586                 newName, newHistoryName, newType, newUnimportantForLogging,
4587                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4588     }
4589 
noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging, long elapsedRealtimeMs, long uptimeMs)4590     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4591             String historyName, int type, WorkSource newWs, int newPid, String newName,
4592             String newHistoryName, int newType, boolean newUnimportantForLogging,
4593             long elapsedRealtimeMs, long uptimeMs) {
4594         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
4595 
4596         // For correct semantics, we start the need worksources first, so that we won't
4597         // make inappropriate history items as if all wake locks went away and new ones
4598         // appeared.  This is okay because tracking of wake locks allows nesting.
4599         //
4600         // First the starts :
4601         final int NN = newWs.size();
4602         for (int i=0; i<NN; i++) {
4603             noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
4604                     newUnimportantForLogging, elapsedRealtimeMs, uptimeMs);
4605         }
4606         if (wcs != null) {
4607             List<WorkChain> newChains = wcs[0];
4608             if (newChains != null) {
4609                 for (int i = 0; i < newChains.size(); ++i) {
4610                     final WorkChain newChain = newChains.get(i);
4611                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
4612                             newHistoryName, newType, newUnimportantForLogging, elapsedRealtimeMs,
4613                             uptimeMs);
4614                 }
4615             }
4616         }
4617 
4618         // Then the stops :
4619         final int NO = ws.size();
4620         for (int i=0; i<NO; i++) {
4621             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
4622                     uptimeMs);
4623         }
4624         if (wcs != null) {
4625             List<WorkChain> goneChains = wcs[1];
4626             if (goneChains != null) {
4627                 for (int i = 0; i < goneChains.size(); ++i) {
4628                     final WorkChain goneChain = goneChains.get(i);
4629                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
4630                             historyName, type, elapsedRealtimeMs, uptimeMs);
4631                 }
4632             }
4633         }
4634     }
4635 
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type)4636     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4637             String historyName, int type) {
4638         noteStopWakeFromSourceLocked(ws, pid, name, historyName, type,
4639                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4640     }
4641 
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)4642     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4643             String historyName, int type, long elapsedRealtimeMs, long uptimeMs) {
4644         final int N = ws.size();
4645         for (int i=0; i<N; i++) {
4646             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
4647                     uptimeMs);
4648         }
4649 
4650         List<WorkChain> wcs = ws.getWorkChains();
4651         if (wcs != null) {
4652             for (int i = 0; i < wcs.size(); ++i) {
4653                 final WorkChain wc = wcs.get(i);
4654                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4655                         elapsedRealtimeMs, uptimeMs);
4656             }
4657         }
4658     }
4659 
noteLongPartialWakelockStart(String name, String historyName, int uid)4660     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
4661         noteLongPartialWakelockStart(name, historyName, uid,
4662                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4663     }
4664 
noteLongPartialWakelockStart(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)4665     public void noteLongPartialWakelockStart(String name, String historyName, int uid,
4666             long elapsedRealtimeMs, long uptimeMs) {
4667         uid = mapUid(uid);
4668         noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
4669     }
4670 
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource)4671     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4672             WorkSource workSource) {
4673         noteLongPartialWakelockStartFromSource(name, historyName, workSource,
4674                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4675     }
4676 
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)4677     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4678             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
4679         final int N = workSource.size();
4680         for (int i = 0; i < N; ++i) {
4681             final int uid = mapUid(workSource.getUid(i));
4682             noteLongPartialWakeLockStartInternal(name, historyName, uid,
4683                     elapsedRealtimeMs, uptimeMs);
4684         }
4685 
4686         final List<WorkChain> workChains = workSource.getWorkChains();
4687         if (workChains != null) {
4688             for (int i = 0; i < workChains.size(); ++i) {
4689                 final WorkChain workChain = workChains.get(i);
4690                 final int uid = workChain.getAttributionUid();
4691                 noteLongPartialWakeLockStartInternal(name, historyName, uid,
4692                         elapsedRealtimeMs, uptimeMs);
4693             }
4694         }
4695     }
4696 
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)4697     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid,
4698             long elapsedRealtimeMs, long uptimeMs) {
4699         if (historyName == null) {
4700             historyName = name;
4701         }
4702         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
4703                 0)) {
4704             return;
4705         }
4706         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
4707                 historyName, uid);
4708     }
4709 
noteLongPartialWakelockFinish(String name, String historyName, int uid)4710     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
4711         noteLongPartialWakelockFinish(name, historyName, uid,
4712                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4713     }
4714 
noteLongPartialWakelockFinish(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)4715     public void noteLongPartialWakelockFinish(String name, String historyName, int uid,
4716             long elapsedRealtimeMs, long uptimeMs) {
4717         uid = mapUid(uid);
4718         noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
4719     }
4720 
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource)4721     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
4722             WorkSource workSource) {
4723         noteLongPartialWakelockFinishFromSource(name, historyName, workSource,
4724                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4725     }
4726 
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)4727     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
4728             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
4729         final int N = workSource.size();
4730         for (int i = 0; i < N; ++i) {
4731             final int uid = mapUid(workSource.getUid(i));
4732             noteLongPartialWakeLockFinishInternal(name, historyName, uid,
4733                     elapsedRealtimeMs, uptimeMs);
4734         }
4735 
4736         final List<WorkChain> workChains = workSource.getWorkChains();
4737         if (workChains != null) {
4738             for (int i = 0; i < workChains.size(); ++i) {
4739                 final WorkChain workChain = workChains.get(i);
4740                 final int uid = workChain.getAttributionUid();
4741                 noteLongPartialWakeLockFinishInternal(name, historyName, uid,
4742                         elapsedRealtimeMs, uptimeMs);
4743             }
4744         }
4745     }
4746 
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)4747     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid,
4748             long elapsedRealtimeMs, long uptimeMs) {
4749         if (historyName == null) {
4750             historyName = name;
4751         }
4752         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
4753                 0)) {
4754             return;
4755         }
4756         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
4757                 historyName, uid);
4758     }
4759 
aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs)4760     void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) {
4761         if (mLastWakeupReason != null) {
4762             long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs;
4763             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
4764             timer.add(deltaUptimeMs * 1000, 1, elapsedRealtimeMs); // time in in microseconds
4765             FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
4766                     /* duration_usec */ deltaUptimeMs * 1000);
4767             mLastWakeupReason = null;
4768         }
4769     }
4770 
noteWakeupReasonLocked(String reason)4771     public void noteWakeupReasonLocked(String reason) {
4772         noteWakeupReasonLocked(reason, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4773     }
4774 
noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs)4775     public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
4776         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
4777                 + Integer.toHexString(mHistoryCur.states));
4778         aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
4779         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
4780         mHistoryCur.wakeReasonTag.string = reason;
4781         mHistoryCur.wakeReasonTag.uid = 0;
4782         mLastWakeupReason = reason;
4783         mLastWakeupUptimeMs = uptimeMs;
4784         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4785     }
4786 
startAddingCpuLocked()4787     public boolean startAddingCpuLocked() {
4788         mExternalSync.cancelCpuSyncDueToWakelockChange();
4789         return mOnBatteryInternal;
4790     }
4791 
finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs)4792     public void finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
4793                                       int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
4794                                       int statSoftIrqTimeMs, int statIdleTimeMs) {
4795         if (DEBUG) {
4796             Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
4797                     + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
4798                     + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
4799                     + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
4800         }
4801         mCurStepCpuUserTimeMs += totalUTimeMs;
4802         mCurStepCpuSystemTimeMs += totalSTimeMs;
4803         mCurStepStatUserTimeMs += statUserTimeMs;
4804         mCurStepStatSystemTimeMs += statSystemTimeMs;
4805         mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
4806         mCurStepStatIrqTimeMs += statIrqTimeMs;
4807         mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
4808         mCurStepStatIdleTimeMs += statIdleTimeMs;
4809     }
4810 
noteProcessDiedLocked(int uid, int pid)4811     public void noteProcessDiedLocked(int uid, int pid) {
4812         uid = mapUid(uid);
4813         Uid u = mUidStats.get(uid);
4814         if (u != null) {
4815             u.mPids.remove(pid);
4816         }
4817     }
4818 
getProcessWakeTime(int uid, int pid, long realtimeMs)4819     public long getProcessWakeTime(int uid, int pid, long realtimeMs) {
4820         uid = mapUid(uid);
4821         Uid u = mUidStats.get(uid);
4822         if (u != null) {
4823             Uid.Pid p = u.mPids.get(pid);
4824             if (p != null) {
4825                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtimeMs - p.mWakeStartMs) : 0);
4826             }
4827         }
4828         return 0;
4829     }
4830 
reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs)4831     public void reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs) {
4832         uid = mapUid(uid);
4833         Uid u = mUidStats.get(uid);
4834         if (u != null) {
4835             u.reportExcessiveCpuLocked(proc, overTimeMs, usedTimeMs);
4836         }
4837     }
4838 
4839     int mSensorNesting;
4840 
noteStartSensorLocked(int uid, int sensor)4841     public void noteStartSensorLocked(int uid, int sensor) {
4842         noteStartSensorLocked(uid, sensor, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4843     }
4844 
noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)4845     public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
4846         uid = mapUid(uid);
4847         if (mSensorNesting == 0) {
4848             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
4849             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
4850                     + Integer.toHexString(mHistoryCur.states));
4851             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4852         }
4853         mSensorNesting++;
4854         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4855                 .noteStartSensor(sensor, elapsedRealtimeMs);
4856     }
4857 
noteStopSensorLocked(int uid, int sensor)4858     public void noteStopSensorLocked(int uid, int sensor) {
4859         noteStopSensorLocked(uid, sensor, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4860     }
4861 
noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)4862     public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
4863         uid = mapUid(uid);
4864         mSensorNesting--;
4865         if (mSensorNesting == 0) {
4866             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
4867             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
4868                     + Integer.toHexString(mHistoryCur.states));
4869             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4870         }
4871         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4872                 .noteStopSensor(sensor, elapsedRealtimeMs);
4873     }
4874 
4875     int mGpsNesting;
4876 
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)4877     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
4878         noteGpsChangedLocked(oldWs, newWs, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4879     }
4880 
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)4881     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs,
4882             long elapsedRealtimeMs, long uptimeMs) {
4883         for (int i = 0; i < newWs.size(); ++i) {
4884             noteStartGpsLocked(newWs.getUid(i), null, elapsedRealtimeMs, uptimeMs);
4885         }
4886 
4887         for (int i = 0; i < oldWs.size(); ++i) {
4888             noteStopGpsLocked((oldWs.getUid(i)), null, elapsedRealtimeMs, uptimeMs);
4889         }
4890 
4891         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
4892         if (wcs != null) {
4893             if (wcs[0] != null) {
4894                 final List<WorkChain> newChains = wcs[0];
4895                 for (int i = 0; i < newChains.size(); ++i) {
4896                     noteStartGpsLocked(-1, newChains.get(i), elapsedRealtimeMs, uptimeMs);
4897                 }
4898             }
4899 
4900             if (wcs[1] != null) {
4901                 final List<WorkChain> goneChains = wcs[1];
4902                 for (int i = 0; i < goneChains.size(); ++i) {
4903                     noteStopGpsLocked(-1, goneChains.get(i), elapsedRealtimeMs, uptimeMs);
4904                 }
4905             }
4906         }
4907     }
4908 
noteStartGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)4909     private void noteStartGpsLocked(int uid, WorkChain workChain,
4910             long elapsedRealtimeMs, long uptimeMs) {
4911         uid = getAttributionUid(uid, workChain);
4912         if (mGpsNesting == 0) {
4913             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
4914             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
4915                     + Integer.toHexString(mHistoryCur.states));
4916             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4917         }
4918         mGpsNesting++;
4919 
4920         if (workChain == null) {
4921             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4922                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4923         } else {
4924             FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
4925                     workChain.getUids(), workChain.getTags(),
4926                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4927         }
4928 
4929         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
4930     }
4931 
noteStopGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)4932     private void noteStopGpsLocked(int uid, WorkChain workChain,
4933             long elapsedRealtimeMs, long uptimeMs) {
4934         uid = getAttributionUid(uid, workChain);
4935         mGpsNesting--;
4936         if (mGpsNesting == 0) {
4937             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
4938             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
4939                     + Integer.toHexString(mHistoryCur.states));
4940             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4941             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
4942             mGpsSignalQualityBin = -1;
4943         }
4944 
4945         if (workChain == null) {
4946             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4947                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4948         } else {
4949             FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
4950                     workChain.getTags(), FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4951         }
4952 
4953         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
4954     }
4955 
noteGpsSignalQualityLocked(int signalLevel)4956     public void noteGpsSignalQualityLocked(int signalLevel) {
4957         noteGpsSignalQualityLocked(signalLevel, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4958     }
4959 
noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs)4960     public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) {
4961         if (mGpsNesting == 0) {
4962             return;
4963         }
4964         if (signalLevel < 0 || signalLevel >= mGpsSignalQualityTimer.length) {
4965             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
4966             return;
4967         }
4968         if (mGpsSignalQualityBin != signalLevel) {
4969             if (mGpsSignalQualityBin >= 0) {
4970                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtimeMs);
4971             }
4972             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
4973                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
4974             }
4975             mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
4976                     | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
4977             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4978             mGpsSignalQualityBin = signalLevel;
4979         }
4980         return;
4981     }
4982 
4983     @GuardedBy("this")
noteScreenStateLocked(int display, int state)4984     public void noteScreenStateLocked(int display, int state) {
4985         noteScreenStateLocked(display, state, mClocks.elapsedRealtime(), mClocks.uptimeMillis(),
4986                 mClocks.currentTimeMillis());
4987     }
4988 
4989     @GuardedBy("this")
noteScreenStateLocked(int display, int displayState, long elapsedRealtimeMs, long uptimeMs, long currentTimeMs)4990     public void noteScreenStateLocked(int display, int displayState,
4991             long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
4992         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
4993         // original 4 are mapped to one of the originals.
4994         if (displayState > MAX_TRACKED_SCREEN_STATE) {
4995             if (Display.isOnState(displayState)) {
4996                 displayState = Display.STATE_ON;
4997             } else if (Display.isDozeState(displayState)) {
4998                 if (Display.isSuspendedState(displayState)) {
4999                     displayState = Display.STATE_DOZE_SUSPEND;
5000                 } else {
5001                     displayState = Display.STATE_DOZE;
5002                 }
5003             } else if (Display.isOffState(displayState)) {
5004                 displayState = Display.STATE_OFF;
5005             } else {
5006                 Slog.wtf(TAG, "Unknown screen state (not mapped): " + displayState);
5007                 displayState = Display.STATE_UNKNOWN;
5008             }
5009         }
5010         // As of this point, displayState should be mapped to one of:
5011         //  - Display.STATE_ON,
5012         //  - Display.STATE_DOZE
5013         //  - Display.STATE_DOZE_SUSPEND
5014         //  - Display.STATE_OFF
5015         //  - Display.STATE_UNKNOWN
5016 
5017         int state;
5018         int overallBin = mScreenBrightnessBin;
5019         int externalUpdateFlag = 0;
5020         boolean shouldScheduleSync = false;
5021         final int numDisplay = mPerDisplayBatteryStats.length;
5022         if (display < 0 || display >= numDisplay) {
5023             Slog.wtf(TAG, "Unexpected note screen state for display " + display + " (only "
5024                     + mPerDisplayBatteryStats.length + " displays exist...)");
5025             return;
5026         }
5027         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5028         final int oldDisplayState = displayStats.screenState;
5029 
5030         if (oldDisplayState == displayState) {
5031             // Nothing changed
5032             state = mScreenState;
5033         } else {
5034             displayStats.screenState = displayState;
5035 
5036             // Stop timer for previous display state.
5037             switch (oldDisplayState) {
5038                 case Display.STATE_ON:
5039                     displayStats.screenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5040                     final int bin = displayStats.screenBrightnessBin;
5041                     if (bin >= 0) {
5042                         displayStats.screenBrightnessTimers[bin].stopRunningLocked(
5043                                 elapsedRealtimeMs);
5044                     }
5045                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5046                     shouldScheduleSync = true;
5047                     break;
5048                 case Display.STATE_DOZE:
5049                     // Transition from doze to doze suspend can be ignored.
5050                     if (displayState == Display.STATE_DOZE_SUSPEND) break;
5051                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5052                     shouldScheduleSync = true;
5053                     break;
5054                 case Display.STATE_DOZE_SUSPEND:
5055                     // Transition from doze suspend to doze can be ignored.
5056                     if (displayState == Display.STATE_DOZE) break;
5057                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5058                     shouldScheduleSync = true;
5059                     break;
5060                 case Display.STATE_OFF: // fallthrough
5061                 case Display.STATE_UNKNOWN:
5062                     // Not tracked by timers.
5063                     break;
5064                 default:
5065                     Slog.wtf(TAG,
5066                             "Attempted to stop timer for unexpected display state " + display);
5067             }
5068 
5069             // Start timer for new display state.
5070             switch (displayState) {
5071                 case Display.STATE_ON:
5072                     displayStats.screenOnTimer.startRunningLocked(elapsedRealtimeMs);
5073                     final int bin = displayStats.screenBrightnessBin;
5074                     if (bin >= 0) {
5075                         displayStats.screenBrightnessTimers[bin].startRunningLocked(
5076                                 elapsedRealtimeMs);
5077                     }
5078                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5079                     shouldScheduleSync = true;
5080                     break;
5081                 case Display.STATE_DOZE:
5082                     // Transition from doze suspend to doze can be ignored.
5083                     if (oldDisplayState == Display.STATE_DOZE_SUSPEND) break;
5084                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5085                     shouldScheduleSync = true;
5086                     break;
5087                 case Display.STATE_DOZE_SUSPEND:
5088                     // Transition from doze to doze suspend can be ignored.
5089                     if (oldDisplayState == Display.STATE_DOZE) break;
5090                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5091                     shouldScheduleSync = true;
5092                     break;
5093                 case Display.STATE_OFF: // fallthrough
5094                 case Display.STATE_UNKNOWN:
5095                     // Not tracked by timers.
5096                     break;
5097                 default:
5098                     Slog.wtf(TAG,
5099                             "Attempted to start timer for unexpected display state " + displayState
5100                                     + " for display " + display);
5101             }
5102 
5103             if (shouldScheduleSync
5104                     && mGlobalMeasuredEnergyStats != null
5105                     && mGlobalMeasuredEnergyStats.isStandardBucketSupported(
5106                     MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON)) {
5107                 // Display measured energy stats is available. Prepare to schedule an
5108                 // external sync.
5109                 externalUpdateFlag |= ExternalStatsSync.UPDATE_DISPLAY;
5110             }
5111 
5112             // Reevaluate most important display screen state.
5113             state = Display.STATE_UNKNOWN;
5114             for (int i = 0; i < numDisplay; i++) {
5115                 final int tempState = mPerDisplayBatteryStats[i].screenState;
5116                 if (tempState == Display.STATE_ON
5117                         || state == Display.STATE_ON) {
5118                     state = Display.STATE_ON;
5119                 } else if (tempState == Display.STATE_DOZE
5120                         || state == Display.STATE_DOZE) {
5121                     state = Display.STATE_DOZE;
5122                 } else if (tempState == Display.STATE_DOZE_SUSPEND
5123                         || state == Display.STATE_DOZE_SUSPEND) {
5124                     state = Display.STATE_DOZE_SUSPEND;
5125                 } else if (tempState == Display.STATE_OFF
5126                         || state == Display.STATE_OFF) {
5127                     state = Display.STATE_OFF;
5128                 }
5129             }
5130         }
5131 
5132         final boolean batteryRunning = mOnBatteryTimeBase.isRunning();
5133         final boolean batteryScreenOffRunning = mOnBatteryScreenOffTimeBase.isRunning();
5134 
5135         state = mPretendScreenOff ? Display.STATE_OFF : state;
5136         if (mScreenState != state) {
5137             recordDailyStatsIfNeededLocked(true, currentTimeMs);
5138             final int oldState = mScreenState;
5139             mScreenState = state;
5140             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
5141                     + ", newState=" + Display.stateToString(state));
5142 
5143             if (state != Display.STATE_UNKNOWN) {
5144                 int stepState = state-1;
5145                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
5146                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
5147                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
5148                 } else {
5149                     Slog.wtf(TAG, "Unexpected screen state: " + state);
5150                 }
5151             }
5152 
5153             boolean updateHistory = false;
5154             if (Display.isDozeState(state) && !Display.isDozeState(oldState)) {
5155                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
5156                 mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5157                 updateHistory = true;
5158             } else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) {
5159                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
5160                 mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5161                 updateHistory = true;
5162             }
5163             if (Display.isOnState(state)) {
5164                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
5165                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
5166                         + Integer.toHexString(mHistoryCur.states));
5167                 mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
5168                 if (mScreenBrightnessBin >= 0) {
5169                     mScreenBrightnessTimer[mScreenBrightnessBin]
5170                             .startRunningLocked(elapsedRealtimeMs);
5171                 }
5172                 updateHistory = true;
5173             } else if (Display.isOnState(oldState)) {
5174                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
5175                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
5176                         + Integer.toHexString(mHistoryCur.states));
5177                 mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5178                 if (mScreenBrightnessBin >= 0) {
5179                     mScreenBrightnessTimer[mScreenBrightnessBin]
5180                             .stopRunningLocked(elapsedRealtimeMs);
5181                 }
5182                 updateHistory = true;
5183             }
5184             if (updateHistory) {
5185                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
5186                         + Display.stateToString(state));
5187                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5188             }
5189 
5190             // Per screen state Cpu stats needed. Prepare to schedule an external sync.
5191             externalUpdateFlag |= ExternalStatsSync.UPDATE_CPU;
5192             shouldScheduleSync = true;
5193 
5194             if (Display.isOnState(state)) {
5195                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
5196                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
5197                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
5198                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
5199                         elapsedRealtimeMs, uptimeMs);
5200             } else if (Display.isOnState(oldState)) {
5201                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
5202                         elapsedRealtimeMs, uptimeMs);
5203                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
5204                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
5205             }
5206             // Update discharge amounts.
5207             if (mOnBatteryInternal) {
5208                 updateDischargeScreenLevelsLocked(oldState, state);
5209             }
5210         }
5211 
5212         // Changing display states might have changed the screen used to determine the overall
5213         // brightness.
5214         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
5215 
5216         if (shouldScheduleSync) {
5217             final int numDisplays = mPerDisplayBatteryStats.length;
5218             final int[] displayStates = new int[numDisplays];
5219             for (int i = 0; i < numDisplays; i++) {
5220                 displayStates[i] = mPerDisplayBatteryStats[i].screenState;
5221             }
5222             mExternalSync.scheduleSyncDueToScreenStateChange(externalUpdateFlag,
5223                     batteryRunning, batteryScreenOffRunning, state, displayStates);
5224         }
5225     }
5226 
5227     @UnsupportedAppUsage
noteScreenBrightnessLocked(int brightness)5228     public void noteScreenBrightnessLocked(int brightness) {
5229         noteScreenBrightnessLocked(0, brightness);
5230     }
5231 
5232     /**
5233      * Note screen brightness change for a display.
5234      */
noteScreenBrightnessLocked(int display, int brightness)5235     public void noteScreenBrightnessLocked(int display, int brightness) {
5236         noteScreenBrightnessLocked(display, brightness, mClocks.elapsedRealtime(),
5237                 mClocks.uptimeMillis());
5238     }
5239 
5240 
5241     /**
5242      * Note screen brightness change for a display.
5243      */
noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs, long uptimeMs)5244     public void noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs,
5245             long uptimeMs) {
5246         // Bin the brightness.
5247         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
5248         if (bin < 0) bin = 0;
5249         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
5250 
5251         final int overallBin;
5252 
5253         final int numDisplays = mPerDisplayBatteryStats.length;
5254         if (display < 0 || display >= numDisplays) {
5255             Slog.wtf(TAG, "Unexpected note screen brightness for display " + display + " (only "
5256                     + mPerDisplayBatteryStats.length + " displays exist...)");
5257             return;
5258         }
5259 
5260         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5261         final int oldBin = displayStats.screenBrightnessBin;
5262         if (oldBin == bin) {
5263             // Nothing changed
5264             overallBin = mScreenBrightnessBin;
5265         } else {
5266             displayStats.screenBrightnessBin = bin;
5267             if (displayStats.screenState == Display.STATE_ON) {
5268                 if (oldBin >= 0) {
5269                     displayStats.screenBrightnessTimers[oldBin].stopRunningLocked(
5270                             elapsedRealtimeMs);
5271                 }
5272                 displayStats.screenBrightnessTimers[bin].startRunningLocked(
5273                         elapsedRealtimeMs);
5274             }
5275             overallBin = evaluateOverallScreenBrightnessBinLocked();
5276         }
5277 
5278         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
5279     }
5280 
evaluateOverallScreenBrightnessBinLocked()5281     private int evaluateOverallScreenBrightnessBinLocked() {
5282         int overallBin = -1;
5283         final int numDisplays = getDisplayCount();
5284         for (int display = 0; display < numDisplays; display++) {
5285             final int displayBrightnessBin;
5286             if (mPerDisplayBatteryStats[display].screenState == Display.STATE_ON) {
5287                 displayBrightnessBin = mPerDisplayBatteryStats[display].screenBrightnessBin;
5288             } else {
5289                 displayBrightnessBin = -1;
5290             }
5291             if (displayBrightnessBin > overallBin) {
5292                 overallBin = displayBrightnessBin;
5293             }
5294         }
5295         return overallBin;
5296     }
5297 
maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs, long uptimeMs)5298     private void maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs,
5299             long uptimeMs) {
5300         if (mScreenBrightnessBin != overallBin) {
5301             if (overallBin >= 0) {
5302                 mHistoryCur.states = (mHistoryCur.states & ~HistoryItem.STATE_BRIGHTNESS_MASK)
5303                         | (overallBin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
5304                 if (DEBUG_HISTORY) {
5305                     Slog.v(TAG, "Screen brightness " + overallBin + " to: "
5306                             + Integer.toHexString(mHistoryCur.states));
5307                 }
5308                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5309             }
5310             if (mScreenState == Display.STATE_ON) {
5311                 if (mScreenBrightnessBin >= 0) {
5312                     mScreenBrightnessTimer[mScreenBrightnessBin]
5313                             .stopRunningLocked(elapsedRealtimeMs);
5314                 }
5315                 if (overallBin >= 0) {
5316                     mScreenBrightnessTimer[overallBin]
5317                             .startRunningLocked(elapsedRealtimeMs);
5318                 }
5319             }
5320             mScreenBrightnessBin = overallBin;
5321         }
5322     }
5323 
5324     @UnsupportedAppUsage
noteUserActivityLocked(int uid, int event)5325     public void noteUserActivityLocked(int uid, int event) {
5326         noteUserActivityLocked(uid, event, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5327     }
5328 
noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs)5329     public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) {
5330         if (mOnBatteryInternal) {
5331             uid = mapUid(uid);
5332             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event);
5333         }
5334     }
5335 
noteWakeUpLocked(String reason, int reasonUid)5336     public void noteWakeUpLocked(String reason, int reasonUid) {
5337         noteWakeUpLocked(reason, reasonUid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5338     }
5339 
noteWakeUpLocked(String reason, int reasonUid, long elapsedRealtimeMs, long uptimeMs)5340     public void noteWakeUpLocked(String reason, int reasonUid,
5341             long elapsedRealtimeMs, long uptimeMs) {
5342         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP,
5343                 reason, reasonUid);
5344     }
5345 
noteInteractiveLocked(boolean interactive)5346     public void noteInteractiveLocked(boolean interactive) {
5347         noteInteractiveLocked(interactive, mClocks.elapsedRealtime());
5348     }
5349 
noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs)5350     public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) {
5351         if (mInteractive != interactive) {
5352             mInteractive = interactive;
5353             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
5354             if (interactive) {
5355                 mInteractiveTimer.startRunningLocked(elapsedRealtimeMs);
5356             } else {
5357                 mInteractiveTimer.stopRunningLocked(elapsedRealtimeMs);
5358             }
5359         }
5360     }
5361 
noteConnectivityChangedLocked(int type, String extra)5362     public void noteConnectivityChangedLocked(int type, String extra) {
5363         noteConnectivityChangedLocked(type, extra,
5364                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5365     }
5366 
noteConnectivityChangedLocked(int type, String extra, long elapsedRealtimeMs, long uptimeMs)5367     public void noteConnectivityChangedLocked(int type, String extra,
5368             long elapsedRealtimeMs, long uptimeMs) {
5369         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
5370                 extra, type);
5371         mNumConnectivityChange++;
5372     }
5373 
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5374     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
5375             final long uptimeMillis, int uid) {
5376         uid = mapUid(uid);
5377         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5378                 uid);
5379         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
5380     }
5381 
5382     /**
5383      * Updates the radio power state and returns true if an external stats collection should occur.
5384      */
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)5385     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
5386         return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
5387                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5388     }
5389 
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)5390     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid,
5391             long elapsedRealtimeMs, long uptimeMs) {
5392         if (mMobileRadioPowerState != powerState) {
5393             long realElapsedRealtimeMs;
5394             final boolean active =
5395                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5396                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5397             if (active) {
5398                 if (uid > 0) {
5399                     noteMobileRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
5400                 }
5401 
5402                 mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
5403                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
5404             } else {
5405                 realElapsedRealtimeMs = timestampNs / (1000*1000);
5406                 long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
5407                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
5408                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
5409                             + " is before start time " + lastUpdateTimeMs);
5410                     realElapsedRealtimeMs = elapsedRealtimeMs;
5411                 } else if (realElapsedRealtimeMs < elapsedRealtimeMs) {
5412                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
5413                             - realElapsedRealtimeMs);
5414                 }
5415                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
5416             }
5417             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
5418                     + Integer.toHexString(mHistoryCur.states));
5419             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5420             mMobileRadioPowerState = powerState;
5421             if (active) {
5422                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs);
5423                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs);
5424             } else {
5425                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
5426                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
5427                 // Tell the caller to collect radio network/power stats.
5428                 return true;
5429             }
5430         }
5431         return false;
5432     }
5433 
notePowerSaveModeLocked(boolean enabled)5434     public void notePowerSaveModeLocked(boolean enabled) {
5435         notePowerSaveModeLocked(enabled, mClocks.elapsedRealtime(), mClocks.uptimeMillis(), false);
5436     }
5437 
5438     /**
5439      * Handles power save mode state changes.
5440      */
notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs, boolean forceLog)5441     public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs,
5442             boolean forceLog) {
5443         if (mPowerSaveModeEnabled != enabled) {
5444             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
5445             mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
5446             mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
5447             mPowerSaveModeEnabled = enabled;
5448             if (enabled) {
5449                 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
5450                 if (DEBUG_HISTORY) {
5451                     Slog.v(TAG, "Power save mode enabled to: "
5452                             + Integer.toHexString(mHistoryCur.states2));
5453                 }
5454                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
5455             } else {
5456                 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
5457                 if (DEBUG_HISTORY) {
5458                     Slog.v(TAG, "Power save mode disabled to: "
5459                             + Integer.toHexString(mHistoryCur.states2));
5460                 }
5461                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
5462             }
5463             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5464             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
5465                     enabled
5466                             ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
5467                             : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
5468         } else if (forceLog) {
5469             // Log an initial value for BATTERY_SAVER_MODE_STATE_CHANGED in order to
5470             // allow the atom to read all future state changes.
5471             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
5472                     enabled
5473                             ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
5474                             : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
5475         }
5476     }
5477 
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid)5478     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
5479         noteDeviceIdleModeLocked(mode, activeReason, activeUid,
5480                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5481     }
5482 
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid, long elapsedRealtimeMs, long uptimeMs)5483     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid,
5484             long elapsedRealtimeMs, long uptimeMs) {
5485         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
5486         if (mDeviceIdling && !nowIdling && activeReason == null) {
5487             // We don't go out of general idling mode until explicitly taken out of
5488             // device idle through going active or significant motion.
5489             nowIdling = true;
5490         }
5491         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
5492         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
5493             // We don't go out of general light idling mode until explicitly taken out of
5494             // device idle through going active or significant motion.
5495             nowLightIdling = true;
5496         }
5497         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
5498             addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
5499                     activeReason, activeUid);
5500         }
5501         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
5502             int statsmode;
5503             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
5504             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
5505             else                     statsmode = DEVICE_IDLE_MODE_OFF;
5506             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
5507         }
5508         if (mDeviceIdling != nowIdling) {
5509             mDeviceIdling = nowIdling;
5510             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
5511             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
5512             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
5513             if (nowIdling) {
5514                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtimeMs);
5515             } else {
5516                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
5517             }
5518         }
5519         if (mDeviceLightIdling != nowLightIdling) {
5520             mDeviceLightIdling = nowLightIdling;
5521             if (nowLightIdling) {
5522                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtimeMs);
5523             } else {
5524                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
5525             }
5526         }
5527         if (mDeviceIdleMode != mode) {
5528             mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
5529                     | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
5530             if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
5531                     + Integer.toHexString(mHistoryCur.states2));
5532             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5533             long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
5534             mLastIdleTimeStartMs = elapsedRealtimeMs;
5535             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
5536                 if (lastDuration > mLongestLightIdleTimeMs) {
5537                     mLongestLightIdleTimeMs = lastDuration;
5538                 }
5539                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtimeMs);
5540             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
5541                 if (lastDuration > mLongestFullIdleTimeMs) {
5542                     mLongestFullIdleTimeMs = lastDuration;
5543                 }
5544                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtimeMs);
5545             }
5546             if (mode == DEVICE_IDLE_MODE_LIGHT) {
5547                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtimeMs);
5548             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
5549                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtimeMs);
5550             }
5551             mDeviceIdleMode = mode;
5552             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
5553         }
5554     }
5555 
notePackageInstalledLocked(String pkgName, long versionCode)5556     public void notePackageInstalledLocked(String pkgName, long versionCode) {
5557         notePackageInstalledLocked(pkgName, versionCode,
5558                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5559     }
5560 
notePackageInstalledLocked(String pkgName, long versionCode, long elapsedRealtimeMs, long uptimeMs)5561     public void notePackageInstalledLocked(String pkgName, long versionCode,
5562             long elapsedRealtimeMs, long uptimeMs) {
5563         // XXX need to figure out what to do with long version codes.
5564         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
5565                 pkgName, (int)versionCode);
5566         PackageChange pc = new PackageChange();
5567         pc.mPackageName = pkgName;
5568         pc.mUpdate = true;
5569         pc.mVersionCode = versionCode;
5570         addPackageChange(pc);
5571     }
5572 
notePackageUninstalledLocked(String pkgName)5573     public void notePackageUninstalledLocked(String pkgName) {
5574         notePackageUninstalledLocked(pkgName, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5575     }
5576 
notePackageUninstalledLocked(String pkgName, long elapsedRealtimeMs, long uptimeMs)5577     public void notePackageUninstalledLocked(String pkgName,
5578             long elapsedRealtimeMs, long uptimeMs) {
5579         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
5580                 HistoryItem.EVENT_PACKAGE_UNINSTALLED, pkgName, 0);
5581         PackageChange pc = new PackageChange();
5582         pc.mPackageName = pkgName;
5583         pc.mUpdate = true;
5584         addPackageChange(pc);
5585     }
5586 
addPackageChange(PackageChange pc)5587     private void addPackageChange(PackageChange pc) {
5588         if (mDailyPackageChanges == null) {
5589             mDailyPackageChanges = new ArrayList<>();
5590         }
5591         mDailyPackageChanges.add(pc);
5592     }
5593 
stopAllGpsSignalQualityTimersLocked(int except)5594     void stopAllGpsSignalQualityTimersLocked(int except) {
5595         stopAllGpsSignalQualityTimersLocked(except, mClocks.elapsedRealtime());
5596     }
5597 
stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs)5598     void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
5599         for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
5600             if (i == except) {
5601                 continue;
5602             }
5603             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
5604                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtimeMs);
5605             }
5606         }
5607     }
5608 
5609     @UnsupportedAppUsage
notePhoneOnLocked()5610     public void notePhoneOnLocked() {
5611         notePhoneOnLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5612     }
5613 
notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs)5614     public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
5615         if (!mPhoneOn) {
5616             mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5617             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
5618                     + Integer.toHexString(mHistoryCur.states));
5619             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5620             mPhoneOn = true;
5621             mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
5622         }
5623     }
5624 
5625     @UnsupportedAppUsage
notePhoneOffLocked()5626     public void notePhoneOffLocked() {
5627         notePhoneOffLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5628     }
5629 
notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs)5630     public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
5631         if (mPhoneOn) {
5632             mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5633             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
5634                     + Integer.toHexString(mHistoryCur.states));
5635             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5636             mPhoneOn = false;
5637             mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
5638         }
5639     }
5640 
registerUsbStateReceiver(Context context)5641     private void registerUsbStateReceiver(Context context) {
5642         final IntentFilter usbStateFilter = new IntentFilter();
5643         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
5644         context.registerReceiver(new BroadcastReceiver() {
5645             @Override
5646             public void onReceive(Context context, Intent intent) {
5647                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
5648                 synchronized (BatteryStatsImpl.this) {
5649                     noteUsbConnectionStateLocked(state, mClocks.elapsedRealtime(),
5650                             mClocks.uptimeMillis());
5651                 }
5652             }
5653         }, usbStateFilter);
5654         synchronized (this) {
5655             if (mUsbDataState == USB_DATA_UNKNOWN) {
5656                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
5657                 final boolean initState = usbState != null && usbState.getBooleanExtra(
5658                         UsbManager.USB_CONNECTED, false);
5659                 noteUsbConnectionStateLocked(initState, mClocks.elapsedRealtime(),
5660                         mClocks.uptimeMillis());
5661             }
5662         }
5663     }
5664 
noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs, long uptimeMs)5665     private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs,
5666             long uptimeMs) {
5667         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
5668         if (mUsbDataState != newState) {
5669             mUsbDataState = newState;
5670             if (connected) {
5671                 mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5672             } else {
5673                 mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5674             }
5675             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5676         }
5677     }
5678 
stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)5679     void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
5680         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
5681             if (i == except) {
5682                 continue;
5683             }
5684             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
5685                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
5686             }
5687         }
5688     }
5689 
fixPhoneServiceState(int state, int signalBin)5690     private int fixPhoneServiceState(int state, int signalBin) {
5691         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
5692             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5693             // to infer that we are scanning from other data.
5694             if (state == ServiceState.STATE_OUT_OF_SERVICE
5695                     && signalBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5696                 state = ServiceState.STATE_IN_SERVICE;
5697             }
5698         }
5699 
5700         return state;
5701     }
5702 
updateAllPhoneStateLocked(int state, int simState, int strengthBin, long elapsedRealtimeMs, long uptimeMs)5703     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin,
5704             long elapsedRealtimeMs, long uptimeMs) {
5705         boolean scanning = false;
5706         boolean newHistory = false;
5707 
5708         mPhoneServiceStateRaw = state;
5709         mPhoneSimStateRaw = simState;
5710         mPhoneSignalStrengthBinRaw = strengthBin;
5711 
5712         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
5713             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5714             // to infer that we are scanning from other data.
5715             if (state == ServiceState.STATE_OUT_OF_SERVICE
5716                     && strengthBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5717                 state = ServiceState.STATE_IN_SERVICE;
5718             }
5719         }
5720 
5721         // If the phone is powered off, stop all timers.
5722         if (state == ServiceState.STATE_POWER_OFF) {
5723             strengthBin = -1;
5724 
5725         // If we are in service, make sure the correct signal string timer is running.
5726         } else if (state == ServiceState.STATE_IN_SERVICE) {
5727             // Bin will be changed below.
5728 
5729         // If we're out of service, we are in the lowest signal strength
5730         // bin and have the scanning bit set.
5731         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
5732             scanning = true;
5733             strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
5734             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
5735                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
5736                 newHistory = true;
5737                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
5738                         + Integer.toHexString(mHistoryCur.states));
5739                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs);
5740                 FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
5741                         simState, strengthBin);
5742             }
5743         }
5744 
5745         if (!scanning) {
5746             // If we are no longer scanning, then stop the scanning timer.
5747             if (mPhoneSignalScanningTimer.isRunningLocked()) {
5748                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
5749                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
5750                         + Integer.toHexString(mHistoryCur.states));
5751                 newHistory = true;
5752                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
5753                 FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
5754                         simState, strengthBin);
5755             }
5756         }
5757 
5758         if (mPhoneServiceState != state) {
5759             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
5760                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
5761             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
5762                     + Integer.toHexString(mHistoryCur.states));
5763             newHistory = true;
5764             mPhoneServiceState = state;
5765         }
5766 
5767         if (mPhoneSignalStrengthBin != strengthBin) {
5768             if (mPhoneSignalStrengthBin >= 0) {
5769                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
5770                         elapsedRealtimeMs);
5771             }
5772             if (strengthBin >= 0) {
5773                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5774                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
5775                 }
5776                 mHistoryCur.states =
5777                         (mHistoryCur.states & ~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
5778                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
5779                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
5780                         + Integer.toHexString(mHistoryCur.states));
5781                 newHistory = true;
5782                 FrameworkStatsLog.write(
5783                         FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
5784             } else {
5785                 stopAllPhoneSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
5786             }
5787             mPhoneSignalStrengthBin = strengthBin;
5788         }
5789 
5790         if (newHistory) {
5791             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5792         }
5793     }
5794 
5795     /**
5796      * Telephony stack updates the phone state.
5797      * @param state phone state from ServiceState.getState()
5798      */
notePhoneStateLocked(int state, int simState)5799     public void notePhoneStateLocked(int state, int simState) {
5800         notePhoneStateLocked(state, simState, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5801     }
5802 
notePhoneStateLocked(int state, int simState, long elapsedRealtimeMs, long uptimeMs)5803     public void notePhoneStateLocked(int state, int simState,
5804             long elapsedRealtimeMs, long uptimeMs) {
5805         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw,
5806                 elapsedRealtimeMs, uptimeMs);
5807     }
5808 
5809     @UnsupportedAppUsage
notePhoneSignalStrengthLocked(SignalStrength signalStrength)5810     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
5811         notePhoneSignalStrengthLocked(signalStrength,
5812                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5813     }
5814 
notePhoneSignalStrengthLocked(SignalStrength signalStrength, long elapsedRealtimeMs, long uptimeMs)5815     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
5816             long elapsedRealtimeMs, long uptimeMs) {
5817         // Bin the strength.
5818         int bin = signalStrength.getLevel();
5819         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin,
5820                 elapsedRealtimeMs, uptimeMs);
5821     }
5822 
5823     @UnsupportedAppUsage
notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType)5824     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) {
5825         notePhoneDataConnectionStateLocked(dataType, hasData, serviceType,
5826                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5827     }
5828 
notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType, long elapsedRealtimeMs, long uptimeMs)5829     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType,
5830             long elapsedRealtimeMs, long uptimeMs) {
5831         // BatteryStats uses 0 to represent no network type.
5832         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
5833         // Unknown is included in DATA_CONNECTION_OTHER.
5834         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
5835         if (hasData) {
5836             if (dataType > 0 && dataType <= TelephonyManager.getAllNetworkTypes().length) {
5837                 bin = dataType;
5838             } else {
5839                 switch (serviceType) {
5840                     case ServiceState.STATE_OUT_OF_SERVICE:
5841                         bin = DATA_CONNECTION_OUT_OF_SERVICE;
5842                         break;
5843                     case ServiceState.STATE_EMERGENCY_ONLY:
5844                         bin = DATA_CONNECTION_EMERGENCY_SERVICE;
5845                         break;
5846                     default:
5847                         bin = DATA_CONNECTION_OTHER;
5848                         break;
5849                 }
5850             }
5851         }
5852         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
5853         if (mPhoneDataConnectionType != bin) {
5854             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
5855                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
5856             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
5857                     + Integer.toHexString(mHistoryCur.states));
5858             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5859             if (mPhoneDataConnectionType >= 0) {
5860                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
5861                         elapsedRealtimeMs);
5862             }
5863             mPhoneDataConnectionType = bin;
5864             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs);
5865         }
5866     }
5867 
noteWifiOnLocked()5868     public void noteWifiOnLocked() {
5869         noteWifiOnLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5870     }
5871 
noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs)5872     public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
5873         if (!mWifiOn) {
5874             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
5875             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
5876                     + Integer.toHexString(mHistoryCur.states));
5877             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5878             mWifiOn = true;
5879             mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
5880             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
5881         }
5882     }
5883 
noteWifiOffLocked()5884     public void noteWifiOffLocked() {
5885         noteWifiOffLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5886     }
5887 
noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs)5888     public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
5889         if (mWifiOn) {
5890             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
5891             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
5892                     + Integer.toHexString(mHistoryCur.states));
5893             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5894             mWifiOn = false;
5895             mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
5896             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
5897         }
5898     }
5899 
5900     @UnsupportedAppUsage
noteAudioOnLocked(int uid)5901     public void noteAudioOnLocked(int uid) {
5902         noteAudioOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5903     }
5904 
noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5905     public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5906         uid = mapUid(uid);
5907         if (mAudioOnNesting == 0) {
5908             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
5909             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
5910                     + Integer.toHexString(mHistoryCur.states));
5911             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5912             mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
5913         }
5914         mAudioOnNesting++;
5915         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5916                 .noteAudioTurnedOnLocked(elapsedRealtimeMs);
5917     }
5918 
5919     @UnsupportedAppUsage
noteAudioOffLocked(int uid)5920     public void noteAudioOffLocked(int uid) {
5921         noteAudioOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5922     }
5923 
noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5924     public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5925         if (mAudioOnNesting == 0) {
5926             return;
5927         }
5928         uid = mapUid(uid);
5929         if (--mAudioOnNesting == 0) {
5930             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5931             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5932                     + Integer.toHexString(mHistoryCur.states));
5933             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5934             mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
5935         }
5936         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5937                 .noteAudioTurnedOffLocked(elapsedRealtimeMs);
5938     }
5939 
5940     @UnsupportedAppUsage
noteVideoOnLocked(int uid)5941     public void noteVideoOnLocked(int uid) {
5942         noteVideoOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5943     }
5944 
noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5945     public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5946         uid = mapUid(uid);
5947         if (mVideoOnNesting == 0) {
5948             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
5949             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
5950                     + Integer.toHexString(mHistoryCur.states));
5951             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5952             mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
5953         }
5954         mVideoOnNesting++;
5955         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5956                 .noteVideoTurnedOnLocked(elapsedRealtimeMs);
5957     }
5958 
5959     @UnsupportedAppUsage
noteVideoOffLocked(int uid)5960     public void noteVideoOffLocked(int uid) {
5961         noteVideoOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5962     }
5963 
noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5964     public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5965         if (mVideoOnNesting == 0) {
5966             return;
5967         }
5968         uid = mapUid(uid);
5969         if (--mVideoOnNesting == 0) {
5970             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5971             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5972                     + Integer.toHexString(mHistoryCur.states));
5973             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5974             mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
5975         }
5976         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5977                 .noteVideoTurnedOffLocked(elapsedRealtimeMs);
5978     }
5979 
noteResetAudioLocked()5980     public void noteResetAudioLocked() {
5981         noteResetAudioLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5982     }
5983 
noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs)5984     public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
5985         if (mAudioOnNesting > 0) {
5986             mAudioOnNesting = 0;
5987             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5988             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5989                     + Integer.toHexString(mHistoryCur.states));
5990             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5991             mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5992             for (int i=0; i<mUidStats.size(); i++) {
5993                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5994                 uid.noteResetAudioLocked(elapsedRealtimeMs);
5995             }
5996         }
5997     }
5998 
noteResetVideoLocked()5999     public void noteResetVideoLocked() {
6000         noteResetVideoLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6001     }
6002 
noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs)6003     public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
6004         if (mVideoOnNesting > 0) {
6005             mVideoOnNesting = 0;
6006             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
6007             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
6008                     + Integer.toHexString(mHistoryCur.states));
6009             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6010             mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6011             for (int i=0; i<mUidStats.size(); i++) {
6012                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6013                 uid.noteResetVideoLocked(elapsedRealtimeMs);
6014             }
6015         }
6016     }
6017 
noteActivityResumedLocked(int uid)6018     public void noteActivityResumedLocked(int uid) {
6019         noteActivityResumedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6020     }
6021 
noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6022     public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6023         uid = mapUid(uid);
6024         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6025                 .noteActivityResumedLocked(elapsedRealtimeMs);
6026     }
6027 
noteActivityPausedLocked(int uid)6028     public void noteActivityPausedLocked(int uid) {
6029         noteActivityPausedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6030     }
6031 
noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6032     public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6033         uid = mapUid(uid);
6034         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6035                 .noteActivityPausedLocked(elapsedRealtimeMs);
6036     }
6037 
noteVibratorOnLocked(int uid, long durationMillis)6038     public void noteVibratorOnLocked(int uid, long durationMillis) {
6039         noteVibratorOnLocked(uid, durationMillis,
6040                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6041     }
6042 
noteVibratorOnLocked(int uid, long durationMillis, long elapsedRealtimeMs, long uptimeMs)6043     public void noteVibratorOnLocked(int uid, long durationMillis,
6044             long elapsedRealtimeMs, long uptimeMs) {
6045         uid = mapUid(uid);
6046         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6047                 .noteVibratorOnLocked(durationMillis, elapsedRealtimeMs);
6048     }
6049 
noteVibratorOffLocked(int uid)6050     public void noteVibratorOffLocked(int uid) {
6051         noteVibratorOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6052     }
6053 
noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6054     public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6055         uid = mapUid(uid);
6056         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6057                 .noteVibratorOffLocked(elapsedRealtimeMs);
6058     }
6059 
noteFlashlightOnLocked(int uid)6060     public void noteFlashlightOnLocked(int uid) {
6061         noteFlashlightOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6062     }
6063 
noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6064     public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6065         uid = mapUid(uid);
6066         if (mFlashlightOnNesting++ == 0) {
6067             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
6068             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
6069                     + Integer.toHexString(mHistoryCur.states2));
6070             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6071             mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
6072         }
6073         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6074                 .noteFlashlightTurnedOnLocked(elapsedRealtimeMs);
6075     }
6076 
noteFlashlightOffLocked(int uid)6077     public void noteFlashlightOffLocked(int uid) {
6078         noteFlashlightOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6079     }
6080 
noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6081     public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6082         if (mFlashlightOnNesting == 0) {
6083             return;
6084         }
6085         uid = mapUid(uid);
6086         if (--mFlashlightOnNesting == 0) {
6087             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
6088             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
6089                     + Integer.toHexString(mHistoryCur.states2));
6090             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6091             mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
6092         }
6093         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6094                 .noteFlashlightTurnedOffLocked(elapsedRealtimeMs);
6095     }
6096 
noteCameraOnLocked(int uid)6097     public void noteCameraOnLocked(int uid) {
6098         noteCameraOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6099     }
6100 
noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6101     public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6102         uid = mapUid(uid);
6103         if (mCameraOnNesting++ == 0) {
6104             mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
6105             if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
6106                     + Integer.toHexString(mHistoryCur.states2));
6107             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6108             mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
6109         }
6110         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6111                 .noteCameraTurnedOnLocked(elapsedRealtimeMs);
6112     }
6113 
noteCameraOffLocked(int uid)6114     public void noteCameraOffLocked(int uid) {
6115         noteCameraOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6116     }
6117 
noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6118     public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6119         if (mCameraOnNesting == 0) {
6120             return;
6121         }
6122         uid = mapUid(uid);
6123         if (--mCameraOnNesting == 0) {
6124             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
6125             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
6126                     + Integer.toHexString(mHistoryCur.states2));
6127             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6128             mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
6129         }
6130         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6131                 .noteCameraTurnedOffLocked(elapsedRealtimeMs);
6132     }
6133 
noteResetCameraLocked()6134     public void noteResetCameraLocked() {
6135         noteResetCameraLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6136     }
6137 
noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs)6138     public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
6139         if (mCameraOnNesting > 0) {
6140             mCameraOnNesting = 0;
6141             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
6142             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
6143                     + Integer.toHexString(mHistoryCur.states2));
6144             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6145             mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6146             for (int i=0; i<mUidStats.size(); i++) {
6147                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6148                 uid.noteResetCameraLocked(elapsedRealtimeMs);
6149             }
6150         }
6151     }
6152 
noteResetFlashlightLocked()6153     public void noteResetFlashlightLocked() {
6154         noteResetFlashlightLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6155     }
6156 
noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs)6157     public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
6158         if (mFlashlightOnNesting > 0) {
6159             mFlashlightOnNesting = 0;
6160             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
6161             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
6162                     + Integer.toHexString(mHistoryCur.states2));
6163             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6164             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6165             for (int i=0; i<mUidStats.size(); i++) {
6166                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6167                 uid.noteResetFlashlightLocked(elapsedRealtimeMs);
6168             }
6169         }
6170     }
6171 
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6172     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
6173             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
6174         uid = getAttributionUid(uid, workChain);
6175         if (mBluetoothScanNesting == 0) {
6176             mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
6177             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
6178                     + Integer.toHexString(mHistoryCur.states2));
6179             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6180             mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
6181         }
6182         mBluetoothScanNesting++;
6183         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6184                 .noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized);
6185     }
6186 
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)6187     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
6188         noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
6189                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6190     }
6191 
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6192     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
6193             long elapsedRealtimeMs, long uptimeMs) {
6194         final int N = ws.size();
6195         for (int i = 0; i < N; i++) {
6196             noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized,
6197                     elapsedRealtimeMs, uptimeMs);
6198         }
6199 
6200         final List<WorkChain> workChains = ws.getWorkChains();
6201         if (workChains != null) {
6202             for (int i = 0; i < workChains.size(); ++i) {
6203                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized,
6204                         elapsedRealtimeMs, uptimeMs);
6205             }
6206         }
6207     }
6208 
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6209     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
6210             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
6211         uid = getAttributionUid(uid, workChain);
6212         mBluetoothScanNesting--;
6213         if (mBluetoothScanNesting == 0) {
6214             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
6215             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
6216                     + Integer.toHexString(mHistoryCur.states2));
6217             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6218             mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
6219         }
6220         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6221                 .noteBluetoothScanStoppedLocked(elapsedRealtimeMs, isUnoptimized);
6222     }
6223 
getAttributionUid(int uid, WorkChain workChain)6224     private int getAttributionUid(int uid, WorkChain workChain) {
6225         if (workChain != null) {
6226             return mapUid(workChain.getAttributionUid());
6227         }
6228 
6229         return mapUid(uid);
6230     }
6231 
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)6232     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
6233         noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
6234                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6235     }
6236 
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6237     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
6238             long elapsedRealtimeMs, long uptimeMs) {
6239         final int N = ws.size();
6240         for (int i = 0; i < N; i++) {
6241             noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized,
6242                     elapsedRealtimeMs, uptimeMs);
6243         }
6244 
6245         final List<WorkChain> workChains = ws.getWorkChains();
6246         if (workChains != null) {
6247             for (int i = 0; i < workChains.size(); ++i) {
6248                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized,
6249                         elapsedRealtimeMs, uptimeMs);
6250             }
6251         }
6252     }
6253 
noteResetBluetoothScanLocked()6254     public void noteResetBluetoothScanLocked() {
6255         noteResetBluetoothScanLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6256     }
6257 
noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs)6258     public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
6259         if (mBluetoothScanNesting > 0) {
6260             mBluetoothScanNesting = 0;
6261             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
6262             if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
6263                     + Integer.toHexString(mHistoryCur.states2));
6264             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6265             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
6266             for (int i=0; i<mUidStats.size(); i++) {
6267                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6268                 uid.noteResetBluetoothScanLocked(elapsedRealtimeMs);
6269             }
6270         }
6271     }
6272 
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)6273     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
6274         noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
6275                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6276     }
6277 
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults, long elapsedRealtimeMs, long uptimeMs)6278     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults,
6279             long elapsedRealtimeMs, long uptimeMs) {
6280         final int N = ws.size();
6281         for (int i = 0; i < N; i++) {
6282             int uid = mapUid(ws.getUid(i));
6283             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6284                     .noteBluetoothScanResultsLocked(numNewResults);
6285         }
6286 
6287         final List<WorkChain> workChains = ws.getWorkChains();
6288         if (workChains != null) {
6289             for (int i = 0; i < workChains.size(); ++i) {
6290                 final WorkChain wc = workChains.get(i);
6291                 int uid = mapUid(wc.getAttributionUid());
6292                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6293                         .noteBluetoothScanResultsLocked(numNewResults);
6294             }
6295         }
6296     }
6297 
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)6298     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
6299             final long uptimeMillis, int uid) {
6300         uid = mapUid(uid);
6301         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
6302                 uid);
6303         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
6304     }
6305 
noteWifiRadioPowerState(int powerState, long timestampNs, int uid)6306     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
6307         noteWifiRadioPowerState(powerState, timestampNs, uid,
6308                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6309     }
6310 
noteWifiRadioPowerState(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)6311     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid,
6312             long elapsedRealtimeMs, long uptimeMs) {
6313         if (mWifiRadioPowerState != powerState) {
6314             final boolean active =
6315                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
6316                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
6317             if (active) {
6318                 if (uid > 0) {
6319                     noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
6320                 }
6321                 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
6322                 mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
6323             } else {
6324                 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
6325                 mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000));
6326             }
6327             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
6328                     + Integer.toHexString(mHistoryCur.states));
6329             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6330             mWifiRadioPowerState = powerState;
6331         }
6332     }
6333 
noteWifiRunningLocked(WorkSource ws)6334     public void noteWifiRunningLocked(WorkSource ws) {
6335         noteWifiRunningLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6336     }
6337 
noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6338     public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6339         if (!mGlobalWifiRunning) {
6340             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
6341             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
6342                     + Integer.toHexString(mHistoryCur.states));
6343             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6344             mGlobalWifiRunning = true;
6345             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
6346             int N = ws.size();
6347             for (int i=0; i<N; i++) {
6348                 int uid = mapUid(ws.getUid(i));
6349                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6350                         .noteWifiRunningLocked(elapsedRealtimeMs);
6351             }
6352 
6353             List<WorkChain> workChains = ws.getWorkChains();
6354             if (workChains != null) {
6355                 for (int i = 0; i < workChains.size(); ++i) {
6356                     int uid = mapUid(workChains.get(i).getAttributionUid());
6357                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6358                             .noteWifiRunningLocked(elapsedRealtimeMs);
6359                 }
6360             }
6361 
6362             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
6363         } else {
6364             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
6365         }
6366     }
6367 
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs)6368     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
6369         noteWifiRunningChangedLocked(oldWs, newWs,
6370                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6371     }
6372 
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)6373     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs,
6374             long elapsedRealtimeMs, long uptimeMs) {
6375         if (mGlobalWifiRunning) {
6376             int N = oldWs.size();
6377             for (int i=0; i<N; i++) {
6378                 int uid = mapUid(oldWs.getUid(i));
6379                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6380                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6381             }
6382 
6383             List<WorkChain> workChains = oldWs.getWorkChains();
6384             if (workChains != null) {
6385                 for (int i = 0; i < workChains.size(); ++i) {
6386                     int uid = mapUid(workChains.get(i).getAttributionUid());
6387                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6388                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6389                 }
6390             }
6391 
6392             N = newWs.size();
6393             for (int i=0; i<N; i++) {
6394                 int uid = mapUid(newWs.getUid(i));
6395                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6396                         .noteWifiRunningLocked(elapsedRealtimeMs);
6397             }
6398 
6399             workChains = newWs.getWorkChains();
6400             if (workChains != null) {
6401                 for (int i = 0; i < workChains.size(); ++i) {
6402                     int uid = mapUid(workChains.get(i).getAttributionUid());
6403                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6404                             .noteWifiRunningLocked(elapsedRealtimeMs);
6405                 }
6406             }
6407         } else {
6408             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
6409         }
6410     }
6411 
noteWifiStoppedLocked(WorkSource ws)6412     public void noteWifiStoppedLocked(WorkSource ws) {
6413         noteWifiStoppedLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6414     }
6415 
noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6416     public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6417         if (mGlobalWifiRunning) {
6418             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
6419             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
6420                     + Integer.toHexString(mHistoryCur.states));
6421             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6422             mGlobalWifiRunning = false;
6423             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
6424             int N = ws.size();
6425             for (int i=0; i<N; i++) {
6426                 int uid = mapUid(ws.getUid(i));
6427                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6428                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6429             }
6430 
6431             List<WorkChain> workChains = ws.getWorkChains();
6432             if (workChains != null) {
6433                 for (int i = 0; i < workChains.size(); ++i) {
6434                     int uid = mapUid(workChains.get(i).getAttributionUid());
6435                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6436                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6437                 }
6438             }
6439 
6440             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
6441         } else {
6442             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
6443         }
6444     }
6445 
noteWifiStateLocked(int wifiState, String accessPoint)6446     public void noteWifiStateLocked(int wifiState, String accessPoint) {
6447         noteWifiStateLocked(wifiState, accessPoint, mClocks.elapsedRealtime());
6448     }
6449 
noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs)6450     public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) {
6451         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
6452         if (mWifiState != wifiState) {
6453             if (mWifiState >= 0) {
6454                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtimeMs);
6455             }
6456             mWifiState = wifiState;
6457             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs);
6458             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
6459         }
6460     }
6461 
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth)6462     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
6463         noteWifiSupplicantStateChangedLocked(supplState, failedAuth,
6464                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6465     }
6466 
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth, long elapsedRealtimeMs, long uptimeMs)6467     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth,
6468             long elapsedRealtimeMs, long uptimeMs) {
6469         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
6470         if (mWifiSupplState != supplState) {
6471             if (mWifiSupplState >= 0) {
6472                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtimeMs);
6473             }
6474             mWifiSupplState = supplState;
6475             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
6476             mHistoryCur.states2 =
6477                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
6478                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
6479             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
6480                     + Integer.toHexString(mHistoryCur.states2));
6481             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6482         }
6483     }
6484 
stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)6485     void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
6486         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
6487             if (i == except) {
6488                 continue;
6489             }
6490             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
6491                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
6492             }
6493         }
6494     }
6495 
noteWifiRssiChangedLocked(int newRssi)6496     public void noteWifiRssiChangedLocked(int newRssi) {
6497         noteWifiRssiChangedLocked(newRssi, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6498     }
6499 
noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs)6500     public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) {
6501         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
6502         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
6503         if (mWifiSignalStrengthBin != strengthBin) {
6504             if (mWifiSignalStrengthBin >= 0) {
6505                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
6506                         elapsedRealtimeMs);
6507             }
6508             if (strengthBin >= 0) {
6509                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
6510                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
6511                 }
6512                 mHistoryCur.states2 =
6513                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
6514                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
6515                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
6516                         + Integer.toHexString(mHistoryCur.states2));
6517                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6518             } else {
6519                 stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
6520             }
6521             mWifiSignalStrengthBin = strengthBin;
6522         }
6523     }
6524 
6525     int mWifiFullLockNesting = 0;
6526 
6527     @UnsupportedAppUsage
noteFullWifiLockAcquiredLocked(int uid)6528     public void noteFullWifiLockAcquiredLocked(int uid) {
6529         noteFullWifiLockAcquiredLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6530     }
6531 
noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6532     public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6533         if (mWifiFullLockNesting == 0) {
6534             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
6535             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
6536                     + Integer.toHexString(mHistoryCur.states));
6537             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6538         }
6539         mWifiFullLockNesting++;
6540         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6541                 .noteFullWifiLockAcquiredLocked(elapsedRealtimeMs);
6542     }
6543 
6544     @UnsupportedAppUsage
noteFullWifiLockReleasedLocked(int uid)6545     public void noteFullWifiLockReleasedLocked(int uid) {
6546         noteFullWifiLockReleasedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6547     }
6548 
noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6549     public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6550         mWifiFullLockNesting--;
6551         if (mWifiFullLockNesting == 0) {
6552             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
6553             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
6554                     + Integer.toHexString(mHistoryCur.states));
6555             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6556         }
6557         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6558                 .noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
6559     }
6560 
6561     int mWifiScanNesting = 0;
6562 
noteWifiScanStartedLocked(int uid)6563     public void noteWifiScanStartedLocked(int uid) {
6564         noteWifiScanStartedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6565     }
6566 
noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6567     public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6568         if (mWifiScanNesting == 0) {
6569             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
6570             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
6571                     + Integer.toHexString(mHistoryCur.states));
6572             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6573         }
6574         mWifiScanNesting++;
6575         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6576                 .noteWifiScanStartedLocked(elapsedRealtimeMs);
6577     }
6578 
noteWifiScanStoppedLocked(int uid)6579     public void noteWifiScanStoppedLocked(int uid) {
6580         noteWifiScanStoppedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6581     }
6582 
noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6583     public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6584         mWifiScanNesting--;
6585         if (mWifiScanNesting == 0) {
6586             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
6587             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
6588                     + Integer.toHexString(mHistoryCur.states));
6589             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6590         }
6591         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6592                 .noteWifiScanStoppedLocked(elapsedRealtimeMs);
6593     }
6594 
noteWifiBatchedScanStartedLocked(int uid, int csph)6595     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
6596         noteWifiBatchedScanStartedLocked(uid, csph,
6597                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6598     }
6599 
noteWifiBatchedScanStartedLocked(int uid, int csph, long elapsedRealtimeMs, long uptimeMs)6600     public void noteWifiBatchedScanStartedLocked(int uid, int csph,
6601             long elapsedRealtimeMs, long uptimeMs) {
6602         uid = mapUid(uid);
6603         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6604                 .noteWifiBatchedScanStartedLocked(csph, elapsedRealtimeMs);
6605     }
6606 
noteWifiBatchedScanStoppedLocked(int uid)6607     public void noteWifiBatchedScanStoppedLocked(int uid) {
6608         noteWifiBatchedScanStoppedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6609     }
6610 
noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6611     public void noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6612         uid = mapUid(uid);
6613         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6614                 .noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs);
6615     }
6616 
6617     int mWifiMulticastNesting = 0;
6618 
6619     @UnsupportedAppUsage
noteWifiMulticastEnabledLocked(int uid)6620     public void noteWifiMulticastEnabledLocked(int uid) {
6621         noteWifiMulticastEnabledLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6622     }
6623 
noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6624     public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6625         uid = mapUid(uid);
6626         if (mWifiMulticastNesting == 0) {
6627             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
6628             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
6629                     + Integer.toHexString(mHistoryCur.states));
6630             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6631 
6632             // Start Wifi Multicast overall timer
6633             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
6634                 if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
6635                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
6636             }
6637         }
6638         mWifiMulticastNesting++;
6639         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6640                 .noteWifiMulticastEnabledLocked(elapsedRealtimeMs);
6641     }
6642 
6643     @UnsupportedAppUsage
noteWifiMulticastDisabledLocked(int uid)6644     public void noteWifiMulticastDisabledLocked(int uid) {
6645         noteWifiMulticastDisabledLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6646     }
6647 
noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6648     public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6649         uid = mapUid(uid);
6650         mWifiMulticastNesting--;
6651         if (mWifiMulticastNesting == 0) {
6652             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
6653             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
6654                     + Integer.toHexString(mHistoryCur.states));
6655             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6656 
6657             // Stop Wifi Multicast overall timer
6658             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
6659                 if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
6660                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
6661             }
6662         }
6663         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6664                 .noteWifiMulticastDisabledLocked(elapsedRealtimeMs);
6665     }
6666 
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws)6667     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
6668         noteFullWifiLockAcquiredFromSourceLocked(ws,
6669                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6670     }
6671 
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6672     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws,
6673             long elapsedRealtimeMs, long uptimeMs) {
6674         int N = ws.size();
6675         for (int i=0; i<N; i++) {
6676             final int uid = mapUid(ws.getUid(i));
6677             noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
6678         }
6679 
6680         final List<WorkChain> workChains = ws.getWorkChains();
6681         if (workChains != null) {
6682             for (int i = 0; i < workChains.size(); ++i) {
6683                 final WorkChain workChain = workChains.get(i);
6684                 final int uid = mapUid(workChain.getAttributionUid());
6685                 noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
6686             }
6687         }
6688     }
6689 
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws)6690     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
6691         noteFullWifiLockReleasedFromSourceLocked(ws,
6692                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6693     }
6694 
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6695     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws,
6696             long elapsedRealtimeMs, long uptimeMs) {
6697         int N = ws.size();
6698         for (int i=0; i<N; i++) {
6699             final int uid = mapUid(ws.getUid(i));
6700             noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
6701         }
6702 
6703         final List<WorkChain> workChains = ws.getWorkChains();
6704         if (workChains != null) {
6705             for (int i = 0; i < workChains.size(); ++i) {
6706                 final WorkChain workChain = workChains.get(i);
6707                 final int uid = mapUid(workChain.getAttributionUid());
6708                 noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
6709             }
6710         }
6711     }
6712 
noteWifiScanStartedFromSourceLocked(WorkSource ws)6713     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
6714         noteWifiScanStartedFromSourceLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6715     }
6716 
noteWifiScanStartedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6717     public void noteWifiScanStartedFromSourceLocked(WorkSource ws,
6718             long elapsedRealtimeMs, long uptimeMs) {
6719         int N = ws.size();
6720         for (int i=0; i<N; i++) {
6721             final int uid = mapUid(ws.getUid(i));
6722             noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
6723         }
6724 
6725         final List<WorkChain> workChains = ws.getWorkChains();
6726         if (workChains != null) {
6727             for (int i = 0; i < workChains.size(); ++i) {
6728                 final WorkChain workChain = workChains.get(i);
6729                 final int uid = mapUid(workChain.getAttributionUid());
6730                 noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
6731             }
6732         }
6733     }
6734 
noteWifiScanStoppedFromSourceLocked(WorkSource ws)6735     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
6736         noteWifiScanStoppedFromSourceLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6737     }
6738 
noteWifiScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6739     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws,
6740             long elapsedRealtimeMs, long uptimeMs) {
6741         int N = ws.size();
6742         for (int i=0; i<N; i++) {
6743             final int uid = mapUid(ws.getUid(i));
6744             noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
6745         }
6746 
6747         final List<WorkChain> workChains = ws.getWorkChains();
6748         if (workChains != null) {
6749             for (int i = 0; i < workChains.size(); ++i) {
6750                 final WorkChain workChain = workChains.get(i);
6751                 final int uid = mapUid(workChain.getAttributionUid());
6752                 noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
6753             }
6754         }
6755     }
6756 
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph)6757     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
6758         noteWifiBatchedScanStartedFromSourceLocked(ws, csph,
6759                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6760     }
6761 
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph, long elapsedRealtimeMs, long uptimeMs)6762     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph,
6763             long elapsedRealtimeMs, long uptimeMs) {
6764         int N = ws.size();
6765         for (int i=0; i<N; i++) {
6766             noteWifiBatchedScanStartedLocked(ws.getUid(i), csph, elapsedRealtimeMs, uptimeMs);
6767         }
6768 
6769         final List<WorkChain> workChains = ws.getWorkChains();
6770         if (workChains != null) {
6771             for (int i = 0; i < workChains.size(); ++i) {
6772                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph,
6773                         elapsedRealtimeMs, uptimeMs);
6774             }
6775         }
6776     }
6777 
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws)6778     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
6779         noteWifiBatchedScanStoppedFromSourceLocked(ws,
6780                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6781     }
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6782     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws,
6783             long elapsedRealtimeMs, long uptimeMs) {
6784         int N = ws.size();
6785         for (int i=0; i<N; i++) {
6786             noteWifiBatchedScanStoppedLocked(ws.getUid(i), elapsedRealtimeMs, uptimeMs);
6787         }
6788 
6789         final List<WorkChain> workChains = ws.getWorkChains();
6790         if (workChains != null) {
6791             for (int i = 0; i < workChains.size(); ++i) {
6792                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid(),
6793                         elapsedRealtimeMs, uptimeMs);
6794             }
6795         }
6796     }
6797 
includeInStringArray(String[] array, String str)6798     private static String[] includeInStringArray(String[] array, String str) {
6799         if (ArrayUtils.indexOf(array, str) >= 0) {
6800             return array;
6801         }
6802         String[] newArray = new String[array.length+1];
6803         System.arraycopy(array, 0, newArray, 0, array.length);
6804         newArray[array.length] = str;
6805         return newArray;
6806     }
6807 
excludeFromStringArray(String[] array, String str)6808     private static String[] excludeFromStringArray(String[] array, String str) {
6809         int index = ArrayUtils.indexOf(array, str);
6810         if (index >= 0) {
6811             String[] newArray = new String[array.length-1];
6812             if (index > 0) {
6813                 System.arraycopy(array, 0, newArray, 0, index);
6814             }
6815             if (index < array.length-1) {
6816                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
6817             }
6818             return newArray;
6819         }
6820         return array;
6821     }
6822 
6823     /** @hide */
noteNetworkInterfaceForTransports(String iface, int[] transportTypes)6824     public void noteNetworkInterfaceForTransports(String iface, int[] transportTypes) {
6825         if (TextUtils.isEmpty(iface)) return;
6826         final int displayTransport = NetworkCapabilitiesUtils.getDisplayTransport(transportTypes);
6827 
6828         synchronized (mModemNetworkLock) {
6829             if (displayTransport == TRANSPORT_CELLULAR) {
6830                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
6831                 if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
6832             } else {
6833                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
6834                 if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
6835             }
6836         }
6837 
6838         synchronized (mWifiNetworkLock) {
6839             if (displayTransport == TRANSPORT_WIFI) {
6840                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
6841                 if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
6842             } else {
6843                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
6844                 if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
6845             }
6846         }
6847     }
6848 
6849     /**
6850      * Records timing data related to an incoming Binder call in order to attribute
6851      * the power consumption to the calling app.
6852      */
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)6853     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
6854             Collection<BinderCallsStats.CallStat> callStats) {
6855         noteBinderCallStats(workSourceUid, incrementalCallCount, callStats,
6856                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6857     }
6858 
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats, long elapsedRealtimeMs, long uptimeMs)6859     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
6860             Collection<BinderCallsStats.CallStat> callStats,
6861             long elapsedRealtimeMs, long uptimeMs) {
6862         synchronized (this) {
6863             getUidStatsLocked(workSourceUid, elapsedRealtimeMs, uptimeMs)
6864                     .noteBinderCallStatsLocked(incrementalCallCount, callStats);
6865         }
6866     }
6867 
6868     /**
6869      * Takes note of native IDs of threads taking incoming binder calls. The CPU time
6870      * of these threads is attributed to the apps making those binder calls.
6871      */
noteBinderThreadNativeIds(int[] binderThreadNativeTids)6872     public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) {
6873         mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids);
6874     }
6875 
6876     /**
6877      * Estimates the proportion of system server CPU activity handling incoming binder calls
6878      * that can be attributed to each app
6879      */
6880     @VisibleForTesting
updateSystemServiceCallStats()6881     public void updateSystemServiceCallStats() {
6882         // Start off by computing the average duration of recorded binder calls,
6883         // regardless of which binder or transaction. We will use this as a fallback
6884         // for calls that were not sampled at all.
6885         int totalRecordedCallCount = 0;
6886         long totalRecordedCallTimeMicros = 0;
6887         for (int i = 0; i < mUidStats.size(); i++) {
6888             Uid uid = mUidStats.valueAt(i);
6889             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
6890             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
6891                 BinderCallStats stats = binderCallStats.valueAt(j);
6892                 totalRecordedCallCount += stats.recordedCallCount;
6893                 totalRecordedCallTimeMicros += stats.recordedCpuTimeMicros;
6894             }
6895         }
6896 
6897         long totalSystemServiceTimeMicros = 0;
6898 
6899         // For every UID, use recorded durations of sampled binder calls to estimate
6900         // the total time the system server spent handling requests from this UID.
6901         for (int i = 0; i < mUidStats.size(); i++) {
6902             Uid uid = mUidStats.valueAt(i);
6903 
6904             long totalTimeForUidUs = 0;
6905             int totalCallCountForUid = 0;
6906             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
6907             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
6908                 BinderCallStats stats = binderCallStats.valueAt(j);
6909                 totalCallCountForUid += stats.callCount;
6910                 if (stats.recordedCallCount > 0) {
6911                     totalTimeForUidUs +=
6912                             stats.callCount * stats.recordedCpuTimeMicros / stats.recordedCallCount;
6913                 } else if (totalRecordedCallCount > 0) {
6914                     totalTimeForUidUs +=
6915                             stats.callCount * totalRecordedCallTimeMicros / totalRecordedCallCount;
6916                 }
6917             }
6918 
6919             if (totalCallCountForUid < uid.mBinderCallCount && totalRecordedCallCount > 0) {
6920                 // Estimate remaining calls, which were not tracked because of binder call
6921                 // stats sampling
6922                 totalTimeForUidUs +=
6923                         (uid.mBinderCallCount - totalCallCountForUid) * totalRecordedCallTimeMicros
6924                                 / totalRecordedCallCount;
6925             }
6926 
6927             uid.mSystemServiceTimeUs = totalTimeForUidUs;
6928             totalSystemServiceTimeMicros += totalTimeForUidUs;
6929         }
6930 
6931         for (int i = 0; i < mUidStats.size(); i++) {
6932             Uid uid = mUidStats.valueAt(i);
6933             if (totalSystemServiceTimeMicros > 0) {
6934                 uid.mProportionalSystemServiceUsage =
6935                         (double) uid.mSystemServiceTimeUs / totalSystemServiceTimeMicros;
6936             } else {
6937                 uid.mProportionalSystemServiceUsage = 0;
6938             }
6939         }
6940     }
6941 
getWifiIfaces()6942     public String[] getWifiIfaces() {
6943         synchronized (mWifiNetworkLock) {
6944             return mWifiIfaces;
6945         }
6946     }
6947 
getMobileIfaces()6948     public String[] getMobileIfaces() {
6949         synchronized (mModemNetworkLock) {
6950             return mModemIfaces;
6951         }
6952     }
6953 
6954     @UnsupportedAppUsage
getScreenOnTime(long elapsedRealtimeUs, int which)6955     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
6956         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6957     }
6958 
getScreenOnCount(int which)6959     @Override public int getScreenOnCount(int which) {
6960         return mScreenOnTimer.getCountLocked(which);
6961     }
6962 
getScreenDozeTime(long elapsedRealtimeUs, int which)6963     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
6964         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6965     }
6966 
getScreenDozeCount(int which)6967     @Override public int getScreenDozeCount(int which) {
6968         return mScreenDozeTimer.getCountLocked(which);
6969     }
6970 
6971     @UnsupportedAppUsage
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)6972     @Override public long getScreenBrightnessTime(int brightnessBin,
6973             long elapsedRealtimeUs, int which) {
6974         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
6975                 elapsedRealtimeUs, which);
6976     }
6977 
getScreenBrightnessTimer(int brightnessBin)6978     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
6979         return mScreenBrightnessTimer[brightnessBin];
6980     }
6981 
6982     @Override
getDisplayCount()6983     public int getDisplayCount() {
6984         return mPerDisplayBatteryStats.length;
6985     }
6986 
6987     @Override
getDisplayScreenOnTime(int display, long elapsedRealtimeUs)6988     public long getDisplayScreenOnTime(int display, long elapsedRealtimeUs) {
6989         return mPerDisplayBatteryStats[display].screenOnTimer.getTotalTimeLocked(elapsedRealtimeUs,
6990                 STATS_SINCE_CHARGED);
6991     }
6992 
6993     @Override
getDisplayScreenDozeTime(int display, long elapsedRealtimeUs)6994     public long getDisplayScreenDozeTime(int display, long elapsedRealtimeUs) {
6995         return mPerDisplayBatteryStats[display].screenDozeTimer.getTotalTimeLocked(
6996                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
6997     }
6998 
6999     @Override
getDisplayScreenBrightnessTime(int display, int brightnessBin, long elapsedRealtimeUs)7000     public long getDisplayScreenBrightnessTime(int display, int brightnessBin,
7001             long elapsedRealtimeUs) {
7002         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
7003         return displayStats.screenBrightnessTimers[brightnessBin].getTotalTimeLocked(
7004                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
7005     }
7006 
getInteractiveTime(long elapsedRealtimeUs, int which)7007     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
7008         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7009     }
7010 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)7011     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
7012         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7013     }
7014 
getPowerSaveModeEnabledCount(int which)7015     @Override public int getPowerSaveModeEnabledCount(int which) {
7016         return mPowerSaveModeEnabledTimer.getCountLocked(which);
7017     }
7018 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)7019     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
7020             int which) {
7021         switch (mode) {
7022             case DEVICE_IDLE_MODE_LIGHT:
7023                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7024             case DEVICE_IDLE_MODE_DEEP:
7025                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7026         }
7027         return 0;
7028     }
7029 
getDeviceIdleModeCount(int mode, int which)7030     @Override public int getDeviceIdleModeCount(int mode, int which) {
7031         switch (mode) {
7032             case DEVICE_IDLE_MODE_LIGHT:
7033                 return mDeviceIdleModeLightTimer.getCountLocked(which);
7034             case DEVICE_IDLE_MODE_DEEP:
7035                 return mDeviceIdleModeFullTimer.getCountLocked(which);
7036         }
7037         return 0;
7038     }
7039 
getLongestDeviceIdleModeTime(int mode)7040     @Override public long getLongestDeviceIdleModeTime(int mode) {
7041         switch (mode) {
7042             case DEVICE_IDLE_MODE_LIGHT:
7043                 return mLongestLightIdleTimeMs;
7044             case DEVICE_IDLE_MODE_DEEP:
7045                 return mLongestFullIdleTimeMs;
7046         }
7047         return 0;
7048     }
7049 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)7050     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
7051         switch (mode) {
7052             case DEVICE_IDLE_MODE_LIGHT:
7053                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7054             case DEVICE_IDLE_MODE_DEEP:
7055                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7056         }
7057         return 0;
7058     }
7059 
getDeviceIdlingCount(int mode, int which)7060     @Override public int getDeviceIdlingCount(int mode, int which) {
7061         switch (mode) {
7062             case DEVICE_IDLE_MODE_LIGHT:
7063                 return mDeviceLightIdlingTimer.getCountLocked(which);
7064             case DEVICE_IDLE_MODE_DEEP:
7065                 return mDeviceIdlingTimer.getCountLocked(which);
7066         }
7067         return 0;
7068     }
7069 
getNumConnectivityChange(int which)7070     @Override public int getNumConnectivityChange(int which) {
7071         return mNumConnectivityChange;
7072     }
7073 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)7074     @Override public long getGpsSignalQualityTime(int strengthBin,
7075             long elapsedRealtimeUs, int which) {
7076         if (strengthBin < 0 || strengthBin >= mGpsSignalQualityTimer.length) {
7077             return 0;
7078         }
7079         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
7080                 elapsedRealtimeUs, which);
7081     }
7082 
getGpsBatteryDrainMaMs()7083     @Override public long getGpsBatteryDrainMaMs() {
7084         final double opVolt = mPowerProfile.getAveragePower(
7085             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
7086         if (opVolt == 0) {
7087             return 0;
7088         }
7089         double energyUsedMaMs = 0.0;
7090         final int which = STATS_SINCE_CHARGED;
7091         final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
7092         for(int i=0; i < mGpsSignalQualityTimer.length; i++) {
7093             energyUsedMaMs
7094                     += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
7095                     * (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000);
7096         }
7097         return (long) energyUsedMaMs;
7098     }
7099 
7100     @UnsupportedAppUsage
getPhoneOnTime(long elapsedRealtimeUs, int which)7101     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
7102         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7103     }
7104 
getPhoneOnCount(int which)7105     @Override public int getPhoneOnCount(int which) {
7106         return mPhoneOnTimer.getCountLocked(which);
7107     }
7108 
7109     @UnsupportedAppUsage
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)7110     @Override public long getPhoneSignalStrengthTime(int strengthBin,
7111             long elapsedRealtimeUs, int which) {
7112         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
7113                 elapsedRealtimeUs, which);
7114     }
7115 
7116     @UnsupportedAppUsage
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)7117     @Override public long getPhoneSignalScanningTime(
7118             long elapsedRealtimeUs, int which) {
7119         return mPhoneSignalScanningTimer.getTotalTimeLocked(
7120                 elapsedRealtimeUs, which);
7121     }
7122 
getPhoneSignalScanningTimer()7123     @Override public Timer getPhoneSignalScanningTimer() {
7124         return mPhoneSignalScanningTimer;
7125     }
7126 
7127     @UnsupportedAppUsage
getPhoneSignalStrengthCount(int strengthBin, int which)7128     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
7129         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
7130     }
7131 
getPhoneSignalStrengthTimer(int strengthBin)7132     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
7133         return mPhoneSignalStrengthsTimer[strengthBin];
7134     }
7135 
7136     @UnsupportedAppUsage
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)7137     @Override public long getPhoneDataConnectionTime(int dataType,
7138             long elapsedRealtimeUs, int which) {
7139         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
7140                 elapsedRealtimeUs, which);
7141     }
7142 
7143     @UnsupportedAppUsage
getPhoneDataConnectionCount(int dataType, int which)7144     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
7145         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
7146     }
7147 
getPhoneDataConnectionTimer(int dataType)7148     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
7149         return mPhoneDataConnectionsTimer[dataType];
7150     }
7151 
7152     @UnsupportedAppUsage
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)7153     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
7154         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7155     }
7156 
getMobileRadioActiveCount(int which)7157     @Override public int getMobileRadioActiveCount(int which) {
7158         return mMobileRadioActiveTimer.getCountLocked(which);
7159     }
7160 
getMobileRadioActiveAdjustedTime(int which)7161     @Override public long getMobileRadioActiveAdjustedTime(int which) {
7162         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
7163     }
7164 
getMobileRadioActiveUnknownTime(int which)7165     @Override public long getMobileRadioActiveUnknownTime(int which) {
7166         return mMobileRadioActiveUnknownTime.getCountLocked(which);
7167     }
7168 
getMobileRadioActiveUnknownCount(int which)7169     @Override public int getMobileRadioActiveUnknownCount(int which) {
7170         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
7171     }
7172 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)7173     @Override public long getWifiMulticastWakelockTime(
7174             long elapsedRealtimeUs, int which) {
7175         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
7176                 elapsedRealtimeUs, which);
7177     }
7178 
getWifiMulticastWakelockCount(int which)7179     @Override public int getWifiMulticastWakelockCount(int which) {
7180         return mWifiMulticastWakelockTimer.getCountLocked(which);
7181     }
7182 
7183     @UnsupportedAppUsage
getWifiOnTime(long elapsedRealtimeUs, int which)7184     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
7185         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7186     }
7187 
getWifiActiveTime(long elapsedRealtimeUs, int which)7188     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
7189         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7190     }
7191 
7192     @UnsupportedAppUsage
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)7193     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
7194         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7195     }
7196 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)7197     @Override public long getWifiStateTime(int wifiState,
7198             long elapsedRealtimeUs, int which) {
7199         return mWifiStateTimer[wifiState].getTotalTimeLocked(
7200                 elapsedRealtimeUs, which);
7201     }
7202 
getWifiStateCount(int wifiState, int which)7203     @Override public int getWifiStateCount(int wifiState, int which) {
7204         return mWifiStateTimer[wifiState].getCountLocked(which);
7205     }
7206 
getWifiStateTimer(int wifiState)7207     @Override public Timer getWifiStateTimer(int wifiState) {
7208         return mWifiStateTimer[wifiState];
7209     }
7210 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)7211     @Override public long getWifiSupplStateTime(int state,
7212             long elapsedRealtimeUs, int which) {
7213         return mWifiSupplStateTimer[state].getTotalTimeLocked(
7214                 elapsedRealtimeUs, which);
7215     }
7216 
getWifiSupplStateCount(int state, int which)7217     @Override public int getWifiSupplStateCount(int state, int which) {
7218         return mWifiSupplStateTimer[state].getCountLocked(which);
7219     }
7220 
getWifiSupplStateTimer(int state)7221     @Override public Timer getWifiSupplStateTimer(int state) {
7222         return mWifiSupplStateTimer[state];
7223     }
7224 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)7225     @Override public long getWifiSignalStrengthTime(int strengthBin,
7226             long elapsedRealtimeUs, int which) {
7227         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
7228                 elapsedRealtimeUs, which);
7229     }
7230 
getWifiSignalStrengthCount(int strengthBin, int which)7231     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
7232         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
7233     }
7234 
getWifiSignalStrengthTimer(int strengthBin)7235     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
7236         return mWifiSignalStrengthsTimer[strengthBin];
7237     }
7238 
7239     @Override
getBluetoothControllerActivity()7240     public ControllerActivityCounter getBluetoothControllerActivity() {
7241         return mBluetoothActivity;
7242     }
7243 
7244     @Override
getWifiControllerActivity()7245     public ControllerActivityCounter getWifiControllerActivity() {
7246         return mWifiActivity;
7247     }
7248 
7249     @Override
getModemControllerActivity()7250     public ControllerActivityCounter getModemControllerActivity() {
7251         return mModemActivity;
7252     }
7253 
7254     @Override
hasBluetoothActivityReporting()7255     public boolean hasBluetoothActivityReporting() {
7256         return mHasBluetoothReporting;
7257     }
7258 
7259     @Override
hasWifiActivityReporting()7260     public boolean hasWifiActivityReporting() {
7261         return mHasWifiReporting;
7262     }
7263 
7264     @Override
hasModemActivityReporting()7265     public boolean hasModemActivityReporting() {
7266         return mHasModemReporting;
7267     }
7268 
7269     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)7270     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
7271         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7272     }
7273 
7274     @Override
getFlashlightOnCount(int which)7275     public long getFlashlightOnCount(int which) {
7276         return mFlashlightOnTimer.getCountLocked(which);
7277     }
7278 
7279     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)7280     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
7281         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7282     }
7283 
7284     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)7285     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
7286         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7287     }
7288 
7289     @Override
7290     @UnsupportedAppUsage
getNetworkActivityBytes(int type, int which)7291     public long getNetworkActivityBytes(int type, int which) {
7292         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
7293             return mNetworkByteActivityCounters[type].getCountLocked(which);
7294         } else {
7295             return 0;
7296         }
7297     }
7298 
7299     @Override
getNetworkActivityPackets(int type, int which)7300     public long getNetworkActivityPackets(int type, int which) {
7301         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
7302             return mNetworkPacketActivityCounters[type].getCountLocked(which);
7303         } else {
7304             return 0;
7305         }
7306     }
7307 
7308     @Override
getBluetoothMeasuredBatteryConsumptionUC()7309     public long getBluetoothMeasuredBatteryConsumptionUC() {
7310         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
7311     }
7312 
7313     @Override
getCpuMeasuredBatteryConsumptionUC()7314     public long getCpuMeasuredBatteryConsumptionUC() {
7315         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
7316     }
7317 
7318     @Override
getGnssMeasuredBatteryConsumptionUC()7319     public long getGnssMeasuredBatteryConsumptionUC() {
7320         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS);
7321     }
7322 
7323     @Override
getMobileRadioMeasuredBatteryConsumptionUC()7324     public long getMobileRadioMeasuredBatteryConsumptionUC() {
7325         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO);
7326     }
7327 
7328     @Override
getScreenOnMeasuredBatteryConsumptionUC()7329     public long getScreenOnMeasuredBatteryConsumptionUC() {
7330         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
7331     }
7332 
7333     @Override
getScreenDozeMeasuredBatteryConsumptionUC()7334     public long getScreenDozeMeasuredBatteryConsumptionUC() {
7335         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE);
7336     }
7337 
7338     @Override
getWifiMeasuredBatteryConsumptionUC()7339     public long getWifiMeasuredBatteryConsumptionUC() {
7340         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
7341     }
7342 
7343     /**
7344      * Returns the consumption (in microcoulombs) that the given standard power bucket consumed.
7345      * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable
7346      *
7347      * @param bucket standard power bucket of interest
7348      * @return charge (in microcoulombs) used for this power bucket
7349      */
getPowerBucketConsumptionUC(@tandardPowerBucket int bucket)7350     private long getPowerBucketConsumptionUC(@StandardPowerBucket int bucket) {
7351         if (mGlobalMeasuredEnergyStats == null) {
7352             return POWER_DATA_UNAVAILABLE;
7353         }
7354         return mGlobalMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket);
7355     }
7356 
7357     @Override
getCustomConsumerMeasuredBatteryConsumptionUC()7358     public @Nullable long[] getCustomConsumerMeasuredBatteryConsumptionUC() {
7359         if (mGlobalMeasuredEnergyStats == null) {
7360             return null;
7361         }
7362         return mGlobalMeasuredEnergyStats.getAccumulatedCustomBucketCharges();
7363     }
7364 
7365     /**
7366      * Returns the names of custom power components.
7367      */
7368     @Override
getCustomEnergyConsumerNames()7369     public @NonNull String[] getCustomEnergyConsumerNames() {
7370         if (mGlobalMeasuredEnergyStats == null) {
7371             return new String[0];
7372         }
7373         final String[] names = mGlobalMeasuredEnergyStats.getCustomBucketNames();
7374         for (int i = 0; i < names.length; i++) {
7375             if (TextUtils.isEmpty(names[i])) {
7376                 names[i] = "CUSTOM_" + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i;
7377             }
7378         }
7379         return names;
7380     }
7381 
getStartClockTime()7382     @Override public long getStartClockTime() {
7383         final long currentTimeMs = mClocks.currentTimeMillis();
7384         if ((currentTimeMs > MILLISECONDS_IN_YEAR
7385                 && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
7386                 || (mStartClockTimeMs > currentTimeMs)) {
7387             // If the start clock time has changed by more than a year, then presumably
7388             // the previous time was completely bogus.  So we are going to figure out a
7389             // new time based on how much time has elapsed since we started counting.
7390             recordCurrentTimeChangeLocked(currentTimeMs, mClocks.elapsedRealtime(),
7391                     mClocks.uptimeMillis());
7392             return currentTimeMs - (mClocks.elapsedRealtime() - (mRealtimeStartUs / 1000));
7393         }
7394         return mStartClockTimeMs;
7395     }
7396 
getStartPlatformVersion()7397     @Override public String getStartPlatformVersion() {
7398         return mStartPlatformVersion;
7399     }
7400 
getEndPlatformVersion()7401     @Override public String getEndPlatformVersion() {
7402         return mEndPlatformVersion;
7403     }
7404 
getParcelVersion()7405     @Override public int getParcelVersion() {
7406         return VERSION;
7407     }
7408 
getIsOnBattery()7409     @Override public boolean getIsOnBattery() {
7410         return mOnBattery;
7411     }
7412 
getStatsStartRealtime()7413     @Override public long getStatsStartRealtime() {
7414         return mRealtimeStartUs;
7415     }
7416 
7417     @UnsupportedAppUsage
getUidStats()7418     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
7419         return mUidStats;
7420     }
7421 
resetIfNotNull(T t, boolean detachIfReset, long elapsedRealtimeUs)7422     private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset,
7423             long elapsedRealtimeUs) {
7424         if (t != null) {
7425             return t.reset(detachIfReset, elapsedRealtimeUs);
7426         }
7427         return true;
7428     }
7429 
resetIfNotNull(T[] t, boolean detachIfReset, long elapsedRealtimeUs)7430     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset,
7431             long elapsedRealtimeUs) {
7432         if (t != null) {
7433             boolean ret = true;
7434             for (int i = 0; i < t.length; i++) {
7435                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
7436             }
7437             return ret;
7438         }
7439         return true;
7440     }
7441 
resetIfNotNull(T[][] t, boolean detachIfReset, long elapsedRealtimeUs)7442     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset,
7443             long elapsedRealtimeUs) {
7444         if (t != null) {
7445             boolean ret = true;
7446             for (int i = 0; i < t.length; i++) {
7447                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
7448             }
7449             return ret;
7450         }
7451         return true;
7452     }
7453 
resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset, long elapsedRealtimeUs)7454     private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
7455             boolean detachIfReset, long elapsedRealtimeUs) {
7456         if (counter != null) {
7457             counter.reset(detachIfReset, elapsedRealtimeUs);
7458         }
7459         return true;
7460     }
7461 
detachIfNotNull(T t)7462     private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
7463         if (t != null) {
7464             t.detach();
7465         }
7466     }
7467 
detachIfNotNull(T[] t)7468     private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
7469         if (t != null) {
7470             for (int i = 0; i < t.length; i++) {
7471                 detachIfNotNull(t[i]);
7472             }
7473         }
7474     }
7475 
detachIfNotNull(T[][] t)7476     private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
7477         if (t != null) {
7478             for (int i = 0; i < t.length; i++) {
7479                 detachIfNotNull(t[i]);
7480             }
7481         }
7482     }
7483 
detachIfNotNull(ControllerActivityCounterImpl counter)7484     private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
7485         if (counter != null) {
7486             counter.detach();
7487         }
7488     }
7489 
7490     /**
7491      * Accumulates stats for a specific binder transaction.
7492      */
7493     @VisibleForTesting
7494     protected static class BinderCallStats {
7495         static final Comparator<BinderCallStats> COMPARATOR =
7496                 Comparator.comparing(BinderCallStats::getClassName)
7497                         .thenComparing(BinderCallStats::getMethodName);
7498 
7499         public Class<? extends Binder> binderClass;
7500         public int transactionCode;
7501         public String methodName;
7502 
7503         public long callCount;
7504         public long recordedCallCount;
7505         public long recordedCpuTimeMicros;
7506 
7507 
7508         @Override
hashCode()7509         public int hashCode() {
7510             return binderClass.hashCode() * 31 + transactionCode;
7511         }
7512 
7513         @Override
equals(Object obj)7514         public boolean equals(Object obj) {
7515             if (!(obj instanceof BinderCallStats)) {
7516                 return false;
7517             }
7518             BinderCallStats bcsk = (BinderCallStats) obj;
7519             return binderClass.equals(bcsk.binderClass) && transactionCode == bcsk.transactionCode;
7520         }
7521 
getClassName()7522         public String getClassName() {
7523             return binderClass.getName();
7524         }
7525 
getMethodName()7526         public String getMethodName() {
7527             return methodName;
7528         }
7529 
7530         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
ensureMethodName(BinderTransactionNameResolver resolver)7531         public void ensureMethodName(BinderTransactionNameResolver resolver) {
7532             if (methodName == null) {
7533                 methodName = resolver.getMethodName(binderClass, transactionCode);
7534             }
7535         }
7536 
7537         @Override
toString()7538         public String toString() {
7539             return "BinderCallStats{"
7540                     + binderClass
7541                     + " transaction=" + transactionCode
7542                     + " callCount=" + callCount
7543                     + " recordedCallCount=" + recordedCallCount
7544                     + " recorderCpuTimeMicros=" + recordedCpuTimeMicros
7545                     + "}";
7546         }
7547     }
7548 
7549     /**
7550      * The statistics associated with a particular uid.
7551      */
7552     public static class Uid extends BatteryStats.Uid {
7553         /**
7554          * BatteryStatsImpl that we are associated with.
7555          */
7556         protected BatteryStatsImpl mBsi;
7557 
7558         final int mUid;
7559 
7560         /** TimeBase for when uid is in background and device is on battery. */
7561         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
7562         public final TimeBase mOnBatteryBackgroundTimeBase;
7563         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
7564         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
7565 
7566         boolean mWifiRunning;
7567         StopwatchTimer mWifiRunningTimer;
7568 
7569         boolean mFullWifiLockOut;
7570         StopwatchTimer mFullWifiLockTimer;
7571 
7572         boolean mWifiScanStarted;
7573         DualTimer mWifiScanTimer;
7574 
7575         static final int NO_BATCHED_SCAN_STARTED = -1;
7576         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7577         StopwatchTimer[] mWifiBatchedScanTimer;
7578 
7579         int mWifiMulticastWakelockCount;
7580         StopwatchTimer mWifiMulticastTimer;
7581 
7582         StopwatchTimer mAudioTurnedOnTimer;
7583         StopwatchTimer mVideoTurnedOnTimer;
7584         StopwatchTimer mFlashlightTurnedOnTimer;
7585         StopwatchTimer mCameraTurnedOnTimer;
7586         StopwatchTimer mForegroundActivityTimer;
7587         StopwatchTimer mForegroundServiceTimer;
7588         /** Total time spent by the uid holding any partial wakelocks. */
7589         DualTimer mAggregatedPartialWakelockTimer;
7590         DualTimer mBluetoothScanTimer;
7591         DualTimer mBluetoothUnoptimizedScanTimer;
7592         Counter mBluetoothScanResultCounter;
7593         Counter mBluetoothScanResultBgCounter;
7594 
7595         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
7596         StopwatchTimer[] mProcessStateTimer;
7597 
7598         boolean mInForegroundService = false;
7599 
7600         BatchTimer mVibratorOnTimer;
7601 
7602         Counter[] mUserActivityCounters;
7603 
7604         LongSamplingCounter[] mNetworkByteActivityCounters;
7605         LongSamplingCounter[] mNetworkPacketActivityCounters;
7606         LongSamplingCounter mMobileRadioActiveTime;
7607         LongSamplingCounter mMobileRadioActiveCount;
7608 
7609         /**
7610          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
7611          */
7612         private LongSamplingCounter mMobileRadioApWakeupCount;
7613 
7614         /**
7615          * How many times this UID woke up the Application Processor due to a Wifi packet.
7616          */
7617         private LongSamplingCounter mWifiRadioApWakeupCount;
7618 
7619         /**
7620          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
7621          * Can be null if the UID has had no such activity.
7622          */
7623         private ControllerActivityCounterImpl mWifiControllerActivity;
7624 
7625         /**
7626          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
7627          * Can be null if the UID has had no such activity.
7628          */
7629         private ControllerActivityCounterImpl mBluetoothControllerActivity;
7630 
7631         /**
7632          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
7633          * Can be null if the UID has had no such activity.
7634          */
7635         private ControllerActivityCounterImpl mModemControllerActivity;
7636 
7637         /**
7638          * The CPU times we had at the last history details update.
7639          */
7640         long mLastStepUserTimeMs;
7641         long mLastStepSystemTimeMs;
7642         long mCurStepUserTimeMs;
7643         long mCurStepSystemTimeMs;
7644 
7645         LongSamplingCounter mUserCpuTime;
7646         LongSamplingCounter mSystemCpuTime;
7647         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
7648         LongSamplingCounter mCpuActiveTimeMs;
7649 
7650         LongSamplingCounterArray mCpuFreqTimeMs;
7651         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
7652         LongSamplingCounterArray mCpuClusterTimesMs;
7653 
7654         LongSamplingCounterArray[] mProcStateTimeMs;
7655         LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
7656 
7657         IntArray mChildUids;
7658 
7659         /**
7660          * The statistics we have collected for this uid's wake locks.
7661          */
7662         final OverflowArrayMap<Wakelock> mWakelockStats;
7663 
7664         /**
7665          * The statistics we have collected for this uid's syncs.
7666          */
7667         final OverflowArrayMap<DualTimer> mSyncStats;
7668 
7669         /**
7670          * The statistics we have collected for this uid's jobs.
7671          */
7672         final OverflowArrayMap<DualTimer> mJobStats;
7673 
7674         /**
7675          * Count of the jobs that have completed and the reasons why they completed.
7676          */
7677         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
7678 
7679         /**
7680          * Count of app launch events that had associated deferred job counts or info about
7681          * last time a job was run.
7682          */
7683         Counter mJobsDeferredEventCount;
7684 
7685         /**
7686          * Count of deferred jobs that were pending when the app was launched or brought to
7687          * the foreground through a user interaction.
7688          */
7689         Counter mJobsDeferredCount;
7690 
7691         /**
7692          * Sum of time since the last time a job was run for this app before it was launched.
7693          */
7694         LongSamplingCounter mJobsFreshnessTimeMs;
7695 
7696         /**
7697          * Array of counts of instances where the time since the last job was run for the app
7698          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
7699          */
7700         final Counter[] mJobsFreshnessBuckets;
7701 
7702         /**
7703          * The statistics we have collected for this uid's sensor activations.
7704          */
7705         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
7706 
7707         /**
7708          * The statistics we have collected for this uid's processes.
7709          */
7710         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
7711 
7712         /**
7713          * The statistics we have collected for this uid's processes.
7714          */
7715         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
7716 
7717         /**
7718          * The transient wake stats we have collected for this uid's pids.
7719          */
7720         final SparseArray<Pid> mPids = new SparseArray<>();
7721 
7722         /**
7723          * Grand total of system server binder calls made by this uid.
7724          */
7725         private long mBinderCallCount;
7726 
7727         /**
7728          * Detailed information about system server binder calls made by this uid.
7729          */
7730         private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>();
7731 
7732         /**
7733          * Measured charge consumption by this uid while on battery.
7734          * Its '<b>custom</b> power buckets' correspond to the
7735          * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
7736          * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
7737          *
7738          * Will be null if energy consumer data is completely unavailable (in which case
7739          * {@link #mGlobalMeasuredEnergyStats} will also be null) or if the power usage by this uid
7740          * is 0 for every bucket.
7741          */
7742         private MeasuredEnergyStats mUidMeasuredEnergyStats;
7743 
7744         /**
7745          * Estimated total time spent by the system server handling requests from this uid.
7746          */
7747         private long mSystemServiceTimeUs;
7748 
7749         /**
7750          * Estimated proportion of system server binder call CPU cost for this uid.
7751          */
7752         private double mProportionalSystemServiceUsage;
7753 
Uid(BatteryStatsImpl bsi, int uid)7754         public Uid(BatteryStatsImpl bsi, int uid) {
7755             this(bsi, uid, bsi.mClocks.elapsedRealtime(), bsi.mClocks.uptimeMillis());
7756         }
7757 
Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs)7758         public Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs) {
7759             mBsi = bsi;
7760             mUid = uid;
7761 
7762             /* Observer list of TimeBase object in Uid is short */
7763             mOnBatteryBackgroundTimeBase = new TimeBase(false);
7764             mOnBatteryBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
7765             /* Observer list of TimeBase object in Uid is short */
7766             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
7767             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
7768 
7769             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7770             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7771             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7772             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
7773 
7774             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
7775                 @Override public Wakelock instantiateObject() {
7776                     return new Wakelock(mBsi, Uid.this);
7777                 }
7778             };
7779             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
7780                 @Override public DualTimer instantiateObject() {
7781                     return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
7782                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7783                 }
7784             };
7785             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
7786                 @Override public DualTimer instantiateObject() {
7787                     return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
7788                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7789                 }
7790             };
7791 
7792             mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
7793                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
7794             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
7795                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
7796             mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
7797                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7798             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
7799             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
7800                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
7801             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
7802             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
7803             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
7804             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7805             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
7806         }
7807 
7808         @VisibleForTesting
setProcessStateForTest(int procState)7809         public void setProcessStateForTest(int procState) {
7810             mProcessState = procState;
7811         }
7812 
7813         @Override
getCpuFreqTimes(int which)7814         public long[] getCpuFreqTimes(int which) {
7815             return nullIfAllZeros(mCpuFreqTimeMs, which);
7816         }
7817 
7818         @Override
getScreenOffCpuFreqTimes(int which)7819         public long[] getScreenOffCpuFreqTimes(int which) {
7820             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
7821         }
7822 
7823         @Override
getCpuActiveTime()7824         public long getCpuActiveTime() {
7825             return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
7826         }
7827 
7828         @Override
getCpuClusterTimes()7829         public long[] getCpuClusterTimes() {
7830             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
7831         }
7832 
7833         @Override
getCpuFreqTimes(int which, int procState)7834         public long[] getCpuFreqTimes(int which, int procState) {
7835             if (which < 0 || which >= NUM_PROCESS_STATE) {
7836                 return null;
7837             }
7838             if (mProcStateTimeMs == null) {
7839                 return null;
7840             }
7841             if (!mBsi.mPerProcStateCpuTimesAvailable) {
7842                 mProcStateTimeMs = null;
7843                 return null;
7844             }
7845             return nullIfAllZeros(mProcStateTimeMs[procState], which);
7846         }
7847 
7848         @Override
getScreenOffCpuFreqTimes(int which, int procState)7849         public long[] getScreenOffCpuFreqTimes(int which, int procState) {
7850             if (which < 0 || which >= NUM_PROCESS_STATE) {
7851                 return null;
7852             }
7853             if (mProcStateScreenOffTimeMs == null) {
7854                 return null;
7855             }
7856             if (!mBsi.mPerProcStateCpuTimesAvailable) {
7857                 mProcStateScreenOffTimeMs = null;
7858                 return null;
7859             }
7860             return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which);
7861         }
7862 
getBinderCallCount()7863         public long getBinderCallCount() {
7864             return mBinderCallCount;
7865         }
7866 
7867         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
getBinderCallStats()7868         public ArraySet<BinderCallStats> getBinderCallStats() {
7869             return mBinderCallStats;
7870         }
7871 
7872         @Override
getProportionalSystemServiceUsage()7873         public  double getProportionalSystemServiceUsage() {
7874             return mProportionalSystemServiceUsage;
7875         }
7876 
addIsolatedUid(int isolatedUid)7877         public void addIsolatedUid(int isolatedUid) {
7878             if (mChildUids == null) {
7879                 mChildUids = new IntArray();
7880             } else if (mChildUids.indexOf(isolatedUid) >= 0) {
7881                 return;
7882             }
7883             mChildUids.add(isolatedUid);
7884         }
7885 
removeIsolatedUid(int isolatedUid)7886         public void removeIsolatedUid(int isolatedUid) {
7887             final int idx = mChildUids == null ? -1 : mChildUids.indexOf(isolatedUid);
7888             if (idx < 0) {
7889                 return;
7890             }
7891             mChildUids.remove(idx);
7892         }
7893 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)7894         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
7895             if (cpuTimesMs == null) {
7896                 return null;
7897             }
7898             final long[] counts = cpuTimesMs.getCountsLocked(which);
7899             if (counts == null) {
7900                 return null;
7901             }
7902             // Return counts only if at least one of the elements is non-zero.
7903             for (int i = counts.length - 1; i >= 0; --i) {
7904                 if (counts[i] != 0) {
7905                     return counts;
7906                 }
7907             }
7908             return null;
7909         }
7910 
addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery)7911         private void addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery) {
7912             if (mProcStateTimeMs == null) {
7913                 mProcStateTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
7914             }
7915             if (mProcStateTimeMs[procState] == null
7916                     || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
7917                 detachIfNotNull(mProcStateTimeMs[procState]);
7918                 mProcStateTimeMs[procState] = new LongSamplingCounterArray(
7919                         mBsi.mOnBatteryTimeBase);
7920             }
7921             mProcStateTimeMs[procState].addCountLocked(cpuTimesMs, onBattery);
7922         }
7923 
addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs, boolean onBatteryScreenOff)7924         private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs,
7925                 boolean onBatteryScreenOff) {
7926             if (mProcStateScreenOffTimeMs == null) {
7927                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
7928             }
7929             if (mProcStateScreenOffTimeMs[procState] == null
7930                     || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) {
7931                 detachIfNotNull(mProcStateScreenOffTimeMs[procState]);
7932                 mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
7933                         mBsi.mOnBatteryScreenOffTimeBase);
7934             }
7935             mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs, onBatteryScreenOff);
7936         }
7937 
7938         @Override
getAggregatedPartialWakelockTimer()7939         public Timer getAggregatedPartialWakelockTimer() {
7940             return mAggregatedPartialWakelockTimer;
7941         }
7942 
7943         @Override
7944         @UnsupportedAppUsage
getWakelockStats()7945         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
7946             return mWakelockStats.getMap();
7947         }
7948 
7949         @Override
getMulticastWakelockStats()7950         public Timer getMulticastWakelockStats() {
7951             return mWifiMulticastTimer;
7952         }
7953 
7954         @Override
getSyncStats()7955         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
7956             return mSyncStats.getMap();
7957         }
7958 
7959         @Override
getJobStats()7960         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
7961             return mJobStats.getMap();
7962         }
7963 
7964         @Override
getJobCompletionStats()7965         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
7966             return mJobCompletions;
7967         }
7968 
7969         @Override
7970         @UnsupportedAppUsage
getSensorStats()7971         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
7972             return mSensorStats;
7973         }
7974 
7975         @Override
7976         @UnsupportedAppUsage
getProcessStats()7977         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
7978             return mProcessStats;
7979         }
7980 
7981         @Override
getPackageStats()7982         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
7983             return mPackageStats;
7984         }
7985 
7986         @Override
7987         @UnsupportedAppUsage
getUid()7988         public int getUid() {
7989             return mUid;
7990         }
7991 
7992         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)7993         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
7994             if (!mWifiRunning) {
7995                 mWifiRunning = true;
7996                 if (mWifiRunningTimer == null) {
7997                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
7998                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
7999                 }
8000                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
8001             }
8002         }
8003 
8004         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)8005         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
8006             if (mWifiRunning) {
8007                 mWifiRunning = false;
8008                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
8009             }
8010         }
8011 
8012         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)8013         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
8014             if (!mFullWifiLockOut) {
8015                 mFullWifiLockOut = true;
8016                 if (mFullWifiLockTimer == null) {
8017                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
8018                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
8019                 }
8020                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
8021             }
8022         }
8023 
8024         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)8025         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
8026             if (mFullWifiLockOut) {
8027                 mFullWifiLockOut = false;
8028                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
8029             }
8030         }
8031 
8032         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)8033         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
8034             if (!mWifiScanStarted) {
8035                 mWifiScanStarted = true;
8036                 if (mWifiScanTimer == null) {
8037                     mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
8038                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
8039                             mOnBatteryBackgroundTimeBase);
8040                 }
8041                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
8042             }
8043         }
8044 
8045         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)8046         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
8047             if (mWifiScanStarted) {
8048                 mWifiScanStarted = false;
8049                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
8050             }
8051         }
8052 
8053         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)8054         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
8055             int bin = 0;
8056             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
8057                 csph = csph >> 3;
8058                 bin++;
8059             }
8060 
8061             if (mWifiBatchedScanBinStarted == bin) return;
8062 
8063             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
8064                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
8065                         stopRunningLocked(elapsedRealtimeMs);
8066             }
8067             mWifiBatchedScanBinStarted = bin;
8068             if (mWifiBatchedScanTimer[bin] == null) {
8069                 makeWifiBatchedScanBin(bin, null);
8070             }
8071             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
8072         }
8073 
8074         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)8075         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
8076             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
8077                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
8078                         stopRunningLocked(elapsedRealtimeMs);
8079                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8080             }
8081         }
8082 
8083         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)8084         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
8085             if (mWifiMulticastWakelockCount == 0) {
8086                 if (mWifiMulticastTimer == null) {
8087                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8088                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
8089                 }
8090                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
8091             }
8092             mWifiMulticastWakelockCount++;
8093         }
8094 
8095         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)8096         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
8097             if (mWifiMulticastWakelockCount == 0) {
8098                 return;
8099             }
8100 
8101             mWifiMulticastWakelockCount--;
8102             if (mWifiMulticastWakelockCount == 0) {
8103                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
8104             }
8105         }
8106 
8107         @Override
getWifiControllerActivity()8108         public ControllerActivityCounter getWifiControllerActivity() {
8109             return mWifiControllerActivity;
8110         }
8111 
8112         @Override
getBluetoothControllerActivity()8113         public ControllerActivityCounter getBluetoothControllerActivity() {
8114             return mBluetoothControllerActivity;
8115         }
8116 
8117         @Override
getModemControllerActivity()8118         public ControllerActivityCounter getModemControllerActivity() {
8119             return mModemControllerActivity;
8120         }
8121 
getOrCreateWifiControllerActivityLocked()8122         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
8123             if (mWifiControllerActivity == null) {
8124                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8125                         NUM_BT_TX_LEVELS);
8126             }
8127             return mWifiControllerActivity;
8128         }
8129 
getOrCreateBluetoothControllerActivityLocked()8130         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
8131             if (mBluetoothControllerActivity == null) {
8132                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8133                         NUM_BT_TX_LEVELS);
8134             }
8135             return mBluetoothControllerActivity;
8136         }
8137 
getOrCreateModemControllerActivityLocked()8138         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
8139             if (mModemControllerActivity == null) {
8140                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8141                         ModemActivityInfo.getNumTxPowerLevels());
8142             }
8143             return mModemControllerActivity;
8144         }
8145 
getOrCreateMeasuredEnergyStatsLocked()8146         private MeasuredEnergyStats getOrCreateMeasuredEnergyStatsLocked() {
8147             if (mUidMeasuredEnergyStats == null) {
8148                 mUidMeasuredEnergyStats =
8149                         MeasuredEnergyStats.createFromTemplate(mBsi.mGlobalMeasuredEnergyStats);
8150             }
8151             return mUidMeasuredEnergyStats;
8152         }
8153 
8154         /** Adds the given charge to the given standard power bucket for this uid. */
addChargeToStandardBucketLocked(long chargeDeltaUC, @StandardPowerBucket int powerBucket)8155         private void addChargeToStandardBucketLocked(long chargeDeltaUC,
8156                 @StandardPowerBucket int powerBucket) {
8157             getOrCreateMeasuredEnergyStatsLocked().updateStandardBucket(powerBucket, chargeDeltaUC);
8158         }
8159 
8160         /** Adds the given charge to the given custom power bucket for this uid. */
addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket)8161         private void addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket) {
8162             getOrCreateMeasuredEnergyStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC);
8163         }
8164 
8165         /**
8166          * Returns the battery consumption (in microcoulomb) of this uid for a standard power bucket
8167          * of interest.
8168          * @param bucket standard power bucket of interest
8169          * @return consumption (in microcolombs) used by this uid for this power bucket
8170          */
getMeasuredBatteryConsumptionUC(@tandardPowerBucket int bucket)8171         public long getMeasuredBatteryConsumptionUC(@StandardPowerBucket int bucket) {
8172             if (mBsi.mGlobalMeasuredEnergyStats == null
8173                     || !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) {
8174                 return POWER_DATA_UNAVAILABLE;
8175             }
8176             if (mUidMeasuredEnergyStats == null) {
8177                 return 0L; // It is supported, but was never filled, so it must be 0
8178             }
8179             return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket);
8180         }
8181 
8182         @Override
getCustomConsumerMeasuredBatteryConsumptionUC()8183         public long[] getCustomConsumerMeasuredBatteryConsumptionUC() {
8184             if (mBsi.mGlobalMeasuredEnergyStats == null) {
8185                 return null;
8186             }
8187             if (mUidMeasuredEnergyStats == null) {
8188                 // Custom buckets may exist. But all values for this uid are 0 so we report all 0s.
8189                 return new long[mBsi.mGlobalMeasuredEnergyStats.getNumberCustomPowerBuckets()];
8190             }
8191             return mUidMeasuredEnergyStats.getAccumulatedCustomBucketCharges();
8192         }
8193 
8194         @Override
getBluetoothMeasuredBatteryConsumptionUC()8195         public long getBluetoothMeasuredBatteryConsumptionUC() {
8196             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
8197         }
8198 
8199         @Override
getCpuMeasuredBatteryConsumptionUC()8200         public long getCpuMeasuredBatteryConsumptionUC() {
8201             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
8202         }
8203 
8204         @Override
getGnssMeasuredBatteryConsumptionUC()8205         public long getGnssMeasuredBatteryConsumptionUC() {
8206             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS);
8207         }
8208 
8209         @Override
getMobileRadioMeasuredBatteryConsumptionUC()8210         public long getMobileRadioMeasuredBatteryConsumptionUC() {
8211             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO);
8212         }
8213 
8214         @Override
getScreenOnMeasuredBatteryConsumptionUC()8215         public long getScreenOnMeasuredBatteryConsumptionUC() {
8216             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
8217         }
8218 
8219         @Override
getWifiMeasuredBatteryConsumptionUC()8220         public long getWifiMeasuredBatteryConsumptionUC() {
8221             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
8222         }
8223 
8224         /**
8225          * Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
8226          * since last marked. Also sets the mark time for both these timers.
8227          *
8228          * @see BatteryStatsHelper#getProcessForegroundTimeMs
8229          *
8230          * @param doCalc if true, then calculate the minimum; else don't bother and return 0. Either
8231          *               way, the mark is set.
8232          */
markProcessForegroundTimeUs(long elapsedRealtimeMs, boolean doCalc)8233         private long markProcessForegroundTimeUs(long elapsedRealtimeMs,
8234                 boolean doCalc) {
8235             long fgTimeUs = 0;
8236             final StopwatchTimer fgTimer = mForegroundActivityTimer;
8237             if (fgTimer != null) {
8238                 if (doCalc) fgTimeUs = fgTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8239                 fgTimer.setMark(elapsedRealtimeMs);
8240             }
8241 
8242             long topTimeUs = 0;
8243             final StopwatchTimer topTimer = mProcessStateTimer[PROCESS_STATE_TOP];
8244             if (topTimer != null) {
8245                 if (doCalc) topTimeUs = topTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8246                 topTimer.setMark(elapsedRealtimeMs);
8247             }
8248 
8249             // Return the min of the two
8250             return (topTimeUs < fgTimeUs) ? topTimeUs : fgTimeUs;
8251         }
8252 
8253 
8254         /**
8255          * Gets the uid's time spent using the GNSS since last marked. Also sets the mark time for
8256          * the GNSS timer.
8257          */
markGnssTimeUs(long elapsedRealtimeMs)8258         private long markGnssTimeUs(long elapsedRealtimeMs) {
8259             final Sensor sensor = mSensorStats.get(Sensor.GPS);
8260             if (sensor == null) {
8261                 return 0;
8262             }
8263 
8264             final StopwatchTimer timer = sensor.mTimer;
8265             if (timer == null) {
8266                 return 0;
8267             }
8268 
8269             final long gnssTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8270             timer.setMark(elapsedRealtimeMs);
8271             return gnssTimeUs;
8272         }
8273 
createAudioTurnedOnTimerLocked()8274         public StopwatchTimer createAudioTurnedOnTimerLocked() {
8275             if (mAudioTurnedOnTimer == null) {
8276                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
8277                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
8278             }
8279             return mAudioTurnedOnTimer;
8280         }
8281 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)8282         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
8283             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
8284         }
8285 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)8286         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
8287             if (mAudioTurnedOnTimer != null) {
8288                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
8289             }
8290         }
8291 
noteResetAudioLocked(long elapsedRealtimeMs)8292         public void noteResetAudioLocked(long elapsedRealtimeMs) {
8293             if (mAudioTurnedOnTimer != null) {
8294                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
8295             }
8296         }
8297 
createVideoTurnedOnTimerLocked()8298         public StopwatchTimer createVideoTurnedOnTimerLocked() {
8299             if (mVideoTurnedOnTimer == null) {
8300                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
8301                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
8302             }
8303             return mVideoTurnedOnTimer;
8304         }
8305 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)8306         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
8307             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
8308         }
8309 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)8310         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
8311             if (mVideoTurnedOnTimer != null) {
8312                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
8313             }
8314         }
8315 
noteResetVideoLocked(long elapsedRealtimeMs)8316         public void noteResetVideoLocked(long elapsedRealtimeMs) {
8317             if (mVideoTurnedOnTimer != null) {
8318                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
8319             }
8320         }
8321 
createFlashlightTurnedOnTimerLocked()8322         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
8323             if (mFlashlightTurnedOnTimer == null) {
8324                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8325                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
8326             }
8327             return mFlashlightTurnedOnTimer;
8328         }
8329 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)8330         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
8331             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
8332         }
8333 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)8334         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
8335             if (mFlashlightTurnedOnTimer != null) {
8336                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
8337             }
8338         }
8339 
noteResetFlashlightLocked(long elapsedRealtimeMs)8340         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
8341             if (mFlashlightTurnedOnTimer != null) {
8342                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
8343             }
8344         }
8345 
createCameraTurnedOnTimerLocked()8346         public StopwatchTimer createCameraTurnedOnTimerLocked() {
8347             if (mCameraTurnedOnTimer == null) {
8348                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
8349                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
8350             }
8351             return mCameraTurnedOnTimer;
8352         }
8353 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)8354         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
8355             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
8356         }
8357 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)8358         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
8359             if (mCameraTurnedOnTimer != null) {
8360                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
8361             }
8362         }
8363 
noteResetCameraLocked(long elapsedRealtimeMs)8364         public void noteResetCameraLocked(long elapsedRealtimeMs) {
8365             if (mCameraTurnedOnTimer != null) {
8366                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
8367             }
8368         }
8369 
createForegroundActivityTimerLocked()8370         public StopwatchTimer createForegroundActivityTimerLocked() {
8371             if (mForegroundActivityTimer == null) {
8372                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8373                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
8374             }
8375             return mForegroundActivityTimer;
8376         }
8377 
createForegroundServiceTimerLocked()8378         public StopwatchTimer createForegroundServiceTimerLocked() {
8379             if (mForegroundServiceTimer == null) {
8380                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8381                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
8382             }
8383             return mForegroundServiceTimer;
8384         }
8385 
createAggregatedPartialWakelockTimerLocked()8386         public DualTimer createAggregatedPartialWakelockTimerLocked() {
8387             if (mAggregatedPartialWakelockTimer == null) {
8388                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
8389                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
8390                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
8391             }
8392             return mAggregatedPartialWakelockTimer;
8393         }
8394 
createBluetoothScanTimerLocked()8395         public DualTimer createBluetoothScanTimerLocked() {
8396             if (mBluetoothScanTimer == null) {
8397                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
8398                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
8399                         mOnBatteryBackgroundTimeBase);
8400             }
8401             return mBluetoothScanTimer;
8402         }
8403 
createBluetoothUnoptimizedScanTimerLocked()8404         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
8405             if (mBluetoothUnoptimizedScanTimer == null) {
8406                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
8407                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
8408                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8409             }
8410             return mBluetoothUnoptimizedScanTimer;
8411         }
8412 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)8413         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
8414                 boolean isUnoptimized) {
8415             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
8416             if (isUnoptimized) {
8417                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
8418             }
8419         }
8420 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)8421         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
8422             if (mBluetoothScanTimer != null) {
8423                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
8424             }
8425             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
8426                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
8427             }
8428         }
8429 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)8430         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
8431             if (mBluetoothScanTimer != null) {
8432                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
8433             }
8434             if (mBluetoothUnoptimizedScanTimer != null) {
8435                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
8436             }
8437         }
8438 
createBluetoothScanResultCounterLocked()8439         public Counter createBluetoothScanResultCounterLocked() {
8440             if (mBluetoothScanResultCounter == null) {
8441                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
8442             }
8443             return mBluetoothScanResultCounter;
8444         }
8445 
createBluetoothScanResultBgCounterLocked()8446         public Counter createBluetoothScanResultBgCounterLocked() {
8447             if (mBluetoothScanResultBgCounter == null) {
8448                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
8449             }
8450             return mBluetoothScanResultBgCounter;
8451         }
8452 
noteBluetoothScanResultsLocked(int numNewResults)8453         public void noteBluetoothScanResultsLocked(int numNewResults) {
8454             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
8455             // Uses background timebase, so the count will only be incremented if uid in background.
8456             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
8457         }
8458 
8459         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)8460         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
8461             // We always start, since we want multiple foreground PIDs to nest
8462             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
8463         }
8464 
8465         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)8466         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
8467             if (mForegroundActivityTimer != null) {
8468                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
8469             }
8470         }
8471 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)8472         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
8473             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
8474         }
8475 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)8476         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
8477             if (mForegroundServiceTimer != null) {
8478                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
8479             }
8480         }
8481 
createVibratorOnTimerLocked()8482         public BatchTimer createVibratorOnTimerLocked() {
8483             if (mVibratorOnTimer == null) {
8484                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
8485                         mBsi.mOnBatteryTimeBase);
8486             }
8487             return mVibratorOnTimer;
8488         }
8489 
noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs)8490         public void noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs) {
8491             createVibratorOnTimerLocked().addDuration(mBsi, durationMillis, elapsedRealtimeMs);
8492         }
8493 
noteVibratorOffLocked(long elapsedRealtimeMs)8494         public void noteVibratorOffLocked(long elapsedRealtimeMs) {
8495             if (mVibratorOnTimer != null) {
8496                 mVibratorOnTimer.abortLastDuration(mBsi, elapsedRealtimeMs);
8497             }
8498         }
8499 
8500         @Override
8501         @UnsupportedAppUsage
getWifiRunningTime(long elapsedRealtimeUs, int which)8502         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
8503             if (mWifiRunningTimer == null) {
8504                 return 0;
8505             }
8506             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8507         }
8508 
8509         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)8510         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
8511             if (mFullWifiLockTimer == null) {
8512                 return 0;
8513             }
8514             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8515         }
8516 
8517         @Override
8518         @UnsupportedAppUsage
getWifiScanTime(long elapsedRealtimeUs, int which)8519         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
8520             if (mWifiScanTimer == null) {
8521                 return 0;
8522             }
8523             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8524         }
8525 
8526         @Override
getWifiScanCount(int which)8527         public int getWifiScanCount(int which) {
8528             if (mWifiScanTimer == null) {
8529                 return 0;
8530             }
8531             return mWifiScanTimer.getCountLocked(which);
8532         }
8533 
8534         @Override
getWifiScanTimer()8535         public Timer getWifiScanTimer() {
8536             return mWifiScanTimer;
8537         }
8538 
8539         @Override
getWifiScanBackgroundCount(int which)8540         public int getWifiScanBackgroundCount(int which) {
8541             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
8542                 return 0;
8543             }
8544             return mWifiScanTimer.getSubTimer().getCountLocked(which);
8545         }
8546 
8547         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)8548         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
8549             if (mWifiScanTimer == null) {
8550                 return 0;
8551             }
8552             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
8553             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
8554         }
8555 
8556         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)8557         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
8558             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
8559                 return 0;
8560             }
8561             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
8562             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
8563         }
8564 
8565         @Override
getWifiScanBackgroundTimer()8566         public Timer getWifiScanBackgroundTimer() {
8567             if (mWifiScanTimer == null) {
8568                 return null;
8569             }
8570             return mWifiScanTimer.getSubTimer();
8571         }
8572 
8573         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)8574         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
8575             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
8576             if (mWifiBatchedScanTimer[csphBin] == null) {
8577                 return 0;
8578             }
8579             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
8580         }
8581 
8582         @Override
getWifiBatchedScanCount(int csphBin, int which)8583         public int getWifiBatchedScanCount(int csphBin, int which) {
8584             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
8585             if (mWifiBatchedScanTimer[csphBin] == null) {
8586                 return 0;
8587             }
8588             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
8589         }
8590 
8591         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)8592         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
8593             if (mWifiMulticastTimer == null) {
8594                 return 0;
8595             }
8596             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8597         }
8598 
8599         @Override
getAudioTurnedOnTimer()8600         public Timer getAudioTurnedOnTimer() {
8601             return mAudioTurnedOnTimer;
8602         }
8603 
8604         @Override
getVideoTurnedOnTimer()8605         public Timer getVideoTurnedOnTimer() {
8606             return mVideoTurnedOnTimer;
8607         }
8608 
8609         @Override
getFlashlightTurnedOnTimer()8610         public Timer getFlashlightTurnedOnTimer() {
8611             return mFlashlightTurnedOnTimer;
8612         }
8613 
8614         @Override
getCameraTurnedOnTimer()8615         public Timer getCameraTurnedOnTimer() {
8616             return mCameraTurnedOnTimer;
8617         }
8618 
8619         @Override
getForegroundActivityTimer()8620         public Timer getForegroundActivityTimer() {
8621             return mForegroundActivityTimer;
8622         }
8623 
8624         @Override
getForegroundServiceTimer()8625         public Timer getForegroundServiceTimer() {
8626             return mForegroundServiceTimer;
8627         }
8628 
8629         @Override
getBluetoothScanTimer()8630         public Timer getBluetoothScanTimer() {
8631             return mBluetoothScanTimer;
8632         }
8633 
8634         @Override
getBluetoothScanBackgroundTimer()8635         public Timer getBluetoothScanBackgroundTimer() {
8636             if (mBluetoothScanTimer == null) {
8637                 return null;
8638             }
8639             return mBluetoothScanTimer.getSubTimer();
8640         }
8641 
8642         @Override
getBluetoothUnoptimizedScanTimer()8643         public Timer getBluetoothUnoptimizedScanTimer() {
8644             return mBluetoothUnoptimizedScanTimer;
8645         }
8646 
8647         @Override
getBluetoothUnoptimizedScanBackgroundTimer()8648         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
8649             if (mBluetoothUnoptimizedScanTimer == null) {
8650                 return null;
8651             }
8652             return mBluetoothUnoptimizedScanTimer.getSubTimer();
8653         }
8654 
8655         @Override
getBluetoothScanResultCounter()8656         public Counter getBluetoothScanResultCounter() {
8657             return mBluetoothScanResultCounter;
8658         }
8659 
8660         @Override
getBluetoothScanResultBgCounter()8661         public Counter getBluetoothScanResultBgCounter() {
8662             return mBluetoothScanResultBgCounter;
8663         }
8664 
makeProcessState(int i, Parcel in)8665         void makeProcessState(int i, Parcel in) {
8666             if (i < 0 || i >= NUM_PROCESS_STATE) return;
8667 
8668             detachIfNotNull(mProcessStateTimer[i]);
8669             if (in == null) {
8670                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
8671                         mBsi.mOnBatteryTimeBase);
8672             } else {
8673                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
8674                         mBsi.mOnBatteryTimeBase, in);
8675             }
8676         }
8677 
8678         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)8679         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
8680             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
8681             if (mProcessStateTimer[state] == null) {
8682                 return 0;
8683             }
8684             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
8685         }
8686 
8687         @Override
getProcessStateTimer(int state)8688         public Timer getProcessStateTimer(int state) {
8689             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
8690             return mProcessStateTimer[state];
8691         }
8692 
8693         @Override
getVibratorOnTimer()8694         public Timer getVibratorOnTimer() {
8695             return mVibratorOnTimer;
8696         }
8697 
8698         @Override
noteUserActivityLocked(int type)8699         public void noteUserActivityLocked(int type) {
8700             if (mUserActivityCounters == null) {
8701                 initUserActivityLocked();
8702             }
8703             if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
8704                 mUserActivityCounters[type].stepAtomic();
8705             } else {
8706                 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
8707                         new Throwable());
8708             }
8709         }
8710 
8711         @Override
hasUserActivity()8712         public boolean hasUserActivity() {
8713             return mUserActivityCounters != null;
8714         }
8715 
8716         @Override
getUserActivityCount(int type, int which)8717         public int getUserActivityCount(int type, int which) {
8718             if (mUserActivityCounters == null) {
8719                 return 0;
8720             }
8721             return mUserActivityCounters[type].getCountLocked(which);
8722         }
8723 
makeWifiBatchedScanBin(int i, Parcel in)8724         void makeWifiBatchedScanBin(int i, Parcel in) {
8725             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
8726 
8727             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
8728             if (collected == null) {
8729                 collected = new ArrayList<StopwatchTimer>();
8730                 mBsi.mWifiBatchedScanTimers.put(i, collected);
8731             }
8732             detachIfNotNull(mWifiBatchedScanTimer[i]);
8733             if (in == null) {
8734                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
8735                         collected, mBsi.mOnBatteryTimeBase);
8736             } else {
8737                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
8738                         collected, mBsi.mOnBatteryTimeBase, in);
8739             }
8740         }
8741 
8742 
initUserActivityLocked()8743         void initUserActivityLocked() {
8744             detachIfNotNull(mUserActivityCounters);
8745             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
8746             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8747                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
8748             }
8749         }
8750 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)8751         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
8752             if (mNetworkByteActivityCounters == null) {
8753                 initNetworkActivityLocked();
8754             }
8755             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
8756                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
8757                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
8758             } else {
8759                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
8760                         new Throwable());
8761             }
8762         }
8763 
noteMobileRadioActiveTimeLocked(long batteryUptime)8764         void noteMobileRadioActiveTimeLocked(long batteryUptime) {
8765             if (mNetworkByteActivityCounters == null) {
8766                 initNetworkActivityLocked();
8767             }
8768             mMobileRadioActiveTime.addCountLocked(batteryUptime);
8769             mMobileRadioActiveCount.addCountLocked(1);
8770         }
8771 
8772         @Override
hasNetworkActivity()8773         public boolean hasNetworkActivity() {
8774             return mNetworkByteActivityCounters != null;
8775         }
8776 
8777         @Override
getNetworkActivityBytes(int type, int which)8778         public long getNetworkActivityBytes(int type, int which) {
8779             if (mNetworkByteActivityCounters != null && type >= 0
8780                     && type < mNetworkByteActivityCounters.length) {
8781                 return mNetworkByteActivityCounters[type].getCountLocked(which);
8782             } else {
8783                 return 0;
8784             }
8785         }
8786 
8787         @Override
getNetworkActivityPackets(int type, int which)8788         public long getNetworkActivityPackets(int type, int which) {
8789             if (mNetworkPacketActivityCounters != null && type >= 0
8790                     && type < mNetworkPacketActivityCounters.length) {
8791                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
8792             } else {
8793                 return 0;
8794             }
8795         }
8796 
8797         @Override
getMobileRadioActiveTime(int which)8798         public long getMobileRadioActiveTime(int which) {
8799             return mMobileRadioActiveTime != null
8800                     ? mMobileRadioActiveTime.getCountLocked(which) : 0;
8801         }
8802 
8803         @Override
getMobileRadioActiveCount(int which)8804         public int getMobileRadioActiveCount(int which) {
8805             return mMobileRadioActiveCount != null
8806                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
8807         }
8808 
8809         @Override
getUserCpuTimeUs(int which)8810         public long getUserCpuTimeUs(int which) {
8811             return mUserCpuTime.getCountLocked(which);
8812         }
8813 
8814         @Override
getSystemCpuTimeUs(int which)8815         public long getSystemCpuTimeUs(int which) {
8816             return mSystemCpuTime.getCountLocked(which);
8817         }
8818 
8819         @Override
getTimeAtCpuSpeed(int cluster, int step, int which)8820         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
8821             if (mCpuClusterSpeedTimesUs != null) {
8822                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
8823                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
8824                     if (cpuSpeedTimesUs != null) {
8825                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
8826                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
8827                             if (c != null) {
8828                                 return c.getCountLocked(which);
8829                             }
8830                         }
8831                     }
8832                 }
8833             }
8834             return 0;
8835         }
8836 
noteMobileRadioApWakeupLocked()8837         public void noteMobileRadioApWakeupLocked() {
8838             if (mMobileRadioApWakeupCount == null) {
8839                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8840             }
8841             mMobileRadioApWakeupCount.addCountLocked(1);
8842         }
8843 
8844         @Override
getMobileRadioApWakeupCount(int which)8845         public long getMobileRadioApWakeupCount(int which) {
8846             if (mMobileRadioApWakeupCount != null) {
8847                 return mMobileRadioApWakeupCount.getCountLocked(which);
8848             }
8849             return 0;
8850         }
8851 
noteWifiRadioApWakeupLocked()8852         public void noteWifiRadioApWakeupLocked() {
8853             if (mWifiRadioApWakeupCount == null) {
8854                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8855             }
8856             mWifiRadioApWakeupCount.addCountLocked(1);
8857         }
8858 
8859         @Override
getWifiRadioApWakeupCount(int which)8860         public long getWifiRadioApWakeupCount(int which) {
8861             if (mWifiRadioApWakeupCount != null) {
8862                 return mWifiRadioApWakeupCount.getCountLocked(which);
8863             }
8864             return 0;
8865         }
8866 
8867         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)8868         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
8869             sb.setLength(0);
8870             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
8871             if (deferredEventCount == 0) {
8872                 return;
8873             }
8874             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
8875             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
8876             sb.append(deferredEventCount); sb.append(',');
8877             sb.append(deferredCount); sb.append(',');
8878             sb.append(totalLatency);
8879             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8880                 if (mJobsFreshnessBuckets[i] == null) {
8881                     sb.append(",0");
8882                 } else {
8883                     sb.append(",");
8884                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
8885                 }
8886             }
8887         }
8888 
8889         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)8890         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
8891             sb.setLength(0);
8892             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
8893             if (deferredEventCount == 0) {
8894                 return;
8895             }
8896             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
8897             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
8898             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
8899             sb.append("count="); sb.append(deferredCount); sb.append(", ");
8900             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
8901             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8902                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
8903                 if (mJobsFreshnessBuckets[i] == null) {
8904                     sb.append("0");
8905                 } else {
8906                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
8907                 }
8908                 sb.append(" ");
8909             }
8910         }
8911 
initNetworkActivityLocked()8912         void initNetworkActivityLocked() {
8913             detachIfNotNull(mNetworkByteActivityCounters);
8914             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8915             detachIfNotNull(mNetworkPacketActivityCounters);
8916             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8917             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8918                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8919                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8920             }
8921             detachIfNotNull(mMobileRadioActiveTime);
8922             mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8923             detachIfNotNull(mMobileRadioActiveCount);
8924             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8925         }
8926 
8927         /**
8928          * Clear all stats for this uid.  Returns true if the uid is completely
8929          * inactive so can be dropped.
8930          */
8931         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptimeUs, long realtimeUs, int resetReason)8932         public boolean reset(long uptimeUs, long realtimeUs, int resetReason) {
8933             boolean active = false;
8934 
8935             mOnBatteryBackgroundTimeBase.init(uptimeUs, realtimeUs);
8936             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeUs, realtimeUs);
8937 
8938             if (mWifiRunningTimer != null) {
8939                 active |= !mWifiRunningTimer.reset(false, realtimeUs);
8940                 active |= mWifiRunning;
8941             }
8942             if (mFullWifiLockTimer != null) {
8943                 active |= !mFullWifiLockTimer.reset(false, realtimeUs);
8944                 active |= mFullWifiLockOut;
8945             }
8946             if (mWifiScanTimer != null) {
8947                 active |= !mWifiScanTimer.reset(false, realtimeUs);
8948                 active |= mWifiScanStarted;
8949             }
8950             if (mWifiBatchedScanTimer != null) {
8951                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8952                     if (mWifiBatchedScanTimer[i] != null) {
8953                         active |= !mWifiBatchedScanTimer[i].reset(false, realtimeUs);
8954                     }
8955                 }
8956                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
8957             }
8958             if (mWifiMulticastTimer != null) {
8959                 active |= !mWifiMulticastTimer.reset(false, realtimeUs);
8960                 active |= (mWifiMulticastWakelockCount > 0);
8961             }
8962 
8963             active |= !resetIfNotNull(mAudioTurnedOnTimer, false, realtimeUs);
8964             active |= !resetIfNotNull(mVideoTurnedOnTimer, false, realtimeUs);
8965             active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false, realtimeUs);
8966             active |= !resetIfNotNull(mCameraTurnedOnTimer, false, realtimeUs);
8967             active |= !resetIfNotNull(mForegroundActivityTimer, false, realtimeUs);
8968             active |= !resetIfNotNull(mForegroundServiceTimer, false, realtimeUs);
8969             active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false, realtimeUs);
8970             active |= !resetIfNotNull(mBluetoothScanTimer, false, realtimeUs);
8971             active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false, realtimeUs);
8972 
8973             resetIfNotNull(mBluetoothScanResultCounter, false, realtimeUs);
8974             resetIfNotNull(mBluetoothScanResultBgCounter, false, realtimeUs);
8975 
8976             if (mProcessStateTimer != null) {
8977                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8978                     active |= !resetIfNotNull(mProcessStateTimer[i], false, realtimeUs);
8979                 }
8980                 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
8981             }
8982             if (mVibratorOnTimer != null) {
8983                 if (mVibratorOnTimer.reset(false, realtimeUs)) {
8984                     mVibratorOnTimer.detach();
8985                     mVibratorOnTimer = null;
8986                 } else {
8987                     active = true;
8988                 }
8989             }
8990 
8991             resetIfNotNull(mUserActivityCounters, false, realtimeUs);
8992 
8993             resetIfNotNull(mNetworkByteActivityCounters, false, realtimeUs);
8994             resetIfNotNull(mNetworkPacketActivityCounters, false, realtimeUs);
8995             resetIfNotNull(mMobileRadioActiveTime, false, realtimeUs);
8996             resetIfNotNull(mMobileRadioActiveCount, false, realtimeUs);
8997 
8998             resetIfNotNull(mWifiControllerActivity, false, realtimeUs);
8999             resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs);
9000             resetIfNotNull(mModemControllerActivity, false, realtimeUs);
9001 
9002             if (resetReason == RESET_REASON_MEASURED_ENERGY_BUCKETS_CHANGE) {
9003                 mUidMeasuredEnergyStats = null;
9004             } else {
9005                 MeasuredEnergyStats.resetIfNotNull(mUidMeasuredEnergyStats);
9006             }
9007 
9008             resetIfNotNull(mUserCpuTime, false, realtimeUs);
9009             resetIfNotNull(mSystemCpuTime, false, realtimeUs);
9010 
9011             resetIfNotNull(mCpuClusterSpeedTimesUs, false, realtimeUs);
9012 
9013             resetIfNotNull(mCpuFreqTimeMs, false, realtimeUs /* unused */);
9014             resetIfNotNull(mScreenOffCpuFreqTimeMs, false, realtimeUs /* unused */);
9015 
9016 
9017             resetIfNotNull(mCpuActiveTimeMs, false, realtimeUs /* unused */);
9018             resetIfNotNull(mCpuClusterTimesMs, false, realtimeUs /* unused */);
9019 
9020             resetIfNotNull(mProcStateTimeMs, false, realtimeUs /* unused */);
9021 
9022             resetIfNotNull(mProcStateScreenOffTimeMs, false, realtimeUs /* unused */);
9023 
9024             resetIfNotNull(mMobileRadioApWakeupCount, false, realtimeUs);
9025 
9026             resetIfNotNull(mWifiRadioApWakeupCount, false, realtimeUs);
9027 
9028 
9029             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9030             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
9031                 Wakelock wl = wakeStats.valueAt(iw);
9032                 if (wl.reset(realtimeUs)) {
9033                     wakeStats.removeAt(iw);
9034                 } else {
9035                     active = true;
9036                 }
9037             }
9038             final long realtimeMs = realtimeUs / 1000;
9039             mWakelockStats.cleanup(realtimeMs);
9040             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9041             for (int is=syncStats.size()-1; is>=0; is--) {
9042                 DualTimer timer = syncStats.valueAt(is);
9043                 if (timer.reset(false, realtimeUs)) {
9044                     syncStats.removeAt(is);
9045                     timer.detach();
9046                 } else {
9047                     active = true;
9048                 }
9049             }
9050             mSyncStats.cleanup(realtimeMs);
9051             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9052             for (int ij=jobStats.size()-1; ij>=0; ij--) {
9053                 DualTimer timer = jobStats.valueAt(ij);
9054                 if (timer.reset(false, realtimeUs)) {
9055                     jobStats.removeAt(ij);
9056                     timer.detach();
9057                 } else {
9058                     active = true;
9059                 }
9060             }
9061             mJobStats.cleanup(realtimeMs);
9062             mJobCompletions.clear();
9063 
9064             resetIfNotNull(mJobsDeferredEventCount, false, realtimeUs);
9065             resetIfNotNull(mJobsDeferredCount, false, realtimeUs);
9066             resetIfNotNull(mJobsFreshnessTimeMs, false, realtimeUs /* unused */);
9067             resetIfNotNull(mJobsFreshnessBuckets, false, realtimeUs);
9068 
9069             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
9070                 Sensor s = mSensorStats.valueAt(ise);
9071                 if (s.reset(realtimeUs)) {
9072                     mSensorStats.removeAt(ise);
9073                 } else {
9074                     active = true;
9075                 }
9076             }
9077 
9078             for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
9079                 Proc proc = mProcessStats.valueAt(ip);
9080                 proc.detach();
9081             }
9082             mProcessStats.clear();
9083 
9084             for (int i = mPids.size() - 1; i >= 0; i--) {
9085                 Pid pid = mPids.valueAt(i);
9086                 if (pid.mWakeNesting > 0) {
9087                     active = true;
9088                 } else {
9089                     mPids.removeAt(i);
9090                 }
9091             }
9092 
9093 
9094             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
9095                 Pkg p = mPackageStats.valueAt(i);
9096                 p.detach();
9097             }
9098             mPackageStats.clear();
9099 
9100             mBinderCallCount = 0;
9101             mBinderCallStats.clear();
9102 
9103             mProportionalSystemServiceUsage = 0;
9104 
9105             mLastStepUserTimeMs = mLastStepSystemTimeMs = 0;
9106             mCurStepUserTimeMs = mCurStepSystemTimeMs = 0;
9107 
9108 
9109             return !active;
9110         }
9111 
9112         /**
9113          * This method MUST be called whenever the Uid object is destructed, otherwise it is a
9114          * memory leak in {@link TimeBase#mObservers} list.
9115          * Typically the Uid object is destructed when it is removed from
9116          * {@link BatteryStatsImpl#mUidStats}
9117          */
detachFromTimeBase()9118         void detachFromTimeBase() {
9119             detachIfNotNull(mWifiRunningTimer);
9120             detachIfNotNull(mFullWifiLockTimer);
9121             detachIfNotNull(mWifiScanTimer);
9122             detachIfNotNull(mWifiBatchedScanTimer);
9123             detachIfNotNull(mWifiMulticastTimer);
9124             detachIfNotNull(mAudioTurnedOnTimer);
9125             detachIfNotNull(mVideoTurnedOnTimer);
9126             detachIfNotNull(mFlashlightTurnedOnTimer);
9127 
9128             detachIfNotNull(mCameraTurnedOnTimer);
9129             detachIfNotNull(mForegroundActivityTimer);
9130             detachIfNotNull(mForegroundServiceTimer);
9131 
9132             detachIfNotNull(mAggregatedPartialWakelockTimer);
9133 
9134             detachIfNotNull(mBluetoothScanTimer);
9135             detachIfNotNull(mBluetoothUnoptimizedScanTimer);
9136             detachIfNotNull(mBluetoothScanResultCounter);
9137             detachIfNotNull(mBluetoothScanResultBgCounter);
9138 
9139             detachIfNotNull(mProcessStateTimer);
9140 
9141             detachIfNotNull(mVibratorOnTimer);
9142 
9143             detachIfNotNull(mUserActivityCounters);
9144 
9145             detachIfNotNull(mNetworkByteActivityCounters);
9146             detachIfNotNull(mNetworkPacketActivityCounters);
9147 
9148             detachIfNotNull(mMobileRadioActiveTime);
9149             detachIfNotNull(mMobileRadioActiveCount);
9150             detachIfNotNull(mMobileRadioApWakeupCount);
9151             detachIfNotNull(mWifiRadioApWakeupCount);
9152 
9153             detachIfNotNull(mWifiControllerActivity);
9154             detachIfNotNull(mBluetoothControllerActivity);
9155             detachIfNotNull(mModemControllerActivity);
9156 
9157             mPids.clear();
9158 
9159             detachIfNotNull(mUserCpuTime);
9160             detachIfNotNull(mSystemCpuTime);
9161 
9162             detachIfNotNull(mCpuClusterSpeedTimesUs);
9163 
9164             detachIfNotNull(mCpuActiveTimeMs);
9165             detachIfNotNull(mCpuFreqTimeMs);
9166 
9167             detachIfNotNull(mScreenOffCpuFreqTimeMs);
9168 
9169             detachIfNotNull(mCpuClusterTimesMs);
9170 
9171             detachIfNotNull(mProcStateTimeMs);
9172 
9173             detachIfNotNull(mProcStateScreenOffTimeMs);
9174 
9175             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9176             for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
9177                 Wakelock wl = wakeStats.valueAt(iw);
9178                 wl.detachFromTimeBase();
9179             }
9180             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9181             for (int is = syncStats.size() - 1; is >= 0; is--) {
9182                 DualTimer timer = syncStats.valueAt(is);
9183                 detachIfNotNull(timer);
9184             }
9185             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9186             for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
9187                 DualTimer timer = jobStats.valueAt(ij);
9188                 detachIfNotNull(timer);
9189             }
9190 
9191             detachIfNotNull(mJobsDeferredEventCount);
9192             detachIfNotNull(mJobsDeferredCount);
9193             detachIfNotNull(mJobsFreshnessTimeMs);
9194             detachIfNotNull(mJobsFreshnessBuckets);
9195 
9196 
9197             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
9198                 Sensor s = mSensorStats.valueAt(ise);
9199                 s.detachFromTimeBase();
9200             }
9201 
9202             for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
9203                 Proc proc = mProcessStats.valueAt(ip);
9204                 proc.detach();
9205             }
9206             mProcessStats.clear();
9207 
9208             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
9209                 Pkg p = mPackageStats.valueAt(i);
9210                 p.detach();
9211             }
9212             mPackageStats.clear();
9213         }
9214 
writeJobCompletionsToParcelLocked(Parcel out)9215         void writeJobCompletionsToParcelLocked(Parcel out) {
9216             int NJC = mJobCompletions.size();
9217             out.writeInt(NJC);
9218             for (int ijc=0; ijc<NJC; ijc++) {
9219                 out.writeString(mJobCompletions.keyAt(ijc));
9220                 SparseIntArray types = mJobCompletions.valueAt(ijc);
9221                 int NT = types.size();
9222                 out.writeInt(NT);
9223                 for (int it=0; it<NT; it++) {
9224                     out.writeInt(types.keyAt(it));
9225                     out.writeInt(types.valueAt(it));
9226                 }
9227             }
9228         }
9229 
writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs)9230         void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
9231             mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
9232             mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
9233 
9234             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9235             int NW = wakeStats.size();
9236             out.writeInt(NW);
9237             for (int iw=0; iw<NW; iw++) {
9238                 out.writeString(wakeStats.keyAt(iw));
9239                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
9240                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
9241             }
9242 
9243             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9244             int NS = syncStats.size();
9245             out.writeInt(NS);
9246             for (int is=0; is<NS; is++) {
9247                 out.writeString(syncStats.keyAt(is));
9248                 DualTimer timer = syncStats.valueAt(is);
9249                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
9250             }
9251 
9252             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9253             int NJ = jobStats.size();
9254             out.writeInt(NJ);
9255             for (int ij=0; ij<NJ; ij++) {
9256                 out.writeString(jobStats.keyAt(ij));
9257                 DualTimer timer = jobStats.valueAt(ij);
9258                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
9259             }
9260 
9261             writeJobCompletionsToParcelLocked(out);
9262 
9263             mJobsDeferredEventCount.writeToParcel(out);
9264             mJobsDeferredCount.writeToParcel(out);
9265             mJobsFreshnessTimeMs.writeToParcel(out);
9266             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9267                 Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
9268             }
9269 
9270             int NSE = mSensorStats.size();
9271             out.writeInt(NSE);
9272             for (int ise=0; ise<NSE; ise++) {
9273                 out.writeInt(mSensorStats.keyAt(ise));
9274                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
9275                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
9276             }
9277 
9278             int NP = mProcessStats.size();
9279             out.writeInt(NP);
9280             for (int ip=0; ip<NP; ip++) {
9281                 out.writeString(mProcessStats.keyAt(ip));
9282                 Uid.Proc proc = mProcessStats.valueAt(ip);
9283                 proc.writeToParcelLocked(out);
9284             }
9285 
9286             out.writeInt(mPackageStats.size());
9287             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
9288                 out.writeString(pkgEntry.getKey());
9289                 Uid.Pkg pkg = pkgEntry.getValue();
9290                 pkg.writeToParcelLocked(out);
9291             }
9292 
9293             if (mWifiRunningTimer != null) {
9294                 out.writeInt(1);
9295                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
9296             } else {
9297                 out.writeInt(0);
9298             }
9299             if (mFullWifiLockTimer != null) {
9300                 out.writeInt(1);
9301                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
9302             } else {
9303                 out.writeInt(0);
9304             }
9305             if (mWifiScanTimer != null) {
9306                 out.writeInt(1);
9307                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
9308             } else {
9309                 out.writeInt(0);
9310             }
9311             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9312                 if (mWifiBatchedScanTimer[i] != null) {
9313                     out.writeInt(1);
9314                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
9315                 } else {
9316                     out.writeInt(0);
9317                 }
9318             }
9319             if (mWifiMulticastTimer != null) {
9320                 out.writeInt(1);
9321                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
9322             } else {
9323                 out.writeInt(0);
9324             }
9325 
9326             if (mAudioTurnedOnTimer != null) {
9327                 out.writeInt(1);
9328                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
9329             } else {
9330                 out.writeInt(0);
9331             }
9332             if (mVideoTurnedOnTimer != null) {
9333                 out.writeInt(1);
9334                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
9335             } else {
9336                 out.writeInt(0);
9337             }
9338             if (mFlashlightTurnedOnTimer != null) {
9339                 out.writeInt(1);
9340                 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
9341             } else {
9342                 out.writeInt(0);
9343             }
9344             if (mCameraTurnedOnTimer != null) {
9345                 out.writeInt(1);
9346                 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
9347             } else {
9348                 out.writeInt(0);
9349             }
9350             if (mForegroundActivityTimer != null) {
9351                 out.writeInt(1);
9352                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
9353             } else {
9354                 out.writeInt(0);
9355             }
9356             if (mForegroundServiceTimer != null) {
9357                 out.writeInt(1);
9358                 mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
9359             } else {
9360                 out.writeInt(0);
9361             }
9362             if (mAggregatedPartialWakelockTimer != null) {
9363                 out.writeInt(1);
9364                 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
9365             } else {
9366                 out.writeInt(0);
9367             }
9368             if (mBluetoothScanTimer != null) {
9369                 out.writeInt(1);
9370                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
9371             } else {
9372                 out.writeInt(0);
9373             }
9374             if (mBluetoothUnoptimizedScanTimer != null) {
9375                 out.writeInt(1);
9376                 mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
9377             } else {
9378                 out.writeInt(0);
9379             }
9380             if (mBluetoothScanResultCounter != null) {
9381                 out.writeInt(1);
9382                 mBluetoothScanResultCounter.writeToParcel(out);
9383             } else {
9384                 out.writeInt(0);
9385             }
9386             if (mBluetoothScanResultBgCounter != null) {
9387                 out.writeInt(1);
9388                 mBluetoothScanResultBgCounter.writeToParcel(out);
9389             } else {
9390                 out.writeInt(0);
9391             }
9392             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
9393                 if (mProcessStateTimer[i] != null) {
9394                     out.writeInt(1);
9395                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
9396                 } else {
9397                     out.writeInt(0);
9398                 }
9399             }
9400             if (mVibratorOnTimer != null) {
9401                 out.writeInt(1);
9402                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
9403             } else {
9404                 out.writeInt(0);
9405             }
9406             if (mUserActivityCounters != null) {
9407                 out.writeInt(1);
9408                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
9409                     mUserActivityCounters[i].writeToParcel(out);
9410                 }
9411             } else {
9412                 out.writeInt(0);
9413             }
9414             if (mNetworkByteActivityCounters != null) {
9415                 out.writeInt(1);
9416                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9417                     mNetworkByteActivityCounters[i].writeToParcel(out);
9418                     mNetworkPacketActivityCounters[i].writeToParcel(out);
9419                 }
9420                 mMobileRadioActiveTime.writeToParcel(out);
9421                 mMobileRadioActiveCount.writeToParcel(out);
9422             } else {
9423                 out.writeInt(0);
9424             }
9425 
9426             if (mWifiControllerActivity != null) {
9427                 out.writeInt(1);
9428                 mWifiControllerActivity.writeToParcel(out, 0);
9429             } else {
9430                 out.writeInt(0);
9431             }
9432 
9433             if (mBluetoothControllerActivity != null) {
9434                 out.writeInt(1);
9435                 mBluetoothControllerActivity.writeToParcel(out, 0);
9436             } else {
9437                 out.writeInt(0);
9438             }
9439 
9440             if (mModemControllerActivity != null) {
9441                 out.writeInt(1);
9442                 mModemControllerActivity.writeToParcel(out, 0);
9443             } else {
9444                 out.writeInt(0);
9445             }
9446 
9447             if (mUidMeasuredEnergyStats != null) {
9448                 out.writeInt(1);
9449                 mUidMeasuredEnergyStats.writeToParcel(out);
9450             } else {
9451                 out.writeInt(0);
9452             }
9453 
9454             mUserCpuTime.writeToParcel(out);
9455             mSystemCpuTime.writeToParcel(out);
9456 
9457             mBsi.writeCpuSpeedCountersToParcel(out, mCpuClusterSpeedTimesUs);
9458 
9459             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
9460             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
9461 
9462             mCpuActiveTimeMs.writeToParcel(out);
9463             mCpuClusterTimesMs.writeToParcel(out);
9464 
9465             if (mProcStateTimeMs != null) {
9466                 out.writeInt(mProcStateTimeMs.length);
9467                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
9468                     LongSamplingCounterArray.writeToParcel(out, counters);
9469                 }
9470             } else {
9471                 out.writeInt(0);
9472             }
9473             if (mProcStateScreenOffTimeMs != null) {
9474                 out.writeInt(mProcStateScreenOffTimeMs.length);
9475                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
9476                     LongSamplingCounterArray.writeToParcel(out, counters);
9477                 }
9478             } else {
9479                 out.writeInt(0);
9480             }
9481 
9482             if (mMobileRadioApWakeupCount != null) {
9483                 out.writeInt(1);
9484                 mMobileRadioApWakeupCount.writeToParcel(out);
9485             } else {
9486                 out.writeInt(0);
9487             }
9488 
9489             if (mWifiRadioApWakeupCount != null) {
9490                 out.writeInt(1);
9491                 mWifiRadioApWakeupCount.writeToParcel(out);
9492             } else {
9493                 out.writeInt(0);
9494             }
9495             out.writeDouble(mProportionalSystemServiceUsage);
9496         }
9497 
readJobCompletionsFromParcelLocked(Parcel in)9498         void readJobCompletionsFromParcelLocked(Parcel in) {
9499             int numJobCompletions = in.readInt();
9500             mJobCompletions.clear();
9501             for (int j = 0; j < numJobCompletions; j++) {
9502                 String jobName = in.readString();
9503                 int numTypes = in.readInt();
9504                 if (numTypes > 0) {
9505                     SparseIntArray types = new SparseIntArray();
9506                     for (int k = 0; k < numTypes; k++) {
9507                         int type = in.readInt();
9508                         int count = in.readInt();
9509                         types.put(type, count);
9510                     }
9511                     mJobCompletions.put(jobName, types);
9512                 }
9513             }
9514         }
9515 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in)9516         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
9517             mOnBatteryBackgroundTimeBase.readFromParcel(in);
9518             mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
9519 
9520             int numWakelocks = in.readInt();
9521             mWakelockStats.clear();
9522             for (int j = 0; j < numWakelocks; j++) {
9523                 String wakelockName = in.readString();
9524                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
9525                 wakelock.readFromParcelLocked(
9526                         timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
9527                 mWakelockStats.add(wakelockName, wakelock);
9528             }
9529 
9530             int numSyncs = in.readInt();
9531             mSyncStats.clear();
9532             for (int j = 0; j < numSyncs; j++) {
9533                 String syncName = in.readString();
9534                 if (in.readInt() != 0) {
9535                     mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
9536                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
9537                 }
9538             }
9539 
9540             int numJobs = in.readInt();
9541             mJobStats.clear();
9542             for (int j = 0; j < numJobs; j++) {
9543                 String jobName = in.readString();
9544                 if (in.readInt() != 0) {
9545                     mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
9546                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
9547                 }
9548             }
9549 
9550             readJobCompletionsFromParcelLocked(in);
9551 
9552             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
9553             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
9554             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9555             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9556                 mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
9557                         in);
9558             }
9559 
9560             int numSensors = in.readInt();
9561             mSensorStats.clear();
9562             for (int k = 0; k < numSensors; k++) {
9563                 int sensorNumber = in.readInt();
9564                 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
9565                 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
9566                         in);
9567                 mSensorStats.put(sensorNumber, sensor);
9568             }
9569 
9570             int numProcs = in.readInt();
9571             mProcessStats.clear();
9572             for (int k = 0; k < numProcs; k++) {
9573                 String processName = in.readString();
9574                 Uid.Proc proc = new Proc(mBsi, processName);
9575                 proc.readFromParcelLocked(in);
9576                 mProcessStats.put(processName, proc);
9577             }
9578 
9579             int numPkgs = in.readInt();
9580             mPackageStats.clear();
9581             for (int l = 0; l < numPkgs; l++) {
9582                 String packageName = in.readString();
9583                 Uid.Pkg pkg = new Pkg(mBsi);
9584                 pkg.readFromParcelLocked(in);
9585                 mPackageStats.put(packageName, pkg);
9586             }
9587 
9588             mWifiRunning = false;
9589             if (in.readInt() != 0) {
9590                 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
9591                         mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
9592             } else {
9593                 mWifiRunningTimer = null;
9594             }
9595             mFullWifiLockOut = false;
9596             if (in.readInt() != 0) {
9597                 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
9598                         mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
9599             } else {
9600                 mFullWifiLockTimer = null;
9601             }
9602             mWifiScanStarted = false;
9603             if (in.readInt() != 0) {
9604                 mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
9605                         mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
9606                         in);
9607             } else {
9608                 mWifiScanTimer = null;
9609             }
9610             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
9611             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9612                 if (in.readInt() != 0) {
9613                     makeWifiBatchedScanBin(i, in);
9614                 } else {
9615                     mWifiBatchedScanTimer[i] = null;
9616                 }
9617             }
9618             mWifiMulticastWakelockCount = 0;
9619             if (in.readInt() != 0) {
9620                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
9621                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
9622             } else {
9623                 mWifiMulticastTimer = null;
9624             }
9625             if (in.readInt() != 0) {
9626                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
9627                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
9628             } else {
9629                 mAudioTurnedOnTimer = null;
9630             }
9631             if (in.readInt() != 0) {
9632                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
9633                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
9634             } else {
9635                 mVideoTurnedOnTimer = null;
9636             }
9637             if (in.readInt() != 0) {
9638                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
9639                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
9640             } else {
9641                 mFlashlightTurnedOnTimer = null;
9642             }
9643             if (in.readInt() != 0) {
9644                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
9645                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
9646             } else {
9647                 mCameraTurnedOnTimer = null;
9648             }
9649             if (in.readInt() != 0) {
9650                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
9651                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
9652             } else {
9653                 mForegroundActivityTimer = null;
9654             }
9655             if (in.readInt() != 0) {
9656                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
9657                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
9658             } else {
9659                 mForegroundServiceTimer = null;
9660             }
9661             if (in.readInt() != 0) {
9662                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
9663                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
9664                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
9665                         in);
9666             } else {
9667                 mAggregatedPartialWakelockTimer = null;
9668             }
9669             if (in.readInt() != 0) {
9670                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
9671                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
9672                         mOnBatteryBackgroundTimeBase, in);
9673             } else {
9674                 mBluetoothScanTimer = null;
9675             }
9676             if (in.readInt() != 0) {
9677                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
9678                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
9679                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
9680             } else {
9681                 mBluetoothUnoptimizedScanTimer = null;
9682             }
9683             if (in.readInt() != 0) {
9684                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
9685             } else {
9686                 mBluetoothScanResultCounter = null;
9687             }
9688             if (in.readInt() != 0) {
9689                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
9690             } else {
9691                 mBluetoothScanResultBgCounter = null;
9692             }
9693             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
9694             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
9695                 if (in.readInt() != 0) {
9696                     makeProcessState(i, in);
9697                 } else {
9698                     mProcessStateTimer[i] = null;
9699                 }
9700             }
9701             if (in.readInt() != 0) {
9702                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
9703                         mBsi.mOnBatteryTimeBase, in);
9704             } else {
9705                 mVibratorOnTimer = null;
9706             }
9707             if (in.readInt() != 0) {
9708                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
9709                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
9710                     mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
9711                 }
9712             } else {
9713                 mUserActivityCounters = null;
9714             }
9715             if (in.readInt() != 0) {
9716                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9717                 mNetworkPacketActivityCounters
9718                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9719                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9720                     mNetworkByteActivityCounters[i]
9721                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9722                     mNetworkPacketActivityCounters[i]
9723                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9724                 }
9725                 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9726                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9727             } else {
9728                 mNetworkByteActivityCounters = null;
9729                 mNetworkPacketActivityCounters = null;
9730             }
9731 
9732             if (in.readInt() != 0) {
9733                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
9734                         NUM_WIFI_TX_LEVELS, in);
9735             } else {
9736                 mWifiControllerActivity = null;
9737             }
9738 
9739             if (in.readInt() != 0) {
9740                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
9741                         NUM_BT_TX_LEVELS, in);
9742             } else {
9743                 mBluetoothControllerActivity = null;
9744             }
9745 
9746             if (in.readInt() != 0) {
9747                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
9748                         ModemActivityInfo.getNumTxPowerLevels(), in);
9749             } else {
9750                 mModemControllerActivity = null;
9751             }
9752 
9753             if (in.readInt() != 0) {
9754                 mUidMeasuredEnergyStats = new MeasuredEnergyStats(in);
9755             }
9756 
9757             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9758             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9759 
9760             mCpuClusterSpeedTimesUs = mBsi.readCpuSpeedCountersFromParcel(in);
9761 
9762             mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
9763             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
9764                     in, mBsi.mOnBatteryScreenOffTimeBase);
9765 
9766             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9767             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
9768 
9769             int length = in.readInt();
9770             if (length == NUM_PROCESS_STATE) {
9771                 mProcStateTimeMs = new LongSamplingCounterArray[length];
9772                 for (int procState = 0; procState < length; ++procState) {
9773                     mProcStateTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
9774                             in, mBsi.mOnBatteryTimeBase);
9775                 }
9776             } else {
9777                 mProcStateTimeMs = null;
9778             }
9779             length = in.readInt();
9780             if (length == NUM_PROCESS_STATE) {
9781                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
9782                 for (int procState = 0; procState < length; ++procState) {
9783                     mProcStateScreenOffTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
9784                             in, mBsi.mOnBatteryScreenOffTimeBase);
9785                 }
9786             } else {
9787                 mProcStateScreenOffTimeMs = null;
9788             }
9789 
9790             if (in.readInt() != 0) {
9791                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9792             } else {
9793                 mMobileRadioApWakeupCount = null;
9794             }
9795 
9796             if (in.readInt() != 0) {
9797                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9798             } else {
9799                 mWifiRadioApWakeupCount = null;
9800             }
9801 
9802             mProportionalSystemServiceUsage = in.readDouble();
9803         }
9804 
noteJobsDeferredLocked(int numDeferred, long sinceLast)9805         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
9806             mJobsDeferredEventCount.addAtomic(1);
9807             mJobsDeferredCount.addAtomic(numDeferred);
9808             if (sinceLast != 0) {
9809                 // Add the total time, which can be divided by the event count to get an average
9810                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
9811                 // Also keep track of how many times there were in these different buckets.
9812                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9813                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
9814                         if (mJobsFreshnessBuckets[i] == null) {
9815                             mJobsFreshnessBuckets[i] = new Counter(
9816                                     mBsi.mOnBatteryTimeBase);
9817                         }
9818                         mJobsFreshnessBuckets[i].addAtomic(1);
9819                         break;
9820                     }
9821                 }
9822             }
9823         }
9824 
9825         // Reusable object used as a key to lookup values in mBinderCallStats
9826         private static BinderCallStats sTempBinderCallStats = new BinderCallStats();
9827 
9828         /**
9829          * Notes incoming binder call stats associated with this work source UID.
9830          */
noteBinderCallStatsLocked(long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)9831         public void noteBinderCallStatsLocked(long incrementalCallCount,
9832                 Collection<BinderCallsStats.CallStat> callStats) {
9833             if (DEBUG) {
9834                 Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], "
9835                         + " incrementalCallCount: " + incrementalCallCount + " callStats = ["
9836                         + new ArrayList<>(callStats) + "]");
9837             }
9838             mBinderCallCount += incrementalCallCount;
9839             for (BinderCallsStats.CallStat stat : callStats) {
9840                 BinderCallStats bcs;
9841                 sTempBinderCallStats.binderClass = stat.binderClass;
9842                 sTempBinderCallStats.transactionCode = stat.transactionCode;
9843                 int index = mBinderCallStats.indexOf(sTempBinderCallStats);
9844                 if (index >= 0) {
9845                     bcs = mBinderCallStats.valueAt(index);
9846                 } else {
9847                     bcs = new BinderCallStats();
9848                     bcs.binderClass = stat.binderClass;
9849                     bcs.transactionCode = stat.transactionCode;
9850                     mBinderCallStats.add(bcs);
9851                 }
9852 
9853                 bcs.callCount += stat.incrementalCallCount;
9854                 bcs.recordedCallCount = stat.recordedCallCount;
9855                 bcs.recordedCpuTimeMicros = stat.cpuTimeMicros;
9856             }
9857         }
9858 
9859         /**
9860          * The statistics associated with a particular wake lock.
9861          */
9862         public static class Wakelock extends BatteryStats.Uid.Wakelock {
9863             /**
9864              * BatteryStatsImpl that we are associated with.
9865              */
9866             protected BatteryStatsImpl mBsi;
9867 
9868             /**
9869              * BatteryStatsImpl that we are associated with.
9870              */
9871             protected Uid mUid;
9872 
9873             /**
9874              * How long (in ms) this uid has been keeping the device partially awake.
9875              * Tracks both the total time and the time while the app was in the background.
9876              */
9877             DualTimer mTimerPartial;
9878 
9879             /**
9880              * How long (in ms) this uid has been keeping the device fully awake.
9881              */
9882             StopwatchTimer mTimerFull;
9883 
9884             /**
9885              * How long (in ms) this uid has had a window keeping the device awake.
9886              */
9887             StopwatchTimer mTimerWindow;
9888 
9889             /**
9890              * How long (in ms) this uid has had a draw wake lock.
9891              */
9892             StopwatchTimer mTimerDraw;
9893 
Wakelock(BatteryStatsImpl bsi, Uid uid)9894             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
9895                 mBsi = bsi;
9896                 mUid = uid;
9897             }
9898 
9899             /**
9900              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
9901              * proper timer pool from the given BatteryStatsImpl object.
9902              *
9903              * @param in the Parcel to be read from.
9904              * return a new Timer, or null.
9905              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)9906             private StopwatchTimer readStopwatchTimerFromParcel(int type,
9907                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
9908                 if (in.readInt() == 0) {
9909                     return null;
9910                 }
9911 
9912                 return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
9913             }
9914 
9915             /**
9916              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
9917              * proper timer pool from the given BatteryStatsImpl object.
9918              *
9919              * @param in the Parcel to be read from.
9920              * return a new Timer, or null.
9921              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)9922             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
9923                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9924                 if (in.readInt() == 0) {
9925                     return null;
9926                 }
9927 
9928                 return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
9929             }
9930 
reset(long elapsedRealtimeUs)9931             boolean reset(long elapsedRealtimeUs) {
9932                 boolean wlactive = false;
9933 
9934                 wlactive |= !resetIfNotNull(mTimerFull, false, elapsedRealtimeUs);
9935                 wlactive |= !resetIfNotNull(mTimerPartial, false, elapsedRealtimeUs);
9936                 wlactive |= !resetIfNotNull(mTimerWindow, false, elapsedRealtimeUs);
9937                 wlactive |= !resetIfNotNull(mTimerDraw, false, elapsedRealtimeUs);
9938 
9939                 if (!wlactive) {
9940                     detachIfNotNull(mTimerFull);
9941                     mTimerFull = null;
9942 
9943                     detachIfNotNull(mTimerPartial);
9944                     mTimerPartial = null;
9945 
9946                     detachIfNotNull(mTimerWindow);
9947                     mTimerWindow = null;
9948 
9949                     detachIfNotNull(mTimerDraw);
9950                     mTimerDraw = null;
9951                 }
9952                 return !wlactive;
9953             }
9954 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)9955             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
9956                     TimeBase screenOffBgTimeBase, Parcel in) {
9957                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
9958                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
9959                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
9960                         mBsi.mFullTimers, timeBase, in);
9961                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
9962                         mBsi.mWindowTimers, timeBase, in);
9963                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
9964                         mBsi.mDrawTimers, timeBase, in);
9965             }
9966 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)9967             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
9968                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
9969                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
9970                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
9971                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
9972             }
9973 
9974             @Override
9975             @UnsupportedAppUsage
getWakeTime(int type)9976             public Timer getWakeTime(int type) {
9977                 switch (type) {
9978                 case WAKE_TYPE_FULL: return mTimerFull;
9979                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
9980                 case WAKE_TYPE_WINDOW: return mTimerWindow;
9981                 case WAKE_TYPE_DRAW: return mTimerDraw;
9982                 default: throw new IllegalArgumentException("type = " + type);
9983                 }
9984             }
9985 
detachFromTimeBase()9986             public void detachFromTimeBase() {
9987                 detachIfNotNull(mTimerPartial);
9988                 detachIfNotNull(mTimerFull);
9989                 detachIfNotNull(mTimerWindow);
9990                 detachIfNotNull(mTimerDraw);
9991             }
9992         }
9993 
9994         public static class Sensor extends BatteryStats.Uid.Sensor {
9995             /**
9996              * BatteryStatsImpl that we are associated with.
9997              */
9998             protected BatteryStatsImpl mBsi;
9999 
10000             /**
10001              * Uid that we are associated with.
10002              */
10003             protected Uid mUid;
10004 
10005             final int mHandle;
10006             DualTimer mTimer;
10007 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)10008             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
10009                 mBsi = bsi;
10010                 mUid = uid;
10011                 mHandle = handle;
10012             }
10013 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10014             private DualTimer readTimersFromParcel(
10015                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10016                 if (in.readInt() == 0) {
10017                     return null;
10018                 }
10019 
10020                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
10021                 if (pool == null) {
10022                     pool = new ArrayList<StopwatchTimer>();
10023                     mBsi.mSensorTimers.put(mHandle, pool);
10024                 }
10025                 return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
10026             }
10027 
reset(long elapsedRealtimeUs)10028             boolean reset(long elapsedRealtimeUs) {
10029                 if (mTimer.reset(true, elapsedRealtimeUs)) {
10030                     mTimer = null;
10031                     return true;
10032                 }
10033                 return false;
10034             }
10035 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10036             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10037                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
10038             }
10039 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)10040             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
10041                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
10042             }
10043 
10044             @Override
10045             @UnsupportedAppUsage
getSensorTime()10046             public Timer getSensorTime() {
10047                 return mTimer;
10048             }
10049 
10050             @Override
getSensorBackgroundTime()10051             public Timer getSensorBackgroundTime() {
10052                 if (mTimer == null) {
10053                     return null;
10054                 }
10055                 return mTimer.getSubTimer();
10056             }
10057 
10058             @Override
10059             @UnsupportedAppUsage
getHandle()10060             public int getHandle() {
10061                 return mHandle;
10062             }
10063 
detachFromTimeBase()10064             public void  detachFromTimeBase() {
10065                 detachIfNotNull(mTimer);
10066             }
10067         }
10068 
10069         /**
10070          * The statistics associated with a particular process.
10071          */
10072         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
10073             /**
10074              * BatteryStatsImpl that we are associated with.
10075              */
10076             protected BatteryStatsImpl mBsi;
10077 
10078             /**
10079              * The name of this process.
10080              */
10081             final String mName;
10082 
10083             /**
10084              * Remains true until removed from the stats.
10085              */
10086             boolean mActive = true;
10087 
10088             /**
10089              * Total time (in ms) spent executing in user code.
10090              */
10091             long mUserTimeMs;
10092 
10093             /**
10094              * Total time (in ms) spent executing in kernel code.
10095              */
10096             long mSystemTimeMs;
10097 
10098             /**
10099              * Amount of time (in ms) the process was running in the foreground.
10100              */
10101             long mForegroundTimeMs;
10102 
10103             /**
10104              * Number of times the process has been started.
10105              */
10106             int mStarts;
10107 
10108             /**
10109              * Number of times the process has crashed.
10110              */
10111             int mNumCrashes;
10112 
10113             /**
10114              * Number of times the process has had an ANR.
10115              */
10116             int mNumAnrs;
10117 
10118             ArrayList<ExcessivePower> mExcessivePower;
10119 
Proc(BatteryStatsImpl bsi, String name)10120             public Proc(BatteryStatsImpl bsi, String name) {
10121                 mBsi = bsi;
10122                 mName = name;
10123                 mBsi.mOnBatteryTimeBase.add(this);
10124             }
10125 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10126             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10127                     long baseRealtimeUs) {
10128             }
10129 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10130             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10131                     long baseRealtimeUs) {
10132             }
10133 
10134             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10135             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10136                 if (detachIfReset) {
10137                     this.detach();
10138                 }
10139                 return true;
10140             }
10141 
10142             @Override
detach()10143             public void detach() {
10144                 mActive = false;
10145                 mBsi.mOnBatteryTimeBase.remove(this);
10146             }
10147 
countExcessivePowers()10148             public int countExcessivePowers() {
10149                 return mExcessivePower != null ? mExcessivePower.size() : 0;
10150             }
10151 
getExcessivePower(int i)10152             public ExcessivePower getExcessivePower(int i) {
10153                 if (mExcessivePower != null) {
10154                     return mExcessivePower.get(i);
10155                 }
10156                 return null;
10157             }
10158 
addExcessiveCpu(long overTimeMs, long usedTimeMs)10159             public void addExcessiveCpu(long overTimeMs, long usedTimeMs) {
10160                 if (mExcessivePower == null) {
10161                     mExcessivePower = new ArrayList<ExcessivePower>();
10162                 }
10163                 ExcessivePower ew = new ExcessivePower();
10164                 ew.type = ExcessivePower.TYPE_CPU;
10165                 ew.overTime = overTimeMs;
10166                 ew.usedTime = usedTimeMs;
10167                 mExcessivePower.add(ew);
10168             }
10169 
writeExcessivePowerToParcelLocked(Parcel out)10170             void writeExcessivePowerToParcelLocked(Parcel out) {
10171                 if (mExcessivePower == null) {
10172                     out.writeInt(0);
10173                     return;
10174                 }
10175 
10176                 final int N = mExcessivePower.size();
10177                 out.writeInt(N);
10178                 for (int i=0; i<N; i++) {
10179                     ExcessivePower ew = mExcessivePower.get(i);
10180                     out.writeInt(ew.type);
10181                     out.writeLong(ew.overTime);
10182                     out.writeLong(ew.usedTime);
10183                 }
10184             }
10185 
readExcessivePowerFromParcelLocked(Parcel in)10186             void readExcessivePowerFromParcelLocked(Parcel in) {
10187                 final int N = in.readInt();
10188                 if (N == 0) {
10189                     mExcessivePower = null;
10190                     return;
10191                 }
10192 
10193                 if (N > 10000) {
10194                     throw new ParcelFormatException(
10195                             "File corrupt: too many excessive power entries " + N);
10196                 }
10197 
10198                 mExcessivePower = new ArrayList<>();
10199                 for (int i=0; i<N; i++) {
10200                     ExcessivePower ew = new ExcessivePower();
10201                     ew.type = in.readInt();
10202                     ew.overTime = in.readLong();
10203                     ew.usedTime = in.readLong();
10204                     mExcessivePower.add(ew);
10205                 }
10206             }
10207 
writeToParcelLocked(Parcel out)10208             void writeToParcelLocked(Parcel out) {
10209                 out.writeLong(mUserTimeMs);
10210                 out.writeLong(mSystemTimeMs);
10211                 out.writeLong(mForegroundTimeMs);
10212                 out.writeInt(mStarts);
10213                 out.writeInt(mNumCrashes);
10214                 out.writeInt(mNumAnrs);
10215                 writeExcessivePowerToParcelLocked(out);
10216             }
10217 
readFromParcelLocked(Parcel in)10218             void readFromParcelLocked(Parcel in) {
10219                 mUserTimeMs = in.readLong();
10220                 mSystemTimeMs = in.readLong();
10221                 mForegroundTimeMs = in.readLong();
10222                 mStarts = in.readInt();
10223                 mNumCrashes = in.readInt();
10224                 mNumAnrs = in.readInt();
10225                 readExcessivePowerFromParcelLocked(in);
10226             }
10227 
10228             @UnsupportedAppUsage
addCpuTimeLocked(int utimeMs, int stimeMs)10229             public void addCpuTimeLocked(int utimeMs, int stimeMs) {
10230                 addCpuTimeLocked(utimeMs, stimeMs, mBsi.mOnBatteryTimeBase.isRunning());
10231             }
10232 
addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning)10233             public void addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning) {
10234                 if (isRunning) {
10235                     mUserTimeMs += utimeMs;
10236                     mSystemTimeMs += stimeMs;
10237                 }
10238             }
10239 
10240             @UnsupportedAppUsage
addForegroundTimeLocked(long ttimeMs)10241             public void addForegroundTimeLocked(long ttimeMs) {
10242                 mForegroundTimeMs += ttimeMs;
10243             }
10244 
10245             @UnsupportedAppUsage
incStartsLocked()10246             public void incStartsLocked() {
10247                 mStarts++;
10248             }
10249 
incNumCrashesLocked()10250             public void incNumCrashesLocked() {
10251                 mNumCrashes++;
10252             }
10253 
incNumAnrsLocked()10254             public void incNumAnrsLocked() {
10255                 mNumAnrs++;
10256             }
10257 
10258             @Override
isActive()10259             public boolean isActive() {
10260                 return mActive;
10261             }
10262 
10263             @Override
10264             @UnsupportedAppUsage
getUserTime(int which)10265             public long getUserTime(int which) {
10266                 return mUserTimeMs;
10267             }
10268 
10269             @Override
10270             @UnsupportedAppUsage
getSystemTime(int which)10271             public long getSystemTime(int which) {
10272                 return mSystemTimeMs;
10273             }
10274 
10275             @Override
10276             @UnsupportedAppUsage
getForegroundTime(int which)10277             public long getForegroundTime(int which) {
10278                 return mForegroundTimeMs;
10279             }
10280 
10281             @Override
10282             @UnsupportedAppUsage
getStarts(int which)10283             public int getStarts(int which) {
10284                 return mStarts;
10285             }
10286 
10287             @Override
getNumCrashes(int which)10288             public int getNumCrashes(int which) {
10289                 return mNumCrashes;
10290             }
10291 
10292             @Override
getNumAnrs(int which)10293             public int getNumAnrs(int which) {
10294                 return mNumAnrs;
10295             }
10296         }
10297 
10298         /**
10299          * The statistics associated with a particular package.
10300          */
10301         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
10302             /**
10303              * BatteryStatsImpl that we are associated with.
10304              */
10305             protected BatteryStatsImpl mBsi;
10306 
10307             /**
10308              * Number of times wakeup alarms have occurred for this app.
10309              * On screen-off timebase starting in report v25.
10310              */
10311             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
10312 
10313             /**
10314              * The statics we have collected for this package's services.
10315              */
10316             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
10317 
Pkg(BatteryStatsImpl bsi)10318             public Pkg(BatteryStatsImpl bsi) {
10319                 mBsi = bsi;
10320                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
10321             }
10322 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10323             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10324                     long baseRealtimeUs) {
10325             }
10326 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10327             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10328                     long baseRealtimeUs) {
10329             }
10330 
10331             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10332             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10333                 if (detachIfReset) {
10334                     this.detach();
10335                 }
10336                 return true;
10337             }
10338 
10339             @Override
detach()10340             public void detach() {
10341                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
10342                 for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
10343                     detachIfNotNull(mWakeupAlarms.valueAt(j));
10344                 }
10345                 for (int j = mServiceStats.size() - 1; j >= 0; j--) {
10346                     detachIfNotNull(mServiceStats.valueAt(j));
10347                 }
10348             }
10349 
readFromParcelLocked(Parcel in)10350             void readFromParcelLocked(Parcel in) {
10351                 int numWA = in.readInt();
10352                 mWakeupAlarms.clear();
10353                 for (int i=0; i<numWA; i++) {
10354                     String tag = in.readString();
10355                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
10356                 }
10357 
10358                 int numServs = in.readInt();
10359                 mServiceStats.clear();
10360                 for (int m = 0; m < numServs; m++) {
10361                     String serviceName = in.readString();
10362                     Uid.Pkg.Serv serv = new Serv(mBsi);
10363                     mServiceStats.put(serviceName, serv);
10364 
10365                     serv.readFromParcelLocked(in);
10366                 }
10367             }
10368 
writeToParcelLocked(Parcel out)10369             void writeToParcelLocked(Parcel out) {
10370                 int numWA = mWakeupAlarms.size();
10371                 out.writeInt(numWA);
10372                 for (int i=0; i<numWA; i++) {
10373                     out.writeString(mWakeupAlarms.keyAt(i));
10374                     mWakeupAlarms.valueAt(i).writeToParcel(out);
10375                 }
10376 
10377                 final int NS = mServiceStats.size();
10378                 out.writeInt(NS);
10379                 for (int i=0; i<NS; i++) {
10380                     out.writeString(mServiceStats.keyAt(i));
10381                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
10382                     serv.writeToParcelLocked(out);
10383                 }
10384             }
10385 
10386             @Override
getWakeupAlarmStats()10387             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
10388                 return mWakeupAlarms;
10389             }
10390 
noteWakeupAlarmLocked(String tag)10391             public void noteWakeupAlarmLocked(String tag) {
10392                 Counter c = mWakeupAlarms.get(tag);
10393                 if (c == null) {
10394                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
10395                     mWakeupAlarms.put(tag, c);
10396                 }
10397                 c.stepAtomic();
10398             }
10399 
10400             @Override
getServiceStats()10401             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
10402                 return mServiceStats;
10403             }
10404 
10405             /**
10406              * The statistics associated with a particular service.
10407              */
10408             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
10409                 /**
10410                  * BatteryStatsImpl that we are associated with.
10411                  */
10412                 protected BatteryStatsImpl mBsi;
10413 
10414                 /**
10415                  * The android package in which this service resides.
10416                  */
10417                 protected Pkg mPkg;
10418 
10419                 /**
10420                  * Total time (ms in battery uptime) the service has been left started.
10421                  */
10422                 protected long mStartTimeMs;
10423 
10424                 /**
10425                  * If service has been started and not yet stopped, this is
10426                  * when it was started.
10427                  */
10428                 protected long mRunningSinceMs;
10429 
10430                 /**
10431                  * True if we are currently running.
10432                  */
10433                 protected boolean mRunning;
10434 
10435                 /**
10436                  * Total number of times startService() has been called.
10437                  */
10438                 protected int mStarts;
10439 
10440                 /**
10441                  * Total time (ms in battery uptime) the service has been left launched.
10442                  */
10443                 protected long mLaunchedTimeMs;
10444 
10445                 /**
10446                  * If service has been launched and not yet exited, this is
10447                  * when it was launched (ms in battery uptime).
10448                  */
10449                 protected long mLaunchedSinceMs;
10450 
10451                 /**
10452                  * True if we are currently launched.
10453                  */
10454                 protected boolean mLaunched;
10455 
10456                 /**
10457                  * Total number times the service has been launched.
10458                  */
10459                 protected int mLaunches;
10460 
10461                 /**
10462                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
10463                  */
Serv(BatteryStatsImpl bsi)10464                 public Serv(BatteryStatsImpl bsi) {
10465                     mBsi = bsi;
10466                     mBsi.mOnBatteryTimeBase.add(this);
10467                 }
10468 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10469                 public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10470                         long baseRealtimeUs) {
10471                 }
10472 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10473                 public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10474                         long baseRealtimeUs) {
10475                 }
10476 
10477                 @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10478                 public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10479                     if (detachIfReset) {
10480                         this.detach();
10481                     }
10482                     return true;
10483                 }
10484 
10485                 /**
10486                  * Remove this Serv as a listener from the time base.
10487                  Ms*/
10488                 @Override
detach()10489                 public void detach() {
10490                     mBsi.mOnBatteryTimeBase.remove(this);
10491                 }
10492 
readFromParcelLocked(Parcel in)10493                 public void readFromParcelLocked(Parcel in) {
10494                     mStartTimeMs = in.readLong();
10495                     mRunningSinceMs = in.readLong();
10496                     mRunning = in.readInt() != 0;
10497                     mStarts = in.readInt();
10498                     mLaunchedTimeMs = in.readLong();
10499                     mLaunchedSinceMs = in.readLong();
10500                     mLaunched = in.readInt() != 0;
10501                     mLaunches = in.readInt();
10502                 }
10503 
writeToParcelLocked(Parcel out)10504                 public void writeToParcelLocked(Parcel out) {
10505                     out.writeLong(mStartTimeMs);
10506                     out.writeLong(mRunningSinceMs);
10507                     out.writeInt(mRunning ? 1 : 0);
10508                     out.writeInt(mStarts);
10509                     out.writeLong(mLaunchedTimeMs);
10510                     out.writeLong(mLaunchedSinceMs);
10511                     out.writeInt(mLaunched ? 1 : 0);
10512                     out.writeInt(mLaunches);
10513                 }
10514 
getLaunchTimeToNowLocked(long batteryUptimeMs)10515                 public long getLaunchTimeToNowLocked(long batteryUptimeMs) {
10516                     if (!mLaunched) return mLaunchedTimeMs;
10517                     return mLaunchedTimeMs + batteryUptimeMs - mLaunchedSinceMs;
10518                 }
10519 
getStartTimeToNowLocked(long batteryUptimeMs)10520                 public long getStartTimeToNowLocked(long batteryUptimeMs) {
10521                     if (!mRunning) return mStartTimeMs;
10522                     return mStartTimeMs + batteryUptimeMs - mRunningSinceMs;
10523                 }
10524 
10525                 @UnsupportedAppUsage
startLaunchedLocked()10526                 public void startLaunchedLocked() {
10527                     startLaunchedLocked(mBsi.mClocks.uptimeMillis());
10528                 }
10529 
startLaunchedLocked(long uptimeMs)10530                 public void startLaunchedLocked(long uptimeMs) {
10531                     if (!mLaunched) {
10532                         mLaunches++;
10533                         mLaunchedSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10534                         mLaunched = true;
10535                     }
10536                 }
10537 
10538                 @UnsupportedAppUsage
stopLaunchedLocked()10539                 public void stopLaunchedLocked() {
10540                     stopLaunchedLocked(mBsi.mClocks.uptimeMillis());
10541                 }
10542 
stopLaunchedLocked(long uptimeMs)10543                 public void stopLaunchedLocked(long uptimeMs) {
10544                     if (mLaunched) {
10545                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10546                                 - mLaunchedSinceMs;
10547                         if (timeMs > 0) {
10548                             mLaunchedTimeMs += timeMs;
10549                         } else {
10550                             mLaunches--;
10551                         }
10552                         mLaunched = false;
10553                     }
10554                 }
10555 
10556                 @UnsupportedAppUsage
startRunningLocked()10557                 public void startRunningLocked() {
10558                     startRunningLocked(mBsi.mClocks.uptimeMillis());
10559                 }
10560 
startRunningLocked(long uptimeMs)10561                 public void startRunningLocked(long uptimeMs) {
10562                     if (!mRunning) {
10563                         mStarts++;
10564                         mRunningSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10565                         mRunning = true;
10566                     }
10567                 }
10568 
10569                 @UnsupportedAppUsage
stopRunningLocked()10570                 public void stopRunningLocked() {
10571                     stopRunningLocked(mBsi.mClocks.uptimeMillis());
10572                 }
10573 
stopRunningLocked(long uptimeMs)10574                 public void stopRunningLocked(long uptimeMs) {
10575                     if (mRunning) {
10576                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10577                                 - mRunningSinceMs;
10578                         if (timeMs > 0) {
10579                             mStartTimeMs += timeMs;
10580                         } else {
10581                             mStarts--;
10582                         }
10583                         mRunning = false;
10584                     }
10585                 }
10586 
10587                 @UnsupportedAppUsage
getBatteryStats()10588                 public BatteryStatsImpl getBatteryStats() {
10589                     return mBsi;
10590                 }
10591 
10592                 @Override
getLaunches(int which)10593                 public int getLaunches(int which) {
10594                     return mLaunches;
10595                 }
10596 
10597                 @Override
getStartTime(long now, int which)10598                 public long getStartTime(long now, int which) {
10599                     return getStartTimeToNowLocked(now);
10600                 }
10601 
10602                 @Override
getStarts(int which)10603                 public int getStarts(int which) {
10604                     return mStarts;
10605                 }
10606             }
10607 
newServiceStatsLocked()10608             final Serv newServiceStatsLocked() {
10609                 return new Serv(mBsi);
10610             }
10611         }
10612 
10613         /**
10614          * Retrieve the statistics object for a particular process, creating
10615          * if needed.
10616          */
getProcessStatsLocked(String name)10617         public Proc getProcessStatsLocked(String name) {
10618             Proc ps = mProcessStats.get(name);
10619             if (ps == null) {
10620                 ps = new Proc(mBsi, name);
10621                 mProcessStats.put(name, ps);
10622             }
10623 
10624             return ps;
10625         }
10626 
10627         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState)10628         public void updateUidProcessStateLocked(int procState) {
10629             updateUidProcessStateLocked(procState,
10630                     mBsi.mClocks.elapsedRealtime(), mBsi.mClocks.uptimeMillis());
10631         }
10632 
updateUidProcessStateLocked(int procState, long elapsedRealtimeMs, long uptimeMs)10633         public void updateUidProcessStateLocked(int procState,
10634                 long elapsedRealtimeMs, long uptimeMs) {
10635             int uidRunningState;
10636             // Make special note of Foreground Services
10637             final boolean userAwareService =
10638                     (ActivityManager.isForegroundService(procState));
10639             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
10640 
10641             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
10642                 return;
10643             }
10644 
10645             if (mProcessState != uidRunningState) {
10646                 if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
10647                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
10648 
10649                     if (mBsi.trackPerProcStateCpuTimes()) {
10650                         if (mBsi.mPendingUids.size() == 0) {
10651                             mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
10652                                     mBsi.mOnBatteryTimeBase.isRunning(),
10653                                     mBsi.mOnBatteryScreenOffTimeBase.isRunning(),
10654                                     mBsi.mConstants.PROC_STATE_CPU_TIMES_READ_DELAY_MS);
10655                             mBsi.mNumSingleUidCpuTimeReads++;
10656                         } else {
10657                             mBsi.mNumBatchedSingleUidCpuTimeReads++;
10658                         }
10659                         if (mBsi.mPendingUids.indexOfKey(mUid) < 0
10660                                 || ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
10661                             mBsi.mPendingUids.put(mUid, mProcessState);
10662                         }
10663                     } else {
10664                         mBsi.mPendingUids.clear();
10665                     }
10666                 }
10667                 mProcessState = uidRunningState;
10668                 if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
10669                     if (mProcessStateTimer[uidRunningState] == null) {
10670                         makeProcessState(uidRunningState, null);
10671                     }
10672                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
10673                 }
10674 
10675                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10676                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10677             }
10678 
10679             if (userAwareService != mInForegroundService) {
10680                 if (userAwareService) {
10681                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
10682                 } else {
10683                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
10684                 }
10685                 mInForegroundService = userAwareService;
10686             }
10687         }
10688 
10689         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()10690         public boolean isInBackground() {
10691             // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
10692             // also considered to be 'background' for our purposes, because it's not foreground.
10693             return mProcessState >= PROCESS_STATE_BACKGROUND;
10694         }
10695 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)10696         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
10697             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
10698             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
10699         }
10700 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)10701         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
10702             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
10703             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
10704         }
10705 
getPidStats()10706         public SparseArray<? extends Pid> getPidStats() {
10707             return mPids;
10708         }
10709 
getPidStatsLocked(int pid)10710         public Pid getPidStatsLocked(int pid) {
10711             Pid p = mPids.get(pid);
10712             if (p == null) {
10713                 p = new Pid();
10714                 mPids.put(pid, p);
10715             }
10716             return p;
10717         }
10718 
10719         /**
10720          * Retrieve the statistics object for a particular service, creating
10721          * if needed.
10722          */
getPackageStatsLocked(String name)10723         public Pkg getPackageStatsLocked(String name) {
10724             Pkg ps = mPackageStats.get(name);
10725             if (ps == null) {
10726                 ps = new Pkg(mBsi);
10727                 mPackageStats.put(name, ps);
10728             }
10729 
10730             return ps;
10731         }
10732 
10733         /**
10734          * Retrieve the statistics object for a particular service, creating
10735          * if needed.
10736          */
getServiceStatsLocked(String pkg, String serv)10737         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
10738             Pkg ps = getPackageStatsLocked(pkg);
10739             Pkg.Serv ss = ps.mServiceStats.get(serv);
10740             if (ss == null) {
10741                 ss = ps.newServiceStatsLocked();
10742                 ps.mServiceStats.put(serv, ss);
10743             }
10744 
10745             return ss;
10746         }
10747 
readSyncSummaryFromParcelLocked(String name, Parcel in)10748         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
10749             DualTimer timer = mSyncStats.instantiateObject();
10750             timer.readSummaryFromParcelLocked(in);
10751             mSyncStats.add(name, timer);
10752         }
10753 
readJobSummaryFromParcelLocked(String name, Parcel in)10754         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
10755             DualTimer timer = mJobStats.instantiateObject();
10756             timer.readSummaryFromParcelLocked(in);
10757             mJobStats.add(name, timer);
10758         }
10759 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)10760         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
10761             Wakelock wl = new Wakelock(mBsi, this);
10762             mWakelockStats.add(wlName, wl);
10763             if (in.readInt() != 0) {
10764                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
10765             }
10766             if (in.readInt() != 0) {
10767                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
10768             }
10769             if (in.readInt() != 0) {
10770                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
10771             }
10772             if (in.readInt() != 0) {
10773                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
10774             }
10775         }
10776 
getSensorTimerLocked(int sensor, boolean create)10777         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
10778             Sensor se = mSensorStats.get(sensor);
10779             if (se == null) {
10780                 if (!create) {
10781                     return null;
10782                 }
10783                 se = new Sensor(mBsi, this, sensor);
10784                 mSensorStats.put(sensor, se);
10785             }
10786             DualTimer t = se.mTimer;
10787             if (t != null) {
10788                 return t;
10789             }
10790             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
10791             if (timers == null) {
10792                 timers = new ArrayList<StopwatchTimer>();
10793                 mBsi.mSensorTimers.put(sensor, timers);
10794             }
10795             t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
10796                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
10797             se.mTimer = t;
10798             return t;
10799         }
10800 
noteStartSyncLocked(String name, long elapsedRealtimeMs)10801         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
10802             DualTimer t = mSyncStats.startObject(name, elapsedRealtimeMs);
10803             if (t != null) {
10804                 t.startRunningLocked(elapsedRealtimeMs);
10805             }
10806         }
10807 
noteStopSyncLocked(String name, long elapsedRealtimeMs)10808         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
10809             DualTimer t = mSyncStats.stopObject(name, elapsedRealtimeMs);
10810             if (t != null) {
10811                 t.stopRunningLocked(elapsedRealtimeMs);
10812             }
10813         }
10814 
noteStartJobLocked(String name, long elapsedRealtimeMs)10815         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
10816             DualTimer t = mJobStats.startObject(name, elapsedRealtimeMs);
10817             if (t != null) {
10818                 t.startRunningLocked(elapsedRealtimeMs);
10819             }
10820         }
10821 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)10822         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
10823             DualTimer t = mJobStats.stopObject(name, elapsedRealtimeMs);
10824             if (t != null) {
10825                 t.stopRunningLocked(elapsedRealtimeMs);
10826             }
10827             if (mBsi.mOnBatteryTimeBase.isRunning()) {
10828                 SparseIntArray types = mJobCompletions.get(name);
10829                 if (types == null) {
10830                     types = new SparseIntArray();
10831                     mJobCompletions.put(name, types);
10832                 }
10833                 int last = types.get(stopReason, 0);
10834                 types.put(stopReason, last + 1);
10835             }
10836         }
10837 
getWakelockTimerLocked(Wakelock wl, int type)10838         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
10839             if (wl == null) {
10840                 return null;
10841             }
10842             switch (type) {
10843                 case WAKE_TYPE_PARTIAL: {
10844                     DualTimer t = wl.mTimerPartial;
10845                     if (t == null) {
10846                         t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
10847                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
10848                                 mOnBatteryScreenOffBackgroundTimeBase);
10849                         wl.mTimerPartial = t;
10850                     }
10851                     return t;
10852                 }
10853                 case WAKE_TYPE_FULL: {
10854                     StopwatchTimer t = wl.mTimerFull;
10855                     if (t == null) {
10856                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
10857                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
10858                         wl.mTimerFull = t;
10859                     }
10860                     return t;
10861                 }
10862                 case WAKE_TYPE_WINDOW: {
10863                     StopwatchTimer t = wl.mTimerWindow;
10864                     if (t == null) {
10865                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
10866                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
10867                         wl.mTimerWindow = t;
10868                     }
10869                     return t;
10870                 }
10871                 case WAKE_TYPE_DRAW: {
10872                     StopwatchTimer t = wl.mTimerDraw;
10873                     if (t == null) {
10874                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
10875                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
10876                         wl.mTimerDraw = t;
10877                     }
10878                     return t;
10879                 }
10880                 default:
10881                     throw new IllegalArgumentException("type=" + type);
10882             }
10883         }
10884 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)10885         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10886             Wakelock wl = mWakelockStats.startObject(name, elapsedRealtimeMs);
10887             if (wl != null) {
10888                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
10889             }
10890             if (type == WAKE_TYPE_PARTIAL) {
10891                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
10892                 if (pid >= 0) {
10893                     Pid p = getPidStatsLocked(pid);
10894                     if (p.mWakeNesting++ == 0) {
10895                         p.mWakeStartMs = elapsedRealtimeMs;
10896                     }
10897                 }
10898             }
10899         }
10900 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)10901         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10902             Wakelock wl = mWakelockStats.stopObject(name, elapsedRealtimeMs);
10903             if (wl != null) {
10904                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
10905                 wlt.stopRunningLocked(elapsedRealtimeMs);
10906             }
10907             if (type == WAKE_TYPE_PARTIAL) {
10908                 if (mAggregatedPartialWakelockTimer != null) {
10909                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
10910                 }
10911                 if (pid >= 0) {
10912                     Pid p = mPids.get(pid);
10913                     if (p != null && p.mWakeNesting > 0) {
10914                         if (p.mWakeNesting-- == 1) {
10915                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
10916                             p.mWakeStartMs = 0;
10917                         }
10918                     }
10919                 }
10920             }
10921         }
10922 
reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs)10923         public void reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs) {
10924             Proc p = getProcessStatsLocked(proc);
10925             if (p != null) {
10926                 p.addExcessiveCpu(overTimeMs, usedTimeMs);
10927             }
10928         }
10929 
noteStartSensor(int sensor, long elapsedRealtimeMs)10930         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
10931             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
10932             t.startRunningLocked(elapsedRealtimeMs);
10933         }
10934 
noteStopSensor(int sensor, long elapsedRealtimeMs)10935         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
10936             // Don't create a timer if one doesn't already exist
10937             DualTimer t = getSensorTimerLocked(sensor, false);
10938             if (t != null) {
10939                 t.stopRunningLocked(elapsedRealtimeMs);
10940             }
10941         }
10942 
noteStartGps(long elapsedRealtimeMs)10943         public void noteStartGps(long elapsedRealtimeMs) {
10944             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
10945         }
10946 
noteStopGps(long elapsedRealtimeMs)10947         public void noteStopGps(long elapsedRealtimeMs) {
10948             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
10949         }
10950 
getBatteryStats()10951         public BatteryStatsImpl getBatteryStats() {
10952             return mBsi;
10953         }
10954     }
10955 
getCpuFreqs()10956     public long[] getCpuFreqs() {
10957         return mCpuFreqs;
10958     }
10959 
BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider)10960     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
10961             MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider) {
10962         this(new SystemClocks(), systemDir, handler, cb, energyStatsCb, userInfoProvider);
10963     }
10964 
BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider)10965     private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
10966             PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb,
10967             UserInfoProvider userInfoProvider) {
10968         init(clocks);
10969 
10970         if (systemDir == null) {
10971             mStatsFile = null;
10972             mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
10973         } else {
10974             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
10975             mBatteryStatsHistory = new BatteryStatsHistory(this, systemDir, mHistoryBuffer);
10976         }
10977         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
10978         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
10979         mHandler = new MyHandler(handler.getLooper());
10980         mConstants = new Constants(mHandler);
10981         mStartCount++;
10982         initTimersAndCounters();
10983         mOnBattery = mOnBatteryInternal = false;
10984         long uptimeUs = mClocks.uptimeMillis() * 1000;
10985         long realtimeUs = mClocks.elapsedRealtime() * 1000;
10986         initTimes(uptimeUs, realtimeUs);
10987         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
10988         initDischarge(realtimeUs);
10989         clearHistoryLocked();
10990         updateDailyDeadlineLocked();
10991         mPlatformIdleStateCallback = cb;
10992         mMeasuredEnergyRetriever = energyStatsCb;
10993         mUserInfoProvider = userInfoProvider;
10994 
10995         // Notify statsd that the system is initially not in doze.
10996         mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
10997         FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
10998     }
10999 
11000     @VisibleForTesting
initTimersAndCounters()11001     protected void initTimersAndCounters() {
11002         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
11003         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
11004         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11005             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
11006                     mOnBatteryTimeBase);
11007         }
11008 
11009         mPerDisplayBatteryStats = new DisplayBatteryStats[1];
11010         mPerDisplayBatteryStats[0] = new DisplayBatteryStats(mClocks, mOnBatteryTimeBase);
11011 
11012         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
11013         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
11014                 mOnBatteryTimeBase);
11015         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
11016                 mOnBatteryTimeBase);
11017         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
11018         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
11019         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
11020         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
11021         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
11022             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
11023                     mOnBatteryTimeBase);
11024         }
11025         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
11026                 mOnBatteryTimeBase);
11027         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11028             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
11029                     mOnBatteryTimeBase);
11030         }
11031         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11032             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
11033             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
11034         }
11035         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
11036         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
11037                 NUM_BT_TX_LEVELS);
11038         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
11039                 ModemActivityInfo.getNumTxPowerLevels());
11040         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
11041         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
11042                 mOnBatteryTimeBase);
11043         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
11044         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
11045         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
11046         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null,
11047                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
11048         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
11049         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
11050         for (int i=0; i<NUM_WIFI_STATES; i++) {
11051             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
11052                     mOnBatteryTimeBase);
11053         }
11054         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11055             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
11056                     mOnBatteryTimeBase);
11057         }
11058         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11059             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
11060                     mOnBatteryTimeBase);
11061         }
11062         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
11063         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
11064             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
11065                 mOnBatteryTimeBase);
11066         }
11067         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
11068         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
11069         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
11070         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
11071         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
11072         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
11073         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11074         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11075         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11076         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11077         mDischargeStartLevel = 0;
11078         mDischargeUnplugLevel = 0;
11079         mDischargePlugLevel = -1;
11080         mDischargeCurrentLevel = 0;
11081         mCurrentBatteryLevel = 0;
11082     }
11083 
11084     @UnsupportedAppUsage
BatteryStatsImpl(Parcel p)11085     public BatteryStatsImpl(Parcel p) {
11086         this(new SystemClocks(), p);
11087     }
11088 
BatteryStatsImpl(Clocks clocks, Parcel p)11089     public BatteryStatsImpl(Clocks clocks, Parcel p) {
11090         init(clocks);
11091         mStatsFile = null;
11092         mCheckinFile = null;
11093         mDailyFile = null;
11094         mHandler = null;
11095         mExternalSync = null;
11096         mConstants = new Constants(mHandler);
11097         clearHistoryLocked();
11098         mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
11099         readFromParcel(p);
11100         mPlatformIdleStateCallback = null;
11101         mMeasuredEnergyRetriever = null;
11102     }
11103 
setPowerProfileLocked(PowerProfile profile)11104     public void setPowerProfileLocked(PowerProfile profile) {
11105         mPowerProfile = profile;
11106 
11107         // We need to initialize the KernelCpuSpeedReaders to read from
11108         // the first cpu of each core. Once we have the PowerProfile, we have access to this
11109         // information.
11110         final int numClusters = mPowerProfile.getNumCpuClusters();
11111         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
11112         int firstCpuOfCluster = 0;
11113         for (int i = 0; i < numClusters; i++) {
11114             final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
11115             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
11116                     numSpeedSteps);
11117             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
11118         }
11119 
11120         if (mEstimatedBatteryCapacityMah == -1) {
11121             // Initialize the estimated battery capacity to a known preset one.
11122             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
11123         }
11124 
11125         setDisplayCountLocked(mPowerProfile.getNumDisplays());
11126     }
11127 
getPowerProfile()11128     PowerProfile getPowerProfile() {
11129         return mPowerProfile;
11130     }
11131 
11132     /**
11133      * Starts tracking CPU time-in-state for threads of the system server process,
11134      * keeping a separate account of threads receiving incoming binder calls.
11135      */
startTrackingSystemServerCpuTime()11136     public void startTrackingSystemServerCpuTime() {
11137         mSystemServerCpuThreadReader.startTrackingThreadCpuTime();
11138     }
11139 
getSystemServiceCpuThreadTimes()11140     public SystemServiceCpuThreadTimes getSystemServiceCpuThreadTimes() {
11141         return mSystemServerCpuThreadReader.readAbsolute();
11142     }
11143 
setCallback(BatteryCallback cb)11144     public void setCallback(BatteryCallback cb) {
11145         mCallback = cb;
11146     }
11147 
setRadioScanningTimeoutLocked(long timeoutUs)11148     public void setRadioScanningTimeoutLocked(long timeoutUs) {
11149         if (mPhoneSignalScanningTimer != null) {
11150             mPhoneSignalScanningTimer.setTimeout(timeoutUs);
11151         }
11152     }
11153 
setExternalStatsSyncLocked(ExternalStatsSync sync)11154     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
11155         mExternalSync = sync;
11156     }
11157 
11158     /**
11159      * Initialize and set multi display timers and states.
11160      */
setDisplayCountLocked(int numDisplays)11161     public void setDisplayCountLocked(int numDisplays) {
11162         mPerDisplayBatteryStats = new DisplayBatteryStats[numDisplays];
11163         for (int i = 0; i < numDisplays; i++) {
11164             mPerDisplayBatteryStats[i] = new DisplayBatteryStats(mClocks, mOnBatteryTimeBase);
11165         }
11166     }
11167 
updateDailyDeadlineLocked()11168     public void updateDailyDeadlineLocked() {
11169         // Get the current time.
11170         long currentTimeMs = mDailyStartTimeMs = mClocks.currentTimeMillis();
11171         Calendar calDeadline = Calendar.getInstance();
11172         calDeadline.setTimeInMillis(currentTimeMs);
11173 
11174         // Move time up to the next day, ranging from 1am to 3pm.
11175         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
11176         calDeadline.set(Calendar.MILLISECOND, 0);
11177         calDeadline.set(Calendar.SECOND, 0);
11178         calDeadline.set(Calendar.MINUTE, 0);
11179         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
11180         mNextMinDailyDeadlineMs = calDeadline.getTimeInMillis();
11181         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
11182         mNextMaxDailyDeadlineMs = calDeadline.getTimeInMillis();
11183     }
11184 
recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs)11185     public void recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs) {
11186         if (currentTimeMs >= mNextMaxDailyDeadlineMs) {
11187             recordDailyStatsLocked();
11188         } else if (settled && currentTimeMs >= mNextMinDailyDeadlineMs) {
11189             recordDailyStatsLocked();
11190         } else if (currentTimeMs < (mDailyStartTimeMs - (1000 * 60 * 60 * 24))) {
11191             recordDailyStatsLocked();
11192         }
11193     }
11194 
recordDailyStatsLocked()11195     public void recordDailyStatsLocked() {
11196         DailyItem item = new DailyItem();
11197         item.mStartTime = mDailyStartTimeMs;
11198         item.mEndTime = mClocks.currentTimeMillis();
11199         boolean hasData = false;
11200         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
11201             hasData = true;
11202             item.mDischargeSteps = new LevelStepTracker(
11203                     mDailyDischargeStepTracker.mNumStepDurations,
11204                     mDailyDischargeStepTracker.mStepDurations);
11205         }
11206         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
11207             hasData = true;
11208             item.mChargeSteps = new LevelStepTracker(
11209                     mDailyChargeStepTracker.mNumStepDurations,
11210                     mDailyChargeStepTracker.mStepDurations);
11211         }
11212         if (mDailyPackageChanges != null) {
11213             hasData = true;
11214             item.mPackageChanges = mDailyPackageChanges;
11215             mDailyPackageChanges = null;
11216         }
11217         mDailyDischargeStepTracker.init();
11218         mDailyChargeStepTracker.init();
11219         updateDailyDeadlineLocked();
11220 
11221         if (hasData) {
11222             final long startTimeMs = SystemClock.uptimeMillis();
11223             mDailyItems.add(item);
11224             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
11225                 mDailyItems.remove(0);
11226             }
11227             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
11228             try {
11229                 TypedXmlSerializer out = Xml.resolveSerializer(memStream);
11230                 writeDailyItemsLocked(out);
11231                 final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
11232                 BackgroundThread.getHandler().post(new Runnable() {
11233                     @Override
11234                     public void run() {
11235                         synchronized (mCheckinFile) {
11236                             final long startTimeMs2 = SystemClock.uptimeMillis();
11237                             FileOutputStream stream = null;
11238                             try {
11239                                 stream = mDailyFile.startWrite();
11240                                 memStream.writeTo(stream);
11241                                 stream.flush();
11242                                 mDailyFile.finishWrite(stream);
11243                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
11244                                         "batterystats-daily",
11245                                         initialTimeMs + SystemClock.uptimeMillis() - startTimeMs2);
11246                             } catch (IOException e) {
11247                                 Slog.w("BatteryStats",
11248                                         "Error writing battery daily items", e);
11249                                 mDailyFile.failWrite(stream);
11250                             }
11251                         }
11252                     }
11253                 });
11254             } catch (IOException e) {
11255             }
11256         }
11257     }
11258 
writeDailyItemsLocked(TypedXmlSerializer out)11259     private void writeDailyItemsLocked(TypedXmlSerializer out) throws IOException {
11260         StringBuilder sb = new StringBuilder(64);
11261         out.startDocument(null, true);
11262         out.startTag(null, "daily-items");
11263         for (int i=0; i<mDailyItems.size(); i++) {
11264             final DailyItem dit = mDailyItems.get(i);
11265             out.startTag(null, "item");
11266             out.attributeLong(null, "start", dit.mStartTime);
11267             out.attributeLong(null, "end", dit.mEndTime);
11268             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
11269             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
11270             if (dit.mPackageChanges != null) {
11271                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
11272                     PackageChange pc = dit.mPackageChanges.get(j);
11273                     if (pc.mUpdate) {
11274                         out.startTag(null, "upd");
11275                         out.attribute(null, "pkg", pc.mPackageName);
11276                         out.attributeLong(null, "ver", pc.mVersionCode);
11277                         out.endTag(null, "upd");
11278                     } else {
11279                         out.startTag(null, "rem");
11280                         out.attribute(null, "pkg", pc.mPackageName);
11281                         out.endTag(null, "rem");
11282                     }
11283                 }
11284             }
11285             out.endTag(null, "item");
11286         }
11287         out.endTag(null, "daily-items");
11288         out.endDocument();
11289     }
11290 
writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)11291     private void writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps,
11292             StringBuilder tmpBuilder) throws IOException {
11293         if (steps != null) {
11294             out.startTag(null, tag);
11295             out.attributeInt(null, "n", steps.mNumStepDurations);
11296             for (int i=0; i<steps.mNumStepDurations; i++) {
11297                 out.startTag(null, "s");
11298                 tmpBuilder.setLength(0);
11299                 steps.encodeEntryAt(i, tmpBuilder);
11300                 out.attribute(null, "v", tmpBuilder.toString());
11301                 out.endTag(null, "s");
11302             }
11303             out.endTag(null, tag);
11304         }
11305     }
11306 
readDailyStatsLocked()11307     public void readDailyStatsLocked() {
11308         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
11309         mDailyItems.clear();
11310         FileInputStream stream;
11311         try {
11312             stream = mDailyFile.openRead();
11313         } catch (FileNotFoundException e) {
11314             return;
11315         }
11316         try {
11317             TypedXmlPullParser parser = Xml.resolvePullParser(stream);
11318             readDailyItemsLocked(parser);
11319         } catch (IOException e) {
11320         } finally {
11321             try {
11322                 stream.close();
11323             } catch (IOException e) {
11324             }
11325         }
11326     }
11327 
readDailyItemsLocked(TypedXmlPullParser parser)11328     private void readDailyItemsLocked(TypedXmlPullParser parser) {
11329         try {
11330             int type;
11331             while ((type = parser.next()) != XmlPullParser.START_TAG
11332                     && type != XmlPullParser.END_DOCUMENT) {
11333                 ;
11334             }
11335 
11336             if (type != XmlPullParser.START_TAG) {
11337                 throw new IllegalStateException("no start tag found");
11338             }
11339 
11340             int outerDepth = parser.getDepth();
11341             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11342                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11343                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11344                     continue;
11345                 }
11346 
11347                 String tagName = parser.getName();
11348                 if (tagName.equals("item")) {
11349                     readDailyItemTagLocked(parser);
11350                 } else {
11351                     Slog.w(TAG, "Unknown element under <daily-items>: "
11352                             + parser.getName());
11353                     XmlUtils.skipCurrentTag(parser);
11354                 }
11355             }
11356 
11357         } catch (IllegalStateException e) {
11358             Slog.w(TAG, "Failed parsing daily " + e);
11359         } catch (NullPointerException e) {
11360             Slog.w(TAG, "Failed parsing daily " + e);
11361         } catch (NumberFormatException e) {
11362             Slog.w(TAG, "Failed parsing daily " + e);
11363         } catch (XmlPullParserException e) {
11364             Slog.w(TAG, "Failed parsing daily " + e);
11365         } catch (IOException e) {
11366             Slog.w(TAG, "Failed parsing daily " + e);
11367         } catch (IndexOutOfBoundsException e) {
11368             Slog.w(TAG, "Failed parsing daily " + e);
11369         }
11370     }
11371 
readDailyItemTagLocked(TypedXmlPullParser parser)11372     void readDailyItemTagLocked(TypedXmlPullParser parser) throws NumberFormatException,
11373             XmlPullParserException, IOException {
11374         DailyItem dit = new DailyItem();
11375         dit.mStartTime = parser.getAttributeLong(null, "start", 0);
11376         dit.mEndTime = parser.getAttributeLong(null, "end", 0);
11377         int outerDepth = parser.getDepth();
11378         int type;
11379         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11380                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11381             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11382                 continue;
11383             }
11384 
11385             String tagName = parser.getName();
11386             if (tagName.equals("dis")) {
11387                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
11388             } else if (tagName.equals("chg")) {
11389                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
11390             } else if (tagName.equals("upd")) {
11391                 if (dit.mPackageChanges == null) {
11392                     dit.mPackageChanges = new ArrayList<>();
11393                 }
11394                 PackageChange pc = new PackageChange();
11395                 pc.mUpdate = true;
11396                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11397                 pc.mVersionCode = parser.getAttributeLong(null, "ver", 0);
11398                 dit.mPackageChanges.add(pc);
11399                 XmlUtils.skipCurrentTag(parser);
11400             } else if (tagName.equals("rem")) {
11401                 if (dit.mPackageChanges == null) {
11402                     dit.mPackageChanges = new ArrayList<>();
11403                 }
11404                 PackageChange pc = new PackageChange();
11405                 pc.mUpdate = false;
11406                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11407                 dit.mPackageChanges.add(pc);
11408                 XmlUtils.skipCurrentTag(parser);
11409             } else {
11410                 Slog.w(TAG, "Unknown element under <item>: "
11411                         + parser.getName());
11412                 XmlUtils.skipCurrentTag(parser);
11413             }
11414         }
11415         mDailyItems.add(dit);
11416     }
11417 
readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge, String tag)11418     void readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge,
11419             String tag)
11420             throws NumberFormatException, XmlPullParserException, IOException {
11421         final int num = parser.getAttributeInt(null, "n", -1);
11422         if (num == -1) {
11423             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
11424             XmlUtils.skipCurrentTag(parser);
11425             return;
11426         }
11427         LevelStepTracker steps = new LevelStepTracker(num);
11428         if (isCharge) {
11429             dit.mChargeSteps = steps;
11430         } else {
11431             dit.mDischargeSteps = steps;
11432         }
11433         int i = 0;
11434         int outerDepth = parser.getDepth();
11435         int type;
11436         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11437                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11438             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11439                 continue;
11440             }
11441 
11442             String tagName = parser.getName();
11443             if ("s".equals(tagName)) {
11444                 if (i < num) {
11445                     String valueAttr = parser.getAttributeValue(null, "v");
11446                     if (valueAttr != null) {
11447                         steps.decodeEntryAt(i, valueAttr);
11448                         i++;
11449                     }
11450                 }
11451             } else {
11452                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
11453                         + parser.getName());
11454                 XmlUtils.skipCurrentTag(parser);
11455             }
11456         }
11457         steps.mNumStepDurations = i;
11458     }
11459 
11460     @Override
getDailyItemLocked(int daysAgo)11461     public DailyItem getDailyItemLocked(int daysAgo) {
11462         int index = mDailyItems.size()-1-daysAgo;
11463         return index >= 0 ? mDailyItems.get(index) : null;
11464     }
11465 
11466     @Override
getCurrentDailyStartTime()11467     public long getCurrentDailyStartTime() {
11468         return mDailyStartTimeMs;
11469     }
11470 
11471     @Override
getNextMinDailyDeadline()11472     public long getNextMinDailyDeadline() {
11473         return mNextMinDailyDeadlineMs;
11474     }
11475 
11476     @Override
getNextMaxDailyDeadline()11477     public long getNextMaxDailyDeadline() {
11478         return mNextMaxDailyDeadlineMs;
11479     }
11480 
getHistoryTotalSize()11481     public int getHistoryTotalSize() {
11482         return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
11483     }
11484 
getHistoryUsedSize()11485     public int getHistoryUsedSize() {
11486         return mBatteryStatsHistory.getHistoryUsedSize();
11487     }
11488 
11489     @Override
11490     @UnsupportedAppUsage
startIteratingHistoryLocked()11491     public boolean startIteratingHistoryLocked() {
11492         mReadOverflow = false;
11493         mBatteryStatsHistoryIterator = createBatteryStatsHistoryIterator();
11494         return true;
11495     }
11496 
11497     /**
11498      * Creates an iterator for battery stats history.
11499      */
11500     @VisibleForTesting
createBatteryStatsHistoryIterator()11501     public BatteryStatsHistoryIterator createBatteryStatsHistoryIterator() {
11502         ArrayList<HistoryTag> tags = new ArrayList<>(mHistoryTagPool.size());
11503         for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
11504             final HistoryTag tag = entry.getKey();
11505             tag.poolIdx = entry.getValue();
11506             tags.add(tag);
11507         }
11508 
11509         return new BatteryStatsHistoryIterator(mBatteryStatsHistory, tags);
11510     }
11511 
11512     @Override
getHistoryStringPoolSize()11513     public int getHistoryStringPoolSize() {
11514         return mBatteryStatsHistoryIterator.getHistoryStringPoolSize();
11515     }
11516 
11517     @Override
getHistoryStringPoolBytes()11518     public int getHistoryStringPoolBytes() {
11519         return mBatteryStatsHistoryIterator.getHistoryStringPoolBytes();
11520     }
11521 
11522     @Override
getHistoryTagPoolString(int index)11523     public String getHistoryTagPoolString(int index) {
11524         return mBatteryStatsHistoryIterator.getHistoryTagPoolString(index);
11525     }
11526 
11527     @Override
getHistoryTagPoolUid(int index)11528     public int getHistoryTagPoolUid(int index) {
11529         return mBatteryStatsHistoryIterator.getHistoryTagPoolUid(index);
11530     }
11531 
11532     @Override
11533     @UnsupportedAppUsage
getNextHistoryLocked(HistoryItem out)11534     public boolean getNextHistoryLocked(HistoryItem out) {
11535         return mBatteryStatsHistoryIterator.next(out);
11536     }
11537 
11538     @Override
finishIteratingHistoryLocked()11539     public void finishIteratingHistoryLocked() {
11540         mBatteryStatsHistoryIterator = null;
11541     }
11542 
11543     @Override
getHistoryBaseTime()11544     public long getHistoryBaseTime() {
11545         return mHistoryBaseTimeMs;
11546     }
11547 
11548     @Override
getStartCount()11549     public int getStartCount() {
11550         return mStartCount;
11551     }
11552 
11553     @UnsupportedAppUsage
isOnBattery()11554     public boolean isOnBattery() {
11555         return mOnBattery;
11556     }
11557 
isCharging()11558     public boolean isCharging() {
11559         return mCharging;
11560     }
11561 
initTimes(long uptimeUs, long realtimeUs)11562     void initTimes(long uptimeUs, long realtimeUs) {
11563         mStartClockTimeMs = mClocks.currentTimeMillis();
11564         mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
11565         mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
11566         mRealtimeUs = 0;
11567         mUptimeUs = 0;
11568         mRealtimeStartUs = realtimeUs;
11569         mUptimeStartUs = uptimeUs;
11570     }
11571 
initDischarge(long elapsedRealtimeUs)11572     void initDischarge(long elapsedRealtimeUs) {
11573         mLowDischargeAmountSinceCharge = 0;
11574         mHighDischargeAmountSinceCharge = 0;
11575         mDischargeAmountScreenOn = 0;
11576         mDischargeAmountScreenOnSinceCharge = 0;
11577         mDischargeAmountScreenOff = 0;
11578         mDischargeAmountScreenOffSinceCharge = 0;
11579         mDischargeAmountScreenDoze = 0;
11580         mDischargeAmountScreenDozeSinceCharge = 0;
11581         mDischargeStepTracker.init();
11582         mChargeStepTracker.init();
11583         mDischargeScreenOffCounter.reset(false, elapsedRealtimeUs);
11584         mDischargeScreenDozeCounter.reset(false, elapsedRealtimeUs);
11585         mDischargeLightDozeCounter.reset(false, elapsedRealtimeUs);
11586         mDischargeDeepDozeCounter.reset(false, elapsedRealtimeUs);
11587         mDischargeCounter.reset(false, elapsedRealtimeUs);
11588     }
11589 
setBatteryResetListener(BatteryResetListener batteryResetListener)11590     public void setBatteryResetListener(BatteryResetListener batteryResetListener) {
11591         mBatteryResetListener = batteryResetListener;
11592     }
11593 
resetAllStatsCmdLocked()11594     public void resetAllStatsCmdLocked() {
11595         final long mSecUptime = mClocks.uptimeMillis();
11596         long uptimeUs = mSecUptime * 1000;
11597         long mSecRealtime = mClocks.elapsedRealtime();
11598         long realtimeUs = mSecRealtime * 1000;
11599         resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_ADB_COMMAND);
11600         mDischargeStartLevel = mHistoryCur.batteryLevel;
11601         pullPendingStateUpdatesLocked();
11602         addHistoryRecordLocked(mSecRealtime, mSecUptime);
11603         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
11604                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
11605         mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
11606         mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
11607         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
11608             if (Display.isOnState(mScreenState)) {
11609                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
11610                 mDischargeScreenDozeUnplugLevel = 0;
11611                 mDischargeScreenOffUnplugLevel = 0;
11612             } else if (Display.isDozeState(mScreenState)) {
11613                 mDischargeScreenOnUnplugLevel = 0;
11614                 mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
11615                 mDischargeScreenOffUnplugLevel = 0;
11616             } else {
11617                 mDischargeScreenOnUnplugLevel = 0;
11618                 mDischargeScreenDozeUnplugLevel = 0;
11619                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
11620             }
11621             mDischargeAmountScreenOn = 0;
11622             mDischargeAmountScreenOff = 0;
11623             mDischargeAmountScreenDoze = 0;
11624         }
11625         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
11626     }
11627 
resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis, int resetReason)11628     private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis,
11629             int resetReason) {
11630         if (mBatteryResetListener != null) {
11631             mBatteryResetListener.prepareForBatteryStatsReset(resetReason);
11632         }
11633 
11634         final long uptimeUs = uptimeMillis * 1000;
11635         final long elapsedRealtimeUs = elapsedRealtimeMillis * 1000;
11636         mStartCount = 0;
11637         initTimes(uptimeUs, elapsedRealtimeUs);
11638         mScreenOnTimer.reset(false, elapsedRealtimeUs);
11639         mScreenDozeTimer.reset(false, elapsedRealtimeUs);
11640         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11641             mScreenBrightnessTimer[i].reset(false, elapsedRealtimeUs);
11642         }
11643 
11644         final int numDisplays = mPerDisplayBatteryStats.length;
11645         for (int i = 0; i < numDisplays; i++) {
11646             mPerDisplayBatteryStats[i].reset(elapsedRealtimeUs);
11647         }
11648 
11649         if (mPowerProfile != null) {
11650             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
11651         } else {
11652             mEstimatedBatteryCapacityMah = -1;
11653         }
11654         mLastLearnedBatteryCapacityUah = -1;
11655         mMinLearnedBatteryCapacityUah = -1;
11656         mMaxLearnedBatteryCapacityUah = -1;
11657         mInteractiveTimer.reset(false, elapsedRealtimeUs);
11658         mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs);
11659         mLastIdleTimeStartMs = elapsedRealtimeMillis;
11660         mLongestLightIdleTimeMs = 0;
11661         mLongestFullIdleTimeMs = 0;
11662         mDeviceIdleModeLightTimer.reset(false, elapsedRealtimeUs);
11663         mDeviceIdleModeFullTimer.reset(false, elapsedRealtimeUs);
11664         mDeviceLightIdlingTimer.reset(false, elapsedRealtimeUs);
11665         mDeviceIdlingTimer.reset(false, elapsedRealtimeUs);
11666         mPhoneOnTimer.reset(false, elapsedRealtimeUs);
11667         mAudioOnTimer.reset(false, elapsedRealtimeUs);
11668         mVideoOnTimer.reset(false, elapsedRealtimeUs);
11669         mFlashlightOnTimer.reset(false, elapsedRealtimeUs);
11670         mCameraOnTimer.reset(false, elapsedRealtimeUs);
11671         mBluetoothScanTimer.reset(false, elapsedRealtimeUs);
11672         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
11673             mPhoneSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
11674         }
11675         mPhoneSignalScanningTimer.reset(false, elapsedRealtimeUs);
11676         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11677             mPhoneDataConnectionsTimer[i].reset(false, elapsedRealtimeUs);
11678         }
11679         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11680             mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs);
11681             mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs);
11682         }
11683         mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs);
11684         mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs);
11685         mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs);
11686         mMobileRadioActiveUnknownTime.reset(false, elapsedRealtimeUs);
11687         mMobileRadioActiveUnknownCount.reset(false, elapsedRealtimeUs);
11688         mWifiOnTimer.reset(false, elapsedRealtimeUs);
11689         mGlobalWifiRunningTimer.reset(false, elapsedRealtimeUs);
11690         for (int i=0; i<NUM_WIFI_STATES; i++) {
11691             mWifiStateTimer[i].reset(false, elapsedRealtimeUs);
11692         }
11693         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11694             mWifiSupplStateTimer[i].reset(false, elapsedRealtimeUs);
11695         }
11696         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11697             mWifiSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
11698         }
11699         mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs);
11700         mWifiActiveTimer.reset(false, elapsedRealtimeUs);
11701         mWifiActivity.reset(false, elapsedRealtimeUs);
11702         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
11703             mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs);
11704         }
11705         mBluetoothActivity.reset(false, elapsedRealtimeUs);
11706         mModemActivity.reset(false, elapsedRealtimeUs);
11707         mNumConnectivityChange = 0;
11708 
11709         for (int i=0; i<mUidStats.size(); i++) {
11710             if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs, resetReason)) {
11711                 mUidStats.valueAt(i).detachFromTimeBase();
11712                 mUidStats.remove(mUidStats.keyAt(i));
11713                 i--;
11714             }
11715         }
11716 
11717         if (mRpmStats.size() > 0) {
11718             for (SamplingTimer timer : mRpmStats.values()) {
11719                 mOnBatteryTimeBase.remove(timer);
11720             }
11721             mRpmStats.clear();
11722         }
11723         if (mScreenOffRpmStats.size() > 0) {
11724             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
11725                 mOnBatteryScreenOffTimeBase.remove(timer);
11726             }
11727             mScreenOffRpmStats.clear();
11728         }
11729 
11730         if (mKernelWakelockStats.size() > 0) {
11731             for (SamplingTimer timer : mKernelWakelockStats.values()) {
11732                 mOnBatteryScreenOffTimeBase.remove(timer);
11733             }
11734             mKernelWakelockStats.clear();
11735         }
11736 
11737         if (mKernelMemoryStats.size() > 0) {
11738             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
11739                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
11740             }
11741             mKernelMemoryStats.clear();
11742         }
11743 
11744         if (mWakeupReasonStats.size() > 0) {
11745             for (SamplingTimer timer : mWakeupReasonStats.values()) {
11746                 mOnBatteryTimeBase.remove(timer);
11747             }
11748             mWakeupReasonStats.clear();
11749         }
11750 
11751         mTmpRailStats.reset();
11752 
11753         MeasuredEnergyStats.resetIfNotNull(mGlobalMeasuredEnergyStats);
11754 
11755         resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
11756 
11757         mLastHistoryStepDetails = null;
11758         mLastStepCpuUserTimeMs = mLastStepCpuSystemTimeMs = 0;
11759         mCurStepCpuUserTimeMs = mCurStepCpuSystemTimeMs = 0;
11760         mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
11761         mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
11762         mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
11763         mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
11764         mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
11765         mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
11766         mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
11767         mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
11768 
11769         mNumAllUidCpuTimeReads = 0;
11770         mNumUidsRemoved = 0;
11771 
11772         initDischarge(elapsedRealtimeUs);
11773 
11774         clearHistoryLocked();
11775         if (mBatteryStatsHistory != null) {
11776             mBatteryStatsHistory.resetAllFiles();
11777         }
11778 
11779         // Flush external data, gathering snapshots, but don't process it since it is pre-reset data
11780         mIgnoreNextExternalStats = true;
11781         mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ALL);
11782 
11783         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
11784     }
11785 
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)11786     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
11787         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
11788             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
11789                 // Not recording process starts/stops.
11790                 continue;
11791             }
11792             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
11793             if (active == null) {
11794                 continue;
11795             }
11796             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
11797                 SparseIntArray uids = ent.getValue();
11798                 for (int j=0; j<uids.size(); j++) {
11799                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
11800                             uids.keyAt(j));
11801                 }
11802             }
11803         }
11804     }
11805 
updateDischargeScreenLevelsLocked(int oldState, int newState)11806     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
11807         updateOldDischargeScreenLevelLocked(oldState);
11808         updateNewDischargeScreenLevelLocked(newState);
11809     }
11810 
updateOldDischargeScreenLevelLocked(int state)11811     private void updateOldDischargeScreenLevelLocked(int state) {
11812         if (Display.isOnState(state)) {
11813             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
11814             if (diff > 0) {
11815                 mDischargeAmountScreenOn += diff;
11816                 mDischargeAmountScreenOnSinceCharge += diff;
11817             }
11818         } else if (Display.isDozeState(state)) {
11819             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
11820             if (diff > 0) {
11821                 mDischargeAmountScreenDoze += diff;
11822                 mDischargeAmountScreenDozeSinceCharge += diff;
11823             }
11824         } else if (Display.isOffState(state)) {
11825             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
11826             if (diff > 0) {
11827                 mDischargeAmountScreenOff += diff;
11828                 mDischargeAmountScreenOffSinceCharge += diff;
11829             }
11830         }
11831     }
11832 
updateNewDischargeScreenLevelLocked(int state)11833     private void updateNewDischargeScreenLevelLocked(int state) {
11834         if (Display.isOnState(state)) {
11835             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
11836             mDischargeScreenOffUnplugLevel = 0;
11837             mDischargeScreenDozeUnplugLevel = 0;
11838         } else if (Display.isDozeState(state)) {
11839             mDischargeScreenOnUnplugLevel = 0;
11840             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
11841             mDischargeScreenOffUnplugLevel = 0;
11842         } else if (Display.isOffState(state)) {
11843             mDischargeScreenOnUnplugLevel = 0;
11844             mDischargeScreenDozeUnplugLevel = 0;
11845             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
11846         }
11847     }
11848 
pullPendingStateUpdatesLocked()11849     public void pullPendingStateUpdatesLocked() {
11850         if (mOnBatteryInternal) {
11851             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
11852         }
11853     }
11854 
11855     private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
11856 
11857     private final Object mWifiNetworkLock = new Object();
11858 
11859     @GuardedBy("mWifiNetworkLock")
11860     private String[] mWifiIfaces = EmptyArray.STRING;
11861 
11862     @GuardedBy("mWifiNetworkLock")
11863     private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
11864 
11865     private final Object mModemNetworkLock = new Object();
11866 
11867     @GuardedBy("mModemNetworkLock")
11868     private String[] mModemIfaces = EmptyArray.STRING;
11869 
11870     @GuardedBy("mModemNetworkLock")
11871     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
11872 
11873     @VisibleForTesting
readNetworkStatsLocked(String[] ifaces)11874     protected NetworkStats readNetworkStatsLocked(String[] ifaces) {
11875         try {
11876             if (!ArrayUtils.isEmpty(ifaces)) {
11877                 INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
11878                         ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
11879                 if (statsService != null) {
11880                     return statsService.getDetailedUidStats(ifaces);
11881                 } else {
11882                     Slog.e(TAG, "Failed to get networkStatsService ");
11883                 }
11884             }
11885         } catch (RemoteException e) {
11886             Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces) + e);
11887         }
11888         return null;
11889     }
11890 
11891     /**
11892      * Distribute WiFi energy info and network traffic to apps.
11893      * @param info The energy information from the WiFi controller.
11894      */
updateWifiState(@ullable final WifiActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)11895     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
11896             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
11897         if (DEBUG_ENERGY) {
11898             Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
11899         }
11900 
11901         // Grab a separate lock to acquire the network stats, which may do I/O.
11902         NetworkStats delta = null;
11903         synchronized (mWifiNetworkLock) {
11904             final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
11905             if (latestStats != null) {
11906                 delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
11907                         mNetworkStatsPool.acquire());
11908                 mNetworkStatsPool.release(mLastWifiNetworkStats);
11909                 mLastWifiNetworkStats = latestStats;
11910             }
11911         }
11912 
11913         synchronized (this) {
11914             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
11915                 if (delta != null) {
11916                     mNetworkStatsPool.release(delta);
11917                 }
11918                 if (mIgnoreNextExternalStats) {
11919                     // TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
11920                     //  global one) here like we do for display. But I'm not sure it's worth the
11921                     //  complicated code for a codepath that shouldn't ever actually happen in real
11922                     //  life.
11923                 }
11924                 return;
11925             }
11926 
11927             final SparseDoubleArray uidEstimatedConsumptionMah =
11928                     (mGlobalMeasuredEnergyStats != null
11929                             && mWifiPowerCalculator != null && consumedChargeUC > 0) ?
11930                             new SparseDoubleArray() : null;
11931             double totalEstimatedConsumptionMah = 0;
11932 
11933             SparseLongArray rxPackets = new SparseLongArray();
11934             SparseLongArray txPackets = new SparseLongArray();
11935             long totalTxPackets = 0;
11936             long totalRxPackets = 0;
11937             if (delta != null) {
11938                 NetworkStats.Entry entry = new NetworkStats.Entry();
11939                 final int size = delta.size();
11940                 for (int i = 0; i < size; i++) {
11941                     entry = delta.getValues(i, entry);
11942 
11943                     if (DEBUG_ENERGY) {
11944                         Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
11945                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11946                                 + " txPackets=" + entry.txPackets);
11947                     }
11948 
11949                     if (entry.rxBytes == 0 && entry.txBytes == 0) {
11950                         // Skip the lookup below since there is no work to do.
11951                         continue;
11952                     }
11953 
11954                     final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
11955                     if (entry.rxBytes != 0) {
11956                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
11957                                 entry.rxPackets);
11958                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11959                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
11960                                     entry.rxPackets);
11961                         }
11962                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11963                                 entry.rxBytes);
11964                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11965                                 entry.rxPackets);
11966 
11967                         // TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
11968                         rxPackets.put(u.getUid(), entry.rxPackets);
11969 
11970                         // Sum the total number of packets so that the Rx Power can
11971                         // be evenly distributed amongst the apps.
11972                         totalRxPackets += entry.rxPackets;
11973                     }
11974 
11975                     if (entry.txBytes != 0) {
11976                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
11977                                 entry.txPackets);
11978                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11979                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
11980                                     entry.txPackets);
11981                         }
11982                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11983                                 entry.txBytes);
11984                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11985                                 entry.txPackets);
11986 
11987                         // TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
11988                         txPackets.put(u.getUid(), entry.txPackets);
11989 
11990                         // Sum the total number of packets so that the Tx Power can
11991                         // be evenly distributed amongst the apps.
11992                         totalTxPackets += entry.txPackets;
11993                     }
11994 
11995                     // Calculate consumed energy for this uid. Only do so if WifiReporting isn't
11996                     // enabled (if it is, we'll do it later instead using info).
11997                     if (uidEstimatedConsumptionMah != null && info == null && !mHasWifiReporting) {
11998                         final long uidRunningMs = u.mWifiRunningTimer
11999                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12000                         if (uidRunningMs > 0) u.mWifiRunningTimer.setMark(elapsedRealtimeMs);
12001 
12002                         final long uidScanMs = u.mWifiScanTimer
12003                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12004                         if (uidScanMs > 0) u.mWifiScanTimer.setMark(elapsedRealtimeMs);
12005 
12006                         long uidBatchScanMs = 0;
12007                         for (int bn = 0; bn < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bn++) {
12008                             if (u.mWifiBatchedScanTimer[bn] != null) {
12009                                 long bnMs = u.mWifiBatchedScanTimer[bn]
12010                                         .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12011                                 if (bnMs > 0) {
12012                                     u.mWifiBatchedScanTimer[bn].setMark(elapsedRealtimeMs);
12013                                 }
12014                                 uidBatchScanMs += bnMs;
12015                             }
12016                         }
12017 
12018                         uidEstimatedConsumptionMah.add(u.getUid(),
12019                                 mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
12020                                         entry.rxPackets, entry.txPackets,
12021                                         uidRunningMs, uidScanMs, uidBatchScanMs));
12022                     }
12023                 }
12024                 mNetworkStatsPool.release(delta);
12025                 delta = null;
12026             }
12027 
12028             if (info != null) {
12029                 mHasWifiReporting = true;
12030 
12031                 // Measured in mAms
12032                 final long txTimeMs = info.getControllerTxDurationMillis();
12033                 final long rxTimeMs = info.getControllerRxDurationMillis();
12034                 final long scanTimeMs = info.getControllerScanDurationMillis();
12035                 final long idleTimeMs = info.getControllerIdleDurationMillis();
12036                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
12037 
12038                 long leftOverRxTimeMs = rxTimeMs;
12039                 long leftOverTxTimeMs = txTimeMs;
12040 
12041                 if (DEBUG_ENERGY) {
12042                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
12043                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
12044                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
12045                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
12046                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
12047                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
12048                 }
12049 
12050                 long totalWifiLockTimeMs = 0;
12051                 long totalScanTimeMs = 0;
12052 
12053                 // On the first pass, collect some totals so that we can normalize power
12054                 // calculations if we need to.
12055                 final int uidStatsSize = mUidStats.size();
12056                 for (int i = 0; i < uidStatsSize; i++) {
12057                     final Uid uid = mUidStats.valueAt(i);
12058 
12059                     // Sum the total scan power for all apps.
12060                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
12061                             elapsedRealtimeMs * 1000) / 1000;
12062 
12063                     // Sum the total time holding wifi lock for all apps.
12064                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
12065                             elapsedRealtimeMs * 1000) / 1000;
12066                 }
12067 
12068                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
12069                     Slog.d(TAG,
12070                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
12071                                     + rxTimeMs + " ms). Normalizing scan time.");
12072                 }
12073                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
12074                     Slog.d(TAG,
12075                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
12076                                     + txTimeMs + " ms). Normalizing scan time.");
12077                 }
12078 
12079                 // Actually assign and distribute power usage to apps.
12080                 for (int i = 0; i < uidStatsSize; i++) {
12081                     final Uid uid = mUidStats.valueAt(i);
12082 
12083                     final long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
12084                             elapsedRealtimeMs * 1000) / 1000;
12085                     long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
12086                     long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
12087                     if (scanTimeSinceMarkMs > 0) {
12088                         // Set the new mark so that next time we get new data since this point.
12089                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
12090 
12091                         // Our total scan time is more than the reported Tx/Rx time.
12092                         // This is possible because the cost of a scan is approximate.
12093                         // Let's normalize the result so that we evenly blame each app
12094                         // scanning.
12095                         //
12096                         // This means that we may have apps that transmitted/received packets not be
12097                         // blamed for this, but this is fine as scans are relatively more expensive.
12098                         if (totalScanTimeMs > rxTimeMs) {
12099                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
12100                                     totalScanTimeMs;
12101                         }
12102                         if (totalScanTimeMs > txTimeMs) {
12103                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
12104                                     totalScanTimeMs;
12105                         }
12106 
12107                         if (DEBUG_ENERGY) {
12108                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
12109                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
12110                                     + scanTxTimeSinceMarkMs + " ms)");
12111                         }
12112 
12113                         ControllerActivityCounterImpl activityCounter =
12114                                 uid.getOrCreateWifiControllerActivityLocked();
12115                         activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
12116                         activityCounter.getTxTimeCounters()[0].addCountLocked(
12117                                 scanTxTimeSinceMarkMs);
12118                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
12119                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
12120                     }
12121 
12122                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
12123                     // lock.
12124                     long myIdleTimeMs = 0;
12125                     final long wifiLockTimeSinceMarkMs =
12126                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
12127                                     elapsedRealtimeMs * 1000) / 1000;
12128                     if (wifiLockTimeSinceMarkMs > 0) {
12129                         // Set the new mark so that next time we get new data since this point.
12130                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
12131 
12132                         myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) / totalWifiLockTimeMs;
12133                         if (DEBUG_ENERGY) {
12134                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
12135                                     + myIdleTimeMs + " ms");
12136                         }
12137                         uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
12138                                 .addCountLocked(myIdleTimeMs);
12139                     }
12140 
12141                     if (uidEstimatedConsumptionMah != null) {
12142                         double uidEstMah = mWifiPowerCalculator.calcPowerFromControllerDataMah(
12143                                 scanRxTimeSinceMarkMs, scanTxTimeSinceMarkMs, myIdleTimeMs);
12144                         uidEstimatedConsumptionMah.add(uid.getUid(), uidEstMah);
12145                     }
12146                 }
12147 
12148                 if (DEBUG_ENERGY) {
12149                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
12150                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
12151                 }
12152 
12153                 // Distribute the remaining Tx power appropriately between all apps that transmitted
12154                 // packets.
12155                 for (int i = 0; i < txPackets.size(); i++) {
12156                     final Uid uid = getUidStatsLocked(txPackets.keyAt(i),
12157                             elapsedRealtimeMs, uptimeMs);
12158                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
12159                             / totalTxPackets;
12160                     if (DEBUG_ENERGY) {
12161                         Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
12162                     }
12163                     uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
12164                             .addCountLocked(myTxTimeMs);
12165                     if (uidEstimatedConsumptionMah != null) {
12166                         uidEstimatedConsumptionMah.add(uid.getUid(),
12167                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
12168                                         0, myTxTimeMs, 0));
12169                     }
12170                 }
12171 
12172                 // Distribute the remaining Rx power appropriately between all apps that received
12173                 // packets.
12174                 for (int i = 0; i < rxPackets.size(); i++) {
12175                     final Uid uid = getUidStatsLocked(rxPackets.keyAt(i),
12176                             elapsedRealtimeMs, uptimeMs);
12177                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
12178                             / totalRxPackets;
12179                     if (DEBUG_ENERGY) {
12180                         Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
12181                     }
12182                     uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
12183                             .addCountLocked(myRxTimeMs);
12184                     if (uidEstimatedConsumptionMah != null) {
12185                         uidEstimatedConsumptionMah.add(uid.getUid(),
12186                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
12187                                         myRxTimeMs, 0, 0));
12188                     }
12189                 }
12190 
12191                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
12192 
12193 
12194                 // Update WiFi controller stats.
12195                 mWifiActivity.getRxTimeCounter().addCountLocked(
12196                         info.getControllerRxDurationMillis());
12197                 mWifiActivity.getTxTimeCounters()[0].addCountLocked(
12198                         info.getControllerTxDurationMillis());
12199                 mWifiActivity.getScanTimeCounter().addCountLocked(
12200                         info.getControllerScanDurationMillis());
12201                 mWifiActivity.getIdleTimeCounter().addCountLocked(
12202                         info.getControllerIdleDurationMillis());
12203 
12204                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12205                 final double opVolt = mPowerProfile.getAveragePower(
12206                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12207                 double controllerMaMs = 0;
12208                 if (opVolt != 0) {
12209                     // We store the power drain as mAms.
12210                     controllerMaMs = info.getControllerEnergyUsedMicroJoules() / opVolt;
12211                     mWifiActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
12212                 }
12213                 // Converting uWs to mAms.
12214                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
12215                 long monitoredRailChargeConsumedMaMs =
12216                         (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt);
12217                 mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
12218                         monitoredRailChargeConsumedMaMs);
12219                 mHistoryCur.wifiRailChargeMah +=
12220                         (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
12221                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
12222                 mTmpRailStats.resetWifiTotalEnergyUsed();
12223 
12224                 if (uidEstimatedConsumptionMah != null) {
12225                     totalEstimatedConsumptionMah = Math.max(controllerMaMs / MILLISECONDS_IN_HOUR,
12226                             mWifiPowerCalculator.calcPowerFromControllerDataMah(
12227                                     rxTimeMs, txTimeMs, idleTimeMs));
12228                 }
12229             }
12230 
12231             // Update the MeasuredEnergyStats information.
12232             if (uidEstimatedConsumptionMah != null) {
12233                 mGlobalMeasuredEnergyStats.updateStandardBucket(
12234                         MeasuredEnergyStats.POWER_BUCKET_WIFI, consumedChargeUC);
12235 
12236                 // Now calculate the consumption for each uid, according to its proportional usage.
12237                 if (!mHasWifiReporting) {
12238                     final long globalTimeMs = mGlobalWifiRunningTimer
12239                             .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12240                     mGlobalWifiRunningTimer.setMark(elapsedRealtimeMs);
12241                     totalEstimatedConsumptionMah = mWifiPowerCalculator
12242                             .calcGlobalPowerWithoutControllerDataMah(globalTimeMs);
12243                 }
12244                 distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_WIFI,
12245                         consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah);
12246             }
12247         }
12248     }
12249 
12250     private ModemActivityInfo mLastModemActivityInfo = null;
12251 
12252     /**
12253      * Distribute Cell radio energy info and network traffic to apps.
12254      */
noteModemControllerActivity(@ullable final ModemActivityInfo activityInfo, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)12255     public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo,
12256             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
12257         if (DEBUG_ENERGY) {
12258             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
12259         }
12260         ModemActivityInfo deltaInfo = mLastModemActivityInfo == null ? activityInfo
12261                 : mLastModemActivityInfo.getDelta(activityInfo);
12262         mLastModemActivityInfo = activityInfo;
12263 
12264         // Add modem tx power to history.
12265         addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs);
12266 
12267         // Grab a separate lock to acquire the network stats, which may do I/O.
12268         NetworkStats delta = null;
12269         synchronized (mModemNetworkLock) {
12270             final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
12271             if (latestStats != null) {
12272                 delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
12273                         mNetworkStatsPool.acquire());
12274                 mNetworkStatsPool.release(mLastModemNetworkStats);
12275                 mLastModemNetworkStats = latestStats;
12276             }
12277         }
12278 
12279         synchronized (this) {
12280             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12281                 if (delta != null) {
12282                     mNetworkStatsPool.release(delta);
12283                 }
12284                 return;
12285             }
12286 
12287             final SparseDoubleArray uidEstimatedConsumptionMah;
12288             if (consumedChargeUC > 0 && mMobileRadioPowerCalculator != null
12289                     && mGlobalMeasuredEnergyStats != null) {
12290                 mGlobalMeasuredEnergyStats.updateStandardBucket(
12291                         MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC);
12292                 uidEstimatedConsumptionMah = new SparseDoubleArray();
12293             } else {
12294                 uidEstimatedConsumptionMah = null;
12295             }
12296 
12297             if (deltaInfo != null) {
12298                 mHasModemReporting = true;
12299                 mModemActivity.getIdleTimeCounter().addCountLocked(
12300                         deltaInfo.getIdleTimeMillis());
12301                 mModemActivity.getSleepTimeCounter().addCountLocked(
12302                         deltaInfo.getSleepTimeMillis());
12303                 mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getReceiveTimeMillis());
12304                 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels(); lvl++) {
12305                     mModemActivity.getTxTimeCounters()[lvl]
12306                         .addCountLocked(deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl));
12307                 }
12308 
12309                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12310                 final double opVolt = mPowerProfile.getAveragePower(
12311                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12312                 if (opVolt != 0) {
12313                     double energyUsed =
12314                             deltaInfo.getSleepTimeMillis() *
12315                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
12316                             + deltaInfo.getIdleTimeMillis() *
12317                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
12318                             + deltaInfo.getReceiveTimeMillis() *
12319                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
12320                     for (int i = 0; i < Math.min(ModemActivityInfo.getNumTxPowerLevels(),
12321                             CellSignalStrength.getNumSignalStrengthLevels()); i++) {
12322                         energyUsed += deltaInfo.getTransmitDurationMillisAtPowerLevel(i)
12323                                 * mPowerProfile.getAveragePower(
12324                                         PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
12325                     }
12326 
12327                     // We store the power drain as mAms.
12328                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
12329                     // Converting uWs to mAms.
12330                     // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
12331                     long monitoredRailChargeConsumedMaMs =
12332                             (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
12333                     mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
12334                             monitoredRailChargeConsumedMaMs);
12335                     mHistoryCur.modemRailChargeMah +=
12336                             (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
12337                     addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
12338                     mTmpRailStats.resetCellularTotalEnergyUsed();
12339                 }
12340             }
12341             long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
12342                     elapsedRealtimeMs * 1000);
12343             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
12344 
12345             long totalRxPackets = 0;
12346             long totalTxPackets = 0;
12347             if (delta != null) {
12348                 NetworkStats.Entry entry = new NetworkStats.Entry();
12349                 final int size = delta.size();
12350                 for (int i = 0; i < size; i++) {
12351                     entry = delta.getValues(i, entry);
12352                     if (entry.rxPackets == 0 && entry.txPackets == 0) {
12353                         continue;
12354                     }
12355 
12356                     if (DEBUG_ENERGY) {
12357                         Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
12358                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
12359                                 + " txPackets=" + entry.txPackets);
12360                     }
12361 
12362                     totalRxPackets += entry.rxPackets;
12363                     totalTxPackets += entry.txPackets;
12364 
12365                     final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
12366                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
12367                             entry.rxPackets);
12368                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
12369                             entry.txPackets);
12370                     if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
12371                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
12372                                 entry.rxBytes, entry.rxPackets);
12373                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
12374                                 entry.txBytes, entry.txPackets);
12375                     }
12376 
12377                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
12378                             entry.rxBytes);
12379                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12380                             entry.txBytes);
12381                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
12382                             entry.rxPackets);
12383                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12384                             entry.txPackets);
12385                 }
12386 
12387                 // Now distribute proportional blame to the apps that did networking.
12388                 long totalPackets = totalRxPackets + totalTxPackets;
12389                 if (totalPackets > 0) {
12390                     for (int i = 0; i < size; i++) {
12391                         entry = delta.getValues(i, entry);
12392                         if (entry.rxPackets == 0 && entry.txPackets == 0) {
12393                             continue;
12394                         }
12395 
12396                         final Uid u = getUidStatsLocked(mapUid(entry.uid),
12397                                 elapsedRealtimeMs, uptimeMs);
12398 
12399                         // Distribute total radio active time in to this app.
12400                         final long appPackets = entry.rxPackets + entry.txPackets;
12401                         final long appRadioTimeUs =
12402                                 (totalAppRadioTimeUs * appPackets) / totalPackets;
12403                         u.noteMobileRadioActiveTimeLocked(appRadioTimeUs);
12404 
12405                         // Distribute measured mobile radio charge consumption based on app radio
12406                         // active time
12407                         if (uidEstimatedConsumptionMah != null) {
12408                             uidEstimatedConsumptionMah.add(u.getUid(),
12409                                     mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12410                                             appRadioTimeUs / 1000));
12411                         }
12412 
12413                         // Remove this app from the totals, so that we don't lose any time
12414                         // due to rounding.
12415                         totalAppRadioTimeUs -= appRadioTimeUs;
12416                         totalPackets -= appPackets;
12417 
12418                         if (deltaInfo != null) {
12419                             ControllerActivityCounterImpl activityCounter =
12420                                     u.getOrCreateModemControllerActivityLocked();
12421                             if (totalRxPackets > 0 && entry.rxPackets > 0) {
12422                                 final long rxMs = (entry.rxPackets
12423                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
12424                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
12425                             }
12426 
12427                             if (totalTxPackets > 0 && entry.txPackets > 0) {
12428                                 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels();
12429                                         lvl++) {
12430                                     long txMs = entry.txPackets
12431                                             * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
12432                                     txMs /= totalTxPackets;
12433                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
12434                                 }
12435                             }
12436                         }
12437                     }
12438                 }
12439 
12440                 if (totalAppRadioTimeUs > 0) {
12441                     // Whoops, there is some radio time we can't blame on an app!
12442                     mMobileRadioActiveUnknownTime.addCountLocked(totalAppRadioTimeUs);
12443                     mMobileRadioActiveUnknownCount.addCountLocked(1);
12444                 }
12445 
12446 
12447                 // Update the MeasuredEnergyStats information.
12448                 if (uidEstimatedConsumptionMah != null) {
12449                     double totalEstimatedConsumptionMah = 0.0;
12450 
12451                     // Estimate total active radio power consumption since last mark.
12452                     final long totalRadioTimeMs = mMobileRadioActiveTimer.getTimeSinceMarkLocked(
12453                             elapsedRealtimeMs * 1000) / 1000;
12454                     mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
12455                     totalEstimatedConsumptionMah +=
12456                             mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12457                                     totalRadioTimeMs);
12458 
12459                     // Estimate idle power consumption at each signal strength level
12460                     final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
12461                     for (int strengthLevel = 0; strengthLevel < numSignalStrengthLevels;
12462                             strengthLevel++) {
12463                         final long strengthLevelDurationMs =
12464                                 mPhoneSignalStrengthsTimer[strengthLevel].getTimeSinceMarkLocked(
12465                                         elapsedRealtimeMs * 1000) / 1000;
12466                         mPhoneSignalStrengthsTimer[strengthLevel].setMark(elapsedRealtimeMs);
12467 
12468                         totalEstimatedConsumptionMah +=
12469                                 mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
12470                                         strengthLevelDurationMs, strengthLevel);
12471                     }
12472 
12473                     // Estimate total active radio power consumption since last mark.
12474                     final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
12475                             elapsedRealtimeMs * 1000) / 1000;
12476                     mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs);
12477                     totalEstimatedConsumptionMah +=
12478                             mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
12479 
12480                     distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO,
12481                             consumedChargeUC, uidEstimatedConsumptionMah,
12482                             totalEstimatedConsumptionMah);
12483                 }
12484 
12485                 mNetworkStatsPool.release(delta);
12486                 delta = null;
12487             }
12488         }
12489     }
12490 
12491     /**
12492      * Add modem tx power to history
12493      * Device is said to be in high cellular transmit power when it has spent most of the transmit
12494      * time at the highest power level.
12495      * @param activityInfo
12496      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo, long elapsedRealtimeMs, long uptimeMs)12497     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo,
12498             long elapsedRealtimeMs, long uptimeMs) {
12499         if (activityInfo == null) {
12500             return;
12501         }
12502         int levelMaxTimeSpent = 0;
12503         for (int i = 1; i < ModemActivityInfo.getNumTxPowerLevels(); i++) {
12504             if (activityInfo.getTransmitDurationMillisAtPowerLevel(i)
12505                     > activityInfo.getTransmitDurationMillisAtPowerLevel(levelMaxTimeSpent)) {
12506                 levelMaxTimeSpent = i;
12507             }
12508         }
12509         if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) {
12510             mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
12511             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
12512         }
12513     }
12514 
12515     private final class BluetoothActivityInfoCache {
12516         long idleTimeMs;
12517         long rxTimeMs;
12518         long txTimeMs;
12519         long energy;
12520 
12521         SparseLongArray uidRxBytes = new SparseLongArray();
12522         SparseLongArray uidTxBytes = new SparseLongArray();
12523 
set(BluetoothActivityEnergyInfo info)12524         void set(BluetoothActivityEnergyInfo info) {
12525             idleTimeMs = info.getControllerIdleTimeMillis();
12526             rxTimeMs = info.getControllerRxTimeMillis();
12527             txTimeMs = info.getControllerTxTimeMillis();
12528             energy = info.getControllerEnergyUsed();
12529             if (info.getUidTraffic() != null) {
12530                 for (UidTraffic traffic : info.getUidTraffic()) {
12531                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
12532                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
12533                 }
12534             }
12535         }
12536 
reset()12537         void reset() {
12538             idleTimeMs = 0;
12539             rxTimeMs = 0;
12540             txTimeMs = 0;
12541             energy = 0;
12542             uidRxBytes.clear();
12543             uidTxBytes.clear();
12544         }
12545     }
12546 
12547     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
12548             = new BluetoothActivityInfoCache();
12549 
12550     /**
12551      * Distribute Bluetooth energy info and network traffic to apps.
12552      *
12553      * @param info The accumulated energy information from the bluetooth controller.
12554      */
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)12555     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
12556             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
12557         if (DEBUG_ENERGY) {
12558             Slog.d(TAG, "Updating bluetooth stats: " + info);
12559         }
12560 
12561         if (info == null) {
12562             return;
12563         }
12564         if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12565             mLastBluetoothActivityInfo.set(info);
12566             return;
12567         }
12568 
12569         mHasBluetoothReporting = true;
12570 
12571         if (info.getControllerRxTimeMillis() < mLastBluetoothActivityInfo.rxTimeMs
12572                 || info.getControllerTxTimeMillis() < mLastBluetoothActivityInfo.txTimeMs
12573                 || info.getControllerIdleTimeMillis() < mLastBluetoothActivityInfo.idleTimeMs
12574                 || info.getControllerEnergyUsed() < mLastBluetoothActivityInfo.energy) {
12575             // A drop in accumulated Bluetooth stats is a sign of a Bluetooth crash.
12576             // Reset the preserved previous snapshot in order to restart accumulating deltas.
12577             mLastBluetoothActivityInfo.reset();
12578         }
12579 
12580         final long rxTimeMs =
12581                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
12582         final long txTimeMs =
12583                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
12584         final long idleTimeMs =
12585                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
12586 
12587         if (DEBUG_ENERGY) {
12588             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
12589             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
12590             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
12591             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
12592         }
12593 
12594         final SparseDoubleArray uidEstimatedConsumptionMah =
12595                 (mGlobalMeasuredEnergyStats != null
12596                         && mBluetoothPowerCalculator != null && consumedChargeUC > 0) ?
12597                         new SparseDoubleArray() : null;
12598 
12599         long totalScanTimeMs = 0;
12600 
12601         final int uidCount = mUidStats.size();
12602         for (int i = 0; i < uidCount; i++) {
12603             final Uid u = mUidStats.valueAt(i);
12604             if (u.mBluetoothScanTimer == null) {
12605                 continue;
12606             }
12607 
12608             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
12609                     elapsedRealtimeMs * 1000) / 1000;
12610         }
12611 
12612         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
12613         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
12614 
12615         if (DEBUG_ENERGY) {
12616             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
12617                     + " TX=" + normalizeScanTxTime);
12618         }
12619 
12620         long leftOverRxTimeMs = rxTimeMs;
12621         long leftOverTxTimeMs = txTimeMs;
12622 
12623         for (int i = 0; i < uidCount; i++) {
12624             final Uid u = mUidStats.valueAt(i);
12625             if (u.mBluetoothScanTimer == null) {
12626                 continue;
12627             }
12628 
12629             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
12630                     elapsedRealtimeMs * 1000) / 1000;
12631             if (scanTimeSinceMarkMs > 0) {
12632                 // Set the new mark so that next time we get new data since this point.
12633                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
12634 
12635                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
12636                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
12637 
12638                 if (normalizeScanRxTime) {
12639                     // Scan time is longer than the total rx time in the controller,
12640                     // so distribute the scan time proportionately. This means regular traffic
12641                     // will not blamed, but scans are more expensive anyways.
12642                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
12643                 }
12644 
12645                 if (normalizeScanTxTime) {
12646                     // Scan time is longer than the total tx time in the controller,
12647                     // so distribute the scan time proportionately. This means regular traffic
12648                     // will not blamed, but scans are more expensive anyways.
12649                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
12650                 }
12651 
12652                 final ControllerActivityCounterImpl counter =
12653                         u.getOrCreateBluetoothControllerActivityLocked();
12654                 counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
12655                 counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
12656 
12657                 if (uidEstimatedConsumptionMah != null) {
12658                     uidEstimatedConsumptionMah.add(u.getUid(),
12659                             mBluetoothPowerCalculator.calculatePowerMah(
12660                                     scanTimeRxSinceMarkMs, scanTimeTxSinceMarkMs, 0));
12661                 }
12662 
12663                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
12664                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
12665             }
12666         }
12667 
12668         if (DEBUG_ENERGY) {
12669             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
12670                     + leftOverTxTimeMs);
12671         }
12672 
12673         //
12674         // Now distribute blame to apps that did bluetooth traffic.
12675         //
12676 
12677         long totalTxBytes = 0;
12678         long totalRxBytes = 0;
12679 
12680         final UidTraffic[] uidTraffic = info.getUidTraffic();
12681         final int numUids = uidTraffic != null ? uidTraffic.length : 0;
12682         for (int i = 0; i < numUids; i++) {
12683             final UidTraffic traffic = uidTraffic[i];
12684             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
12685                     traffic.getUid());
12686             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
12687                     traffic.getUid());
12688 
12689             // Add to the global counters.
12690             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
12691             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
12692 
12693             // Add to the UID counters.
12694             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()), elapsedRealtimeMs, uptimeMs);
12695             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
12696             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
12697 
12698             // Calculate the total traffic.
12699             totalRxBytes += rxBytes;
12700             totalTxBytes += txBytes;
12701         }
12702 
12703         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
12704                 || leftOverTxTimeMs != 0)) {
12705             for (int i = 0; i < numUids; i++) {
12706                 final UidTraffic traffic = uidTraffic[i];
12707                 final int uid = traffic.getUid();
12708                 final long rxBytes =
12709                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
12710                 final long txBytes =
12711                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
12712 
12713                 final Uid u = getUidStatsLocked(mapUid(uid), elapsedRealtimeMs, uptimeMs);
12714                 final ControllerActivityCounterImpl counter =
12715                         u.getOrCreateBluetoothControllerActivityLocked();
12716 
12717                 if (totalRxBytes > 0 && rxBytes > 0) {
12718                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
12719                     if (DEBUG_ENERGY) {
12720                         Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
12721                     }
12722                     counter.getRxTimeCounter().addCountLocked(timeRxMs);
12723 
12724                     if (uidEstimatedConsumptionMah != null) {
12725                         uidEstimatedConsumptionMah.add(u.getUid(),
12726                                 mBluetoothPowerCalculator.calculatePowerMah(timeRxMs, 0, 0));
12727                     }
12728                 }
12729 
12730                 if (totalTxBytes > 0 && txBytes > 0) {
12731                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
12732                     if (DEBUG_ENERGY) {
12733                         Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
12734                     }
12735                     counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
12736 
12737                     if (uidEstimatedConsumptionMah != null) {
12738                         uidEstimatedConsumptionMah.add(u.getUid(),
12739                                 mBluetoothPowerCalculator.calculatePowerMah(0, timeTxMs, 0));
12740                     }
12741                 }
12742             }
12743         }
12744 
12745         mBluetoothActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
12746         mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(txTimeMs);
12747         mBluetoothActivity.getIdleTimeCounter().addCountLocked(idleTimeMs);
12748 
12749         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12750         final double opVolt = mPowerProfile.getAveragePower(
12751                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12752         double controllerMaMs = 0;
12753         if (opVolt != 0) {
12754             controllerMaMs = (info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
12755                     / opVolt;
12756             // We store the power drain as mAms.
12757             mBluetoothActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
12758         }
12759 
12760         // Update the MeasuredEnergyStats information.
12761         if (uidEstimatedConsumptionMah != null) {
12762             mGlobalMeasuredEnergyStats.updateStandardBucket(
12763                     MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH, consumedChargeUC);
12764 
12765             double totalEstimatedMah
12766                     = mBluetoothPowerCalculator.calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
12767             totalEstimatedMah = Math.max(totalEstimatedMah, controllerMaMs / MILLISECONDS_IN_HOUR);
12768             distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH,
12769                     consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedMah);
12770         }
12771 
12772         mLastBluetoothActivityInfo.set(info);
12773     }
12774     /**
12775      * Read Resource Power Manager (RPM) state and voter times.
12776      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
12777      * instead of fetching it anew.
12778      *
12779      * Note: This should be called without synchronizing this BatteryStatsImpl object
12780      */
fillLowPowerStats()12781     public void fillLowPowerStats() {
12782         if (mPlatformIdleStateCallback == null) return;
12783 
12784         RpmStats rpmStats = new RpmStats();
12785         long now = SystemClock.elapsedRealtime();
12786         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
12787             mPlatformIdleStateCallback.fillLowPowerStats(rpmStats);
12788             synchronized (this) {
12789                 mTmpRpmStats = rpmStats;
12790                 mLastRpmStatsUpdateTimeMs = now;
12791             }
12792         }
12793     }
12794 
12795     /**
12796      * Record Resource Power Manager (RPM) state and voter times.
12797      * TODO(b/185252376): Remove this logging. PowerStatsService logs the same data more
12798      * efficiently.
12799      */
updateRpmStatsLocked(long elapsedRealtimeUs)12800     public void updateRpmStatsLocked(long elapsedRealtimeUs) {
12801         if (mTmpRpmStats == null) return;
12802 
12803         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
12804                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
12805 
12806             // Update values for this platform state.
12807             final String pName = pstate.getKey();
12808             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
12809             final int pCount = pstate.getValue().mCount;
12810             getRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
12811             if (SCREEN_OFF_RPM_STATS_ENABLED) {
12812                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
12813             }
12814 
12815             // Update values for each voter of this platform state.
12816             for (Map.Entry<String, RpmStats.PowerStateElement> voter
12817                     : pstate.getValue().mVoters.entrySet()) {
12818                 final String vName = pName + "." + voter.getKey();
12819                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
12820                 final int vCount = voter.getValue().mCount;
12821                 getRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
12822                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
12823                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
12824                 }
12825             }
12826         }
12827 
12828         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
12829                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
12830 
12831             final String subsysName = subsys.getKey();
12832             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
12833                     : subsys.getValue().mStates.entrySet()) {
12834                 final String name = subsysName + "." + sstate.getKey();
12835                 final long timeUs = sstate.getValue().mTimeMs * 1000;
12836                 final int count = sstate.getValue().mCount;
12837                 getRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
12838                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
12839                     getScreenOffRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
12840                 }
12841             }
12842         }
12843     }
12844 
12845     /**
12846      * Accumulate Cpu charge consumption and distribute it to the correct state and the apps.
12847      * Only call if device is on battery.
12848      *
12849      * @param clusterChargeUC amount of charge (microcoulombs) consumed by each Cpu Cluster
12850      * @param accumulator collection of calculated uid cpu power consumption to smear
12851      *                    clusterChargeUC against.
12852      */
12853     @GuardedBy("this")
updateCpuMeasuredEnergyStatsLocked(@onNull long[] clusterChargeUC, @NonNull CpuDeltaPowerAccumulator accumulator)12854     private void updateCpuMeasuredEnergyStatsLocked(@NonNull long[] clusterChargeUC,
12855             @NonNull CpuDeltaPowerAccumulator accumulator) {
12856         if (DEBUG_ENERGY) {
12857             Slog.d(TAG,
12858                     "Updating cpu cluster stats: " + clusterChargeUC.toString());
12859         }
12860         if (mGlobalMeasuredEnergyStats == null) {
12861             return;
12862         }
12863 
12864         final int numClusters = clusterChargeUC.length;
12865         long totalCpuChargeUC = 0;
12866         for (int i = 0; i < numClusters; i++) {
12867             totalCpuChargeUC += clusterChargeUC[i];
12868         }
12869         if (totalCpuChargeUC <= 0) return;
12870 
12871         mGlobalMeasuredEnergyStats.updateStandardBucket(MeasuredEnergyStats.POWER_BUCKET_CPU,
12872                 totalCpuChargeUC);
12873 
12874         // Calculate the measured microcoulombs/calculated milliamp-hour charge ratio for each
12875         // cluster to normalize  each uid's estimated power usage against actual power usage for
12876         // a given cluster.
12877         final double[] clusterChargeRatio = new double[numClusters];
12878         for (int cluster = 0; cluster < numClusters; cluster++) {
12879 
12880             final double totalClusterChargeMah = accumulator.totalClusterChargesMah[cluster];
12881             if (totalClusterChargeMah <= 0.0) {
12882                 // This cluster did not have any work on it, since last update.
12883                 // Avoid dividing by zero.
12884                 clusterChargeRatio[cluster] = 0.0;
12885             } else {
12886                 clusterChargeRatio[cluster] =
12887                         clusterChargeUC[cluster] / accumulator.totalClusterChargesMah[cluster];
12888             }
12889         }
12890 
12891         // Assign and distribute power usage to apps based on their calculated cpu cluster charge.
12892         final long uidChargeArraySize = accumulator.perUidCpuClusterChargesMah.size();
12893         for (int i = 0; i < uidChargeArraySize; i++) {
12894             final Uid uid = accumulator.perUidCpuClusterChargesMah.keyAt(i);
12895             final double[] uidClusterChargesMah = accumulator.perUidCpuClusterChargesMah.valueAt(i);
12896 
12897             // Iterate each cpu cluster and sum the proportional measured cpu cluster charge to
12898             // get the total cpu charge consumed by a uid.
12899             long uidCpuChargeUC = 0;
12900             for (int cluster = 0; cluster < numClusters; cluster++) {
12901                 final double uidClusterChargeMah = uidClusterChargesMah[cluster];
12902 
12903                 // Proportionally allocate the measured cpu cluster charge to a uid using the
12904                 // measured charge/calculated charge ratio. Add 0.5 to round the proportional
12905                 // charge double to the nearest long value.
12906                 final long uidClusterChargeUC =
12907                         (long) (uidClusterChargeMah * clusterChargeRatio[cluster]
12908                                 + 0.5);
12909 
12910                 uidCpuChargeUC += uidClusterChargeUC;
12911             }
12912 
12913             if (uidCpuChargeUC < 0) {
12914                 Slog.wtf(TAG,
12915                         "Unexpected proportional measured charge (" + uidCpuChargeUC + ") for uid "
12916                                 + uid.mUid);
12917                 continue;
12918             }
12919 
12920             uid.addChargeToStandardBucketLocked(uidCpuChargeUC,
12921                     MeasuredEnergyStats.POWER_BUCKET_CPU);
12922         }
12923     }
12924 
12925     /**
12926      * Accumulate Display charge consumption and distribute it to the correct state and the apps.
12927      *
12928      * NOTE: The algorithm used makes the strong assumption that app foreground activity time
12929      * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported).
12930      * To the extent that those assumptions are violated, the algorithm will err.
12931      *
12932      * @param chargesUC amount of charge (microcoulombs) used by each Display since this was last
12933      *                 called.
12934      * @param screenStates each screen state at the time this data collection was scheduled
12935      */
12936     @GuardedBy("this")
updateDisplayMeasuredEnergyStatsLocked(long[] chargesUC, int[] screenStates, long elapsedRealtimeMs)12937     public void updateDisplayMeasuredEnergyStatsLocked(long[] chargesUC, int[] screenStates,
12938             long elapsedRealtimeMs) {
12939         if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + Arrays.toString(chargesUC));
12940         if (mGlobalMeasuredEnergyStats == null) {
12941             return;
12942         }
12943 
12944         final int numDisplays;
12945         if (mPerDisplayBatteryStats.length == screenStates.length) {
12946             numDisplays = screenStates.length;
12947         } else {
12948             // if this point is reached, it will be reached every display state change.
12949             // Rate limit the wtf logging to once every 100 display updates.
12950             if (mDisplayMismatchWtfCount++ % 100 == 0) {
12951                 Slog.wtf(TAG, "Mismatch between PowerProfile reported display count ("
12952                         + mPerDisplayBatteryStats.length
12953                         + ") and PowerStatsHal reported display count (" + screenStates.length
12954                         + ")");
12955             }
12956             // Keep the show going, use the shorter of the two.
12957             numDisplays = mPerDisplayBatteryStats.length < screenStates.length
12958                     ? mPerDisplayBatteryStats.length : screenStates.length;
12959         }
12960 
12961         final int[] oldScreenStates = new int[numDisplays];
12962         for (int i = 0; i < numDisplays; i++) {
12963             final int screenState = screenStates[i];
12964             oldScreenStates[i] = mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement;
12965             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
12966         }
12967 
12968         if (!mOnBatteryInternal) {
12969             // There's nothing further to update.
12970             return;
12971         }
12972         if (mIgnoreNextExternalStats) {
12973             // Although under ordinary resets we won't get here, and typically a new sync will
12974             // happen right after the reset, strictly speaking we need to set all mark times to now.
12975             final int uidStatsSize = mUidStats.size();
12976             for (int i = 0; i < uidStatsSize; i++) {
12977                 final Uid uid = mUidStats.valueAt(i);
12978                 uid.markProcessForegroundTimeUs(elapsedRealtimeMs, false);
12979             }
12980             return;
12981         }
12982 
12983         long totalScreenOnChargeUC = 0;
12984         for (int i = 0; i < numDisplays; i++) {
12985             final long chargeUC = chargesUC[i];
12986             if (chargeUC <= 0) {
12987                 // There's nothing further to update.
12988                 continue;
12989             }
12990 
12991             final @StandardPowerBucket int powerBucket =
12992                     MeasuredEnergyStats.getDisplayPowerBucket(oldScreenStates[i]);
12993             mGlobalMeasuredEnergyStats.updateStandardBucket(powerBucket, chargeUC);
12994             if (powerBucket == MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON) {
12995                 totalScreenOnChargeUC += chargeUC;
12996             }
12997         }
12998 
12999         // Now we blame individual apps, but only if the display was ON.
13000         if (totalScreenOnChargeUC <= 0) {
13001             return;
13002         }
13003         // TODO(b/175726779): Consider unifying the code with the non-rail display power blaming.
13004 
13005         // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is
13006         // 'double counted' and will simply exceed the realtime that elapsed.
13007         // TODO(b/175726779): collect per display uid visibility for display power attribution.
13008 
13009         // Collect total time since mark so that we can normalize power.
13010         final SparseDoubleArray fgTimeUsArray = new SparseDoubleArray();
13011         final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
13012         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
13013         final int uidStatsSize = mUidStats.size();
13014         for (int i = 0; i < uidStatsSize; i++) {
13015             final Uid uid = mUidStats.valueAt(i);
13016             final long fgTimeUs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true);
13017             if (fgTimeUs == 0) continue;
13018             fgTimeUsArray.put(uid.getUid(), (double) fgTimeUs);
13019         }
13020         distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON,
13021                 totalScreenOnChargeUC, fgTimeUsArray, 0);
13022     }
13023 
13024     /**
13025      * Accumulate GNSS charge consumption and distribute it to the correct state and the apps.
13026      *
13027      * @param chargeUC amount of charge (microcoulombs) used by GNSS since this was last called.
13028      */
13029     @GuardedBy("this")
13030     public void updateGnssMeasuredEnergyStatsLocked(long chargeUC, long elapsedRealtimeMs) {
13031         if (DEBUG_ENERGY) Slog.d(TAG, "Updating gnss stats: " + chargeUC);
13032         if (mGlobalMeasuredEnergyStats == null) {
13033             return;
13034         }
13035 
13036         if (!mOnBatteryInternal || chargeUC <= 0) {
13037             // There's nothing further to update.
13038             return;
13039         }
13040         if (mIgnoreNextExternalStats) {
13041             // Although under ordinary resets we won't get here, and typically a new sync will
13042             // happen right after the reset, strictly speaking we need to set all mark times to now.
13043             final int uidStatsSize = mUidStats.size();
13044             for (int i = 0; i < uidStatsSize; i++) {
13045                 final Uid uid = mUidStats.valueAt(i);
13046                 uid.markGnssTimeUs(elapsedRealtimeMs);
13047             }
13048             return;
13049         }
13050 
13051         mGlobalMeasuredEnergyStats.updateStandardBucket(MeasuredEnergyStats.POWER_BUCKET_GNSS,
13052                 chargeUC);
13053 
13054         // Collect the per uid time since mark so that we can normalize power.
13055         final SparseDoubleArray gnssTimeUsArray = new SparseDoubleArray();
13056         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
13057         final int uidStatsSize = mUidStats.size();
13058         for (int i = 0; i < uidStatsSize; i++) {
13059             final Uid uid = mUidStats.valueAt(i);
13060             final long gnssTimeUs = uid.markGnssTimeUs(elapsedRealtimeMs);
13061             if (gnssTimeUs == 0) continue;
13062             gnssTimeUsArray.put(uid.getUid(), (double) gnssTimeUs);
13063         }
13064         distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_GNSS, chargeUC,
13065                 gnssTimeUsArray, 0);
13066     }
13067 
13068     /**
13069      * Accumulate Custom power bucket charge, globally and for each app.
13070      *
13071      * @param totalChargeUC charge (microcoulombs) used for this bucket since this was last called.
13072      * @param uidCharges map of uid->charge (microcoulombs) for this bucket since last called.
13073      *                    Data inside uidCharges will not be modified (treated immutable).
13074      *                    Uids not already known to BatteryStats will be ignored.
13075      */
13076     public void updateCustomMeasuredEnergyStatsLocked(int customPowerBucket,
13077             long totalChargeUC, @Nullable SparseLongArray uidCharges) {
13078         if (DEBUG_ENERGY) {
13079             Slog.d(TAG, "Updating attributed measured charge stats for custom bucket "
13080                     + customPowerBucket
13081                     + " with total charge " + totalChargeUC
13082                     + " and uid charges " + String.valueOf(uidCharges));
13083         }
13084         if (mGlobalMeasuredEnergyStats == null) return;
13085         if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalChargeUC <= 0) return;
13086 
13087         mGlobalMeasuredEnergyStats.updateCustomBucket(customPowerBucket, totalChargeUC);
13088 
13089         if (uidCharges == null) return;
13090         final int numUids = uidCharges.size();
13091         for (int i = 0; i < numUids; i++) {
13092             final int uidInt = mapUid(uidCharges.keyAt(i));
13093             final long uidChargeUC = uidCharges.valueAt(i);
13094             if (uidChargeUC == 0) continue;
13095             final Uid uidObj = getAvailableUidStatsLocked(uidInt);
13096             if (uidObj != null) {
13097                 uidObj.addChargeToCustomBucketLocked(uidChargeUC, customPowerBucket);
13098             } else {
13099                 // Ignore any uid not already known to BatteryStats, rather than creating a new Uid.
13100                 // Otherwise we could end up reviving dead Uids. Note that the CPU data is updated
13101                 // first, so any uid that has used any CPU should already be known to BatteryStats.
13102                 // Recently removed uids (especially common for isolated uids) can reach this path
13103                 // and are ignored.
13104                 if (!Process.isIsolated(uidInt)) {
13105                     Slog.w(TAG, "Received measured charge " + totalChargeUC + " for custom bucket "
13106                             + customPowerBucket + " for non-existent uid " + uidInt);
13107                 }
13108             }
13109         }
13110     }
13111 
13112     /**
13113      * Attributes energy (for the given bucket) to each uid according to the following formula:
13114      *     blamedEnergy[uid] = totalEnergy * ratioNumerators[uid] / ratioDenominator;
13115      * <p>Does nothing if ratioDenominator is 0.
13116      *
13117      * <p>Here, ratioDenominator = max(sumOfAllRatioNumerators, minRatioDenominator),
13118      * so if given minRatioDenominator <= 0, then sumOfAllRatioNumerators will be used implicitly.
13119      *
13120      * <p>Note that ratioNumerators and minRatioDenominator must use the same units, but need not
13121      * use the same units as totalConsumedChargeUC (which must be in microcoulombs).
13122      *
13123      * <p>A consequence of minRatioDenominator is that the sum over all uids might be less than
13124      * totalConsumedChargeUC. This is intentional; the remainder is purposefully unnaccounted rather
13125      * than incorrectly blamed on uids, and implies unknown (non-uid) sources of drain.
13126      *
13127      * <p>All uids in ratioNumerators must exist in mUidStats already.
13128      */
13129     private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket,
13130             long totalConsumedChargeUC, SparseDoubleArray ratioNumerators,
13131             double minRatioDenominator) {
13132 
13133         // If the sum of all app usage was greater than the total, use that instead:
13134         double sumRatioNumerators = 0;
13135         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
13136             sumRatioNumerators += ratioNumerators.valueAt(i);
13137         }
13138         final double ratioDenominator = Math.max(sumRatioNumerators, minRatioDenominator);
13139         if (ratioDenominator <= 0) return;
13140 
13141         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
13142             final Uid uid = getAvailableUidStatsLocked(ratioNumerators.keyAt(i));
13143             final double ratioNumerator = ratioNumerators.valueAt(i);
13144             final long uidActualUC
13145                     = (long) (totalConsumedChargeUC * ratioNumerator / ratioDenominator + 0.5);
13146             uid.addChargeToStandardBucketLocked(uidActualUC, bucket);
13147         }
13148     }
13149 
13150     /**
13151      * Read and record Rail Energy data.
13152      */
13153     public void updateRailStatsLocked() {
13154         if (mMeasuredEnergyRetriever == null || !mTmpRailStats.isRailStatsAvailable()) {
13155             return;
13156         }
13157         mMeasuredEnergyRetriever.fillRailDataStats(mTmpRailStats);
13158     }
13159 
13160     /** Informs that external stats data has been completely flushed. */
13161     public void informThatAllExternalStatsAreFlushed() {
13162         synchronized (this) {
13163             // Any data from the pre-reset era is flushed, so we can henceforth process future data.
13164             mIgnoreNextExternalStats = false;
13165         }
13166     }
13167 
13168     /**
13169      * Read and distribute kernel wake lock use across apps.
13170      */
13171     public void updateKernelWakelocksLocked() {
13172         updateKernelWakelocksLocked(mClocks.elapsedRealtime() * 1000);
13173     }
13174 
13175     /**
13176      * @see #updateKernelWakelocksLocked()
13177      */
13178     public void updateKernelWakelocksLocked(long elapsedRealtimeUs) {
13179         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
13180                 mTmpWakelockStats);
13181         if (wakelockStats == null) {
13182             // Not crashing might make board bringup easier.
13183             Slog.w(TAG, "Couldn't get kernel wake lock stats");
13184             return;
13185         }
13186 
13187         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
13188             String name = ent.getKey();
13189             KernelWakelockStats.Entry kws = ent.getValue();
13190 
13191             SamplingTimer kwlt = mKernelWakelockStats.get(name);
13192             if (kwlt == null) {
13193                 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
13194                 mKernelWakelockStats.put(name, kwlt);
13195             }
13196 
13197             kwlt.update(kws.mTotalTime, kws.mCount, elapsedRealtimeUs);
13198             kwlt.setUpdateVersion(kws.mVersion);
13199         }
13200 
13201         int numWakelocksSetStale = 0;
13202         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
13203         // this time.
13204         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
13205             SamplingTimer st = ent.getValue();
13206             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
13207                 st.endSample(elapsedRealtimeUs);
13208                 numWakelocksSetStale++;
13209             }
13210         }
13211 
13212         // Record whether we've seen a non-zero time (for debugging b/22716723).
13213         if (wakelockStats.isEmpty()) {
13214             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
13215         }
13216 
13217         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
13218             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
13219                     wakelockStats.kernelWakelockVersion);
13220         }
13221     }
13222 
13223     // We use an anonymous class to access these variables,
13224     // so they can't live on the stack or they'd have to be
13225     // final MutableLong objects (more allocations).
13226     // Used in updateCpuTimeLocked().
13227     long mTempTotalCpuUserTimeUs;
13228     long mTempTotalCpuSystemTimeUs;
13229     long[][] mWakeLockAllocationsUs;
13230 
13231     /**
13232      * Reads the newest memory stats from the kernel.
13233      */
13234     public void updateKernelMemoryBandwidthLocked() {
13235         updateKernelMemoryBandwidthLocked(mClocks.elapsedRealtime() * 1000);
13236     }
13237 
13238     public void updateKernelMemoryBandwidthLocked(long elapsedRealtimeUs) {
13239         mKernelMemoryBandwidthStats.updateStats();
13240         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
13241         final int bandwidthEntryCount = bandwidthEntries.size();
13242         int index;
13243         for (int i = 0; i < bandwidthEntryCount; i++) {
13244             SamplingTimer timer;
13245             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
13246                 timer = mKernelMemoryStats.valueAt(index);
13247             } else {
13248                 timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
13249                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
13250             }
13251             timer.update(bandwidthEntries.valueAt(i), 1, elapsedRealtimeUs);
13252             if (DEBUG_MEMORY) {
13253                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
13254                         + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i),
13255                         mKernelMemoryStats.get(
13256                                 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTimeUs,
13257                         mKernelMemoryStats.size()));
13258             }
13259         }
13260     }
13261 
13262     public boolean isOnBatteryLocked() {
13263         return mOnBatteryTimeBase.isRunning();
13264     }
13265 
13266     public boolean isOnBatteryScreenOffLocked() {
13267         return mOnBatteryScreenOffTimeBase.isRunning();
13268     }
13269 
13270     /**
13271      * Object for calculating and accumulating the estimated cpu power used while reading the
13272      * various cpu kernel files.
13273      */
13274     @VisibleForTesting
13275     public static class CpuDeltaPowerAccumulator {
13276         // Keeps track of total charge used per cluster.
13277         public final double[] totalClusterChargesMah;
13278         // Keeps track of charge used per cluster per uid.
13279         public final ArrayMap<Uid, double[]> perUidCpuClusterChargesMah;
13280 
13281         private final CpuPowerCalculator mCalculator;
13282         private Uid mCachedUid = null;
13283         private double[] mUidClusterCache = null;
13284 
13285         CpuDeltaPowerAccumulator(CpuPowerCalculator calculator, int nClusters) {
13286             mCalculator = calculator;
13287             totalClusterChargesMah = new double[nClusters];
13288             perUidCpuClusterChargesMah = new ArrayMap<>();
13289         }
13290 
13291         /** Add per cpu cluster durations to the currently cached uid. */
13292         public void addCpuClusterDurationsMs(Uid uid, long[] durationsMs) {
13293             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
13294             for (int cluster = 0; cluster < durationsMs.length; cluster++) {
13295                 final double estimatedDeltaMah = mCalculator.calculatePerCpuClusterPowerMah(cluster,
13296                         durationsMs[cluster]);
13297                 uidChargesMah[cluster] += estimatedDeltaMah;
13298                 totalClusterChargesMah[cluster] += estimatedDeltaMah;
13299             }
13300         }
13301 
13302         /** Add per speed per cpu cluster durations to the currently cached uid. */
13303         public void addCpuClusterSpeedDurationsMs(Uid uid, int cluster, int speed,
13304                 long durationsMs) {
13305             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
13306             final double estimatedDeltaMah = mCalculator.calculatePerCpuFreqPowerMah(cluster, speed,
13307                     durationsMs);
13308             uidChargesMah[cluster] += estimatedDeltaMah;
13309             totalClusterChargesMah[cluster] += estimatedDeltaMah;
13310         }
13311 
13312         private double[] getOrCreateUidCpuClusterCharges(Uid uid) {
13313             // Repeated additions on the same uid is very likely.
13314             // Skip a lookup if getting the same uid as the last get.
13315             if (uid == mCachedUid) return mUidClusterCache;
13316 
13317             double[] uidChargesMah = perUidCpuClusterChargesMah.get(uid);
13318             if (uidChargesMah == null) {
13319                 uidChargesMah = new double[totalClusterChargesMah.length];
13320                 perUidCpuClusterChargesMah.put(uid, uidChargesMah);
13321             }
13322             mCachedUid = uid;
13323             mUidClusterCache = uidChargesMah;
13324             return uidChargesMah;
13325         }
13326     }
13327 
13328     /**
13329      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
13330      * and we are on battery with screen off, we give more of the cpu time to those apps holding
13331      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
13332      * It's possible this will be invoked after the internal battery/screen states are updated, so
13333      * passing the appropriate battery/screen states to try attribute the cpu times to correct
13334      * buckets.
13335      */
13336     @GuardedBy("this")
13337     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff,
13338             long[] measuredCpuClusterChargeUC) {
13339         if (mPowerProfile == null) {
13340             return;
13341         }
13342 
13343         if (DEBUG_ENERGY_CPU) {
13344             Slog.d(TAG, "!Cpu updating!");
13345         }
13346 
13347         if (mCpuFreqs == null) {
13348             mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
13349         }
13350 
13351         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
13352         // usually holding the wakelock on behalf of an app.
13353         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
13354         ArrayList<StopwatchTimer> partialTimersToConsider = null;
13355         if (onBatteryScreenOff) {
13356             partialTimersToConsider = new ArrayList<>();
13357             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
13358                 final StopwatchTimer timer = mPartialTimers.get(i);
13359                 // Since the collection and blaming of wakelocks can be scheduled to run after
13360                 // some delay, the mPartialTimers list may have new entries. We can't blame
13361                 // the newly added timer for past cpu time, so we only consider timers that
13362                 // were present for one round of collection. Once a timer has gone through
13363                 // a round of collection, its mInList field is set to true.
13364                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
13365                     partialTimersToConsider.add(timer);
13366                 }
13367             }
13368         }
13369         markPartialTimersAsEligible();
13370 
13371         // When the battery is not on, we don't attribute the cpu times to any timers but we still
13372         // need to take the snapshots.
13373         if (!onBattery) {
13374             mCpuUidUserSysTimeReader.readDelta(false, null);
13375             mCpuUidFreqTimeReader.readDelta(false, null);
13376             mNumAllUidCpuTimeReads += 2;
13377             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
13378                 mCpuUidActiveTimeReader.readDelta(false, null);
13379                 mCpuUidClusterTimeReader.readDelta(false, null);
13380                 mNumAllUidCpuTimeReads += 2;
13381             }
13382             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
13383                 mKernelCpuSpeedReaders[cluster].readDelta();
13384             }
13385             mSystemServerCpuThreadReader.readDelta();
13386             return;
13387         }
13388 
13389         mUserInfoProvider.refreshUserIds();
13390         final SparseLongArray updatedUids = mCpuUidFreqTimeReader.perClusterTimesAvailable()
13391                 ? null : new SparseLongArray();
13392 
13393         final CpuDeltaPowerAccumulator powerAccumulator;
13394         if (mGlobalMeasuredEnergyStats != null
13395                 && mGlobalMeasuredEnergyStats.isStandardBucketSupported(
13396                 MeasuredEnergyStats.POWER_BUCKET_CPU) && mCpuPowerCalculator != null) {
13397             if (measuredCpuClusterChargeUC == null) {
13398                 Slog.wtf(TAG,
13399                         "POWER_BUCKET_CPU supported but no measured Cpu Cluster charge reported "
13400                                 + "on updateCpuTimeLocked!");
13401                 powerAccumulator = null;
13402             } else {
13403                 // Cpu Measured Energy is supported, create an object to accumulate the estimated
13404                 // charge consumption since the last cpu update
13405                 final int numClusters = mPowerProfile.getNumCpuClusters();
13406                 powerAccumulator = new CpuDeltaPowerAccumulator(mCpuPowerCalculator, numClusters);
13407             }
13408         } else {
13409             powerAccumulator = null;
13410         }
13411 
13412         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
13413         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
13414         // freqs, so no need to approximate these values.
13415         if (updatedUids != null) {
13416             updateClusterSpeedTimes(updatedUids, onBattery, powerAccumulator);
13417         }
13418         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff,
13419                 powerAccumulator);
13420         mNumAllUidCpuTimeReads += 2;
13421         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
13422             // Cpu Active times do not get any info ony how to attribute measured Cpu Cluster
13423             // charge, so not need to provide the powerAccumulator
13424             readKernelUidCpuActiveTimesLocked(onBattery);
13425             readKernelUidCpuClusterTimesLocked(onBattery, powerAccumulator);
13426             mNumAllUidCpuTimeReads += 2;
13427         }
13428 
13429         updateSystemServerThreadStats();
13430 
13431         if (powerAccumulator != null) {
13432             updateCpuMeasuredEnergyStatsLocked(measuredCpuClusterChargeUC, powerAccumulator);
13433         }
13434     }
13435 
13436     /**
13437      * Estimates the proportion of the System Server CPU activity (per cluster per speed)
13438      * spent on handling incoming binder calls.
13439      */
13440     @VisibleForTesting
13441     public void updateSystemServerThreadStats() {
13442         // There are some simplifying assumptions made in this algorithm
13443         // 1) We assume that if a thread handles incoming binder calls, all of its activity
13444         //    is spent doing that.  Most incoming calls are handled by threads allocated
13445         //    by the native layer in the binder thread pool, so this assumption is reasonable.
13446         // 2) We use the aggregate CPU time spent in different threads as a proxy for the CPU
13447         //    cost. In reality, in multi-core CPUs, the CPU cost may not be linearly
13448         //    affected by additional threads.
13449 
13450         SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes =
13451                     mSystemServerCpuThreadReader.readDelta();
13452         if (systemServiceCpuThreadTimes == null) {
13453             return;
13454         }
13455 
13456         if (mBinderThreadCpuTimesUs == null) {
13457             mBinderThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
13458         }
13459         mBinderThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
13460 
13461         if (DEBUG_BINDER_STATS) {
13462             Slog.d(TAG, "System server threads per CPU cluster (incoming binder threads)");
13463             long binderThreadTimeMs = 0;
13464             int cpuIndex = 0;
13465             final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked(
13466                     BatteryStats.STATS_SINCE_CHARGED);
13467             int index = 0;
13468             int numCpuClusters = mPowerProfile.getNumCpuClusters();
13469             for (int cluster = 0; cluster < numCpuClusters; cluster++) {
13470                 StringBuilder sb = new StringBuilder();
13471                 sb.append("cpu").append(cpuIndex).append(": [");
13472                 int numSpeeds = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
13473                 for (int speed = 0; speed < numSpeeds; speed++) {
13474                     if (speed != 0) {
13475                         sb.append(", ");
13476                     }
13477                     long binderCountMs = binderThreadCpuTimesUs[index] / 1000;
13478                     sb.append(TextUtils.formatSimple("%10d", binderCountMs));
13479 
13480                     binderThreadTimeMs += binderCountMs;
13481                     index++;
13482                 }
13483                 cpuIndex += mPowerProfile.getNumCoresInCpuCluster(cluster);
13484                 Slog.d(TAG, sb.toString());
13485             }
13486         }
13487     }
13488 
13489     /**
13490      * Mark the current partial timers as gone through a collection so that they will be
13491      * considered in the next cpu times distribution to wakelock holders.
13492      */
13493     @VisibleForTesting
13494     public void markPartialTimersAsEligible() {
13495         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
13496             // No difference, so each timer is now considered for the next collection.
13497             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
13498                 mPartialTimers.get(i).mInList = true;
13499             }
13500         } else {
13501             // The lists are different, meaning we added (or removed a timer) since the last
13502             // collection.
13503             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
13504                 mLastPartialTimers.get(i).mInList = false;
13505             }
13506             mLastPartialTimers.clear();
13507 
13508             // Mark the current timers as gone through a collection.
13509             final int numPartialTimers = mPartialTimers.size();
13510             for (int i = 0; i < numPartialTimers; ++i) {
13511                 final StopwatchTimer timer = mPartialTimers.get(i);
13512                 timer.mInList = true;
13513                 mLastPartialTimers.add(timer);
13514             }
13515         }
13516     }
13517 
13518     /**
13519      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
13520      * calculate cpu times spent by each uid at different frequencies. Will also add estimated
13521      * power consumptions, if powerAccumulator data structure is provided.
13522      *
13523      * @param updatedUids  The uids for which times spent at different frequencies are calculated.
13524      * @param onBattery whether or not this is onBattery
13525      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
13526      */
13527     @VisibleForTesting
13528     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery,
13529             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
13530         long totalCpuClustersTimeMs = 0;
13531         // Read the time spent for each cluster at various cpu frequencies.
13532         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
13533         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
13534             clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
13535             if (clusterSpeedTimesMs[cluster] != null) {
13536                 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
13537                     totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
13538                 }
13539             }
13540         }
13541         if (totalCpuClustersTimeMs != 0) {
13542             // We have cpu times per freq aggregated over all uids but we need the times per uid.
13543             // So, we distribute total time spent by an uid to different cpu freqs based on the
13544             // amount of time cpu was running at that freq.
13545             final int updatedUidsCount = updatedUids.size();
13546             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
13547             final long uptimeMs = mClocks.uptimeMillis();
13548             for (int i = 0; i < updatedUidsCount; ++i) {
13549                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i), elapsedRealtimeMs, uptimeMs);
13550                 final long appCpuTimeUs = updatedUids.valueAt(i);
13551                 // Add the cpu speeds to this UID.
13552                 final int numClusters = mPowerProfile.getNumCpuClusters();
13553                 if (u.mCpuClusterSpeedTimesUs == null ||
13554                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
13555                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13556                 }
13557 
13558                 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
13559                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
13560                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
13561                             u.mCpuClusterSpeedTimesUs[cluster].length) {
13562                         u.mCpuClusterSpeedTimesUs[cluster]
13563                                 = new LongSamplingCounter[speedsInCluster];
13564                     }
13565 
13566                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
13567                     for (int speed = 0; speed < speedsInCluster; speed++) {
13568                         if (cpuSpeeds[speed] == null) {
13569                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
13570                         }
13571                         final long deltaSpeedCount = appCpuTimeUs
13572                                 * clusterSpeedTimesMs[cluster][speed]
13573                                 / totalCpuClustersTimeMs;
13574                         cpuSpeeds[speed].addCountLocked(deltaSpeedCount, onBattery);
13575 
13576                         if (powerAccumulator != null) {
13577                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
13578                                     speed, deltaSpeedCount);
13579                         }
13580                     }
13581                 }
13582             }
13583         }
13584     }
13585 
13586     /**
13587      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
13588      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
13589      * wakelock holders.
13590      *
13591      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
13592      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
13593      */
13594     @VisibleForTesting
13595     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
13596             @Nullable SparseLongArray updatedUids, boolean onBattery) {
13597         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
13598         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
13599         final long startTimeMs = mClocks.uptimeMillis();
13600         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
13601 
13602         mCpuUidUserSysTimeReader.readDelta(false, (uid, timesUs) -> {
13603             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
13604 
13605             uid = mapUid(uid);
13606             if (Process.isIsolated(uid)) {
13607                 // This could happen if the isolated uid mapping was removed before that process
13608                 // was actually killed.
13609                 if (DEBUG) Slog.d(TAG, "Got readings for an isolated uid: " + uid);
13610                 return;
13611             }
13612             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
13613                 if (DEBUG) Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
13614                 return;
13615             }
13616             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
13617 
13618             // Accumulate the total system and user time.
13619             mTempTotalCpuUserTimeUs += userTimeUs;
13620             mTempTotalCpuSystemTimeUs += systemTimeUs;
13621 
13622             StringBuilder sb = null;
13623             if (DEBUG_ENERGY_CPU) {
13624                 sb = new StringBuilder();
13625                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
13626                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
13627                 sb.append(" s=");
13628                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
13629                 sb.append("\n");
13630             }
13631 
13632             if (numWakelocks > 0) {
13633                 // We have wakelocks being held, so only give a portion of the
13634                 // time to the process. The rest will be distributed among wakelock
13635                 // holders.
13636                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
13637                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
13638             }
13639 
13640             if (sb != null) {
13641                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
13642                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
13643                 sb.append(" s=");
13644                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
13645                 Slog.d(TAG, sb.toString());
13646             }
13647 
13648             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
13649             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
13650             if (updatedUids != null) {
13651                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
13652             }
13653         });
13654 
13655         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
13656         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
13657             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
13658         }
13659 
13660         if (numWakelocks > 0) {
13661             // Distribute a portion of the total cpu time to wakelock holders.
13662             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
13663             mTempTotalCpuSystemTimeUs =
13664                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
13665 
13666             for (int i = 0; i < numWakelocks; ++i) {
13667                 final StopwatchTimer timer = partialTimers.get(i);
13668                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
13669                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
13670 
13671                 if (DEBUG_ENERGY_CPU) {
13672                     final StringBuilder sb = new StringBuilder();
13673                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
13674                             .append(": u=");
13675                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
13676                     sb.append(" s=");
13677                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
13678                     Slog.d(TAG, sb.toString());
13679                 }
13680 
13681                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
13682                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
13683                 if (updatedUids != null) {
13684                     final int uid = timer.mUid.getUid();
13685                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
13686                 }
13687 
13688                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
13689                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
13690 
13691                 mTempTotalCpuUserTimeUs -= userTimeUs;
13692                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
13693             }
13694         }
13695     }
13696 
13697     /**
13698      * Take a snapshot of the cpu times spent by each uid in each freq and update the
13699      * corresponding counters.  Will also add estimated power consumptions, if powerAccumulator
13700      * data structure is provided.
13701      *
13702      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
13703      * @param onBattery whether or not this is onBattery
13704      * @param onBatteryScreenOff whether or not this is onBattery with the screen off.
13705      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
13706      */
13707     @VisibleForTesting
13708     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
13709             boolean onBattery, boolean onBatteryScreenOff,
13710             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
13711         final boolean perClusterTimesAvailable =
13712                 mCpuUidFreqTimeReader.perClusterTimesAvailable();
13713         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
13714         final int numClusters = mPowerProfile.getNumCpuClusters();
13715         mWakeLockAllocationsUs = null;
13716         final long startTimeMs = mClocks.uptimeMillis();
13717         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
13718         // If power is being accumulated for attribution, data needs to be read immediately.
13719         final boolean forceRead = powerAccumulator != null;
13720         mCpuUidFreqTimeReader.readDelta(forceRead, (uid, cpuFreqTimeMs) -> {
13721             uid = mapUid(uid);
13722             if (Process.isIsolated(uid)) {
13723                 if (DEBUG) Slog.d(TAG, "Got freq readings for an isolated uid: " + uid);
13724                 return;
13725             }
13726             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
13727                 if (DEBUG) Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
13728                 return;
13729             }
13730             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
13731             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
13732                 detachIfNotNull(u.mCpuFreqTimeMs);
13733                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
13734             }
13735             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
13736             if (u.mScreenOffCpuFreqTimeMs == null ||
13737                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
13738                 detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
13739                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
13740                         mOnBatteryScreenOffTimeBase);
13741             }
13742             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
13743 
13744             if (perClusterTimesAvailable) {
13745                 if (u.mCpuClusterSpeedTimesUs == null ||
13746                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
13747                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13748                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13749                 }
13750                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
13751                     mWakeLockAllocationsUs = new long[numClusters][];
13752                 }
13753 
13754                 int freqIndex = 0;
13755                 for (int cluster = 0; cluster < numClusters; ++cluster) {
13756                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
13757                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
13758                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
13759                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
13760                         u.mCpuClusterSpeedTimesUs[cluster]
13761                                 = new LongSamplingCounter[speedsInCluster];
13762                     }
13763                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
13764                         mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
13765                     }
13766                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
13767                     for (int speed = 0; speed < speedsInCluster; ++speed) {
13768                         if (cpuTimesUs[speed] == null) {
13769                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
13770                         }
13771                         final long appAllocationUs;
13772                         if (mWakeLockAllocationsUs != null) {
13773                             appAllocationUs =
13774                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
13775                             mWakeLockAllocationsUs[cluster][speed] +=
13776                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
13777                         } else {
13778                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
13779                         }
13780                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
13781 
13782                         if (powerAccumulator != null) {
13783                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
13784                                     speed, appAllocationUs / 1000);
13785                         }
13786                         freqIndex++;
13787                     }
13788                 }
13789             }
13790         });
13791 
13792         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
13793         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
13794             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
13795         }
13796 
13797         if (mWakeLockAllocationsUs != null) {
13798             for (int i = 0; i < numWakelocks; ++i) {
13799                 final Uid u = partialTimers.get(i).mUid;
13800                 if (u.mCpuClusterSpeedTimesUs == null ||
13801                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
13802                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13803                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13804                 }
13805 
13806                 for (int cluster = 0; cluster < numClusters; ++cluster) {
13807                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
13808                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
13809                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
13810                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
13811                         u.mCpuClusterSpeedTimesUs[cluster]
13812                                 = new LongSamplingCounter[speedsInCluster];
13813                     }
13814                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
13815                     for (int speed = 0; speed < speedsInCluster; ++speed) {
13816                         if (cpuTimeUs[speed] == null) {
13817                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
13818                         }
13819                         final long allocationUs =
13820                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
13821                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
13822                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
13823 
13824                         if (powerAccumulator != null) {
13825                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
13826                                     speed, allocationUs / 1000);
13827                         }
13828                     }
13829                 }
13830             }
13831         }
13832     }
13833 
13834     /**
13835      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
13836      * counters.
13837      */
13838     @VisibleForTesting
13839     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
13840         final long startTimeMs = mClocks.uptimeMillis();
13841         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
13842         mCpuUidActiveTimeReader.readDelta(false, (uid, cpuActiveTimesMs) -> {
13843             uid = mapUid(uid);
13844             if (Process.isIsolated(uid)) {
13845                 if (DEBUG) Slog.w(TAG, "Got active times for an isolated uid: " + uid);
13846                 return;
13847             }
13848             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
13849                 if (DEBUG) Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
13850                 return;
13851             }
13852             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
13853             u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery);
13854         });
13855 
13856         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
13857         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
13858             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
13859         }
13860     }
13861 
13862     /**
13863      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
13864      * counters. Will also add estimated power consumptions, if powerAccumulator data structure
13865      * is provided.
13866      *
13867      * @param onBattery whether or not this is onBattery
13868      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
13869      */
13870     @VisibleForTesting
13871     public void readKernelUidCpuClusterTimesLocked(boolean onBattery,
13872             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
13873         final long startTimeMs = mClocks.uptimeMillis();
13874         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
13875         // If power is being accumulated for attribution, data needs to be read immediately.
13876         final boolean forceRead = powerAccumulator != null;
13877         mCpuUidClusterTimeReader.readDelta(forceRead, (uid, cpuClusterTimesMs) -> {
13878             uid = mapUid(uid);
13879             if (Process.isIsolated(uid)) {
13880                 if (DEBUG) Slog.w(TAG, "Got cluster times for an isolated uid: " + uid);
13881                 return;
13882             }
13883             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
13884                 if (DEBUG) Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
13885                 return;
13886             }
13887             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
13888             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
13889 
13890             if (powerAccumulator != null) {
13891                 powerAccumulator.addCpuClusterDurationsMs(u, cpuClusterTimesMs);
13892             }
13893         });
13894 
13895         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
13896         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
13897             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
13898         }
13899     }
13900 
13901     boolean setChargingLocked(boolean charging) {
13902         // if the device is no longer charging, remove the callback
13903         // if the device is now charging, it means that this is either called
13904         // 1. directly when level >= 90
13905         // 2. or from within the runnable that we deferred
13906         // For 1. if we have an existing callback, remove it, since we will immediately send a
13907         // ACTION_CHARGING
13908         // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
13909         mHandler.removeCallbacks(mDeferSetCharging);
13910         if (mCharging != charging) {
13911             mCharging = charging;
13912             if (charging) {
13913                 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
13914             } else {
13915                 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
13916             }
13917             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
13918             return true;
13919         }
13920         return false;
13921     }
13922 
13923     /**
13924      * Notifies BatteryStatsImpl that the system server is ready.
13925      */
13926     public void onSystemReady() {
13927         mSystemReady = true;
13928     }
13929 
13930     @GuardedBy("this")
13931     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
13932             final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
13933         boolean doWrite = false;
13934         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
13935         m.arg1 = onBattery ? 1 : 0;
13936         mHandler.sendMessage(m);
13937 
13938         final long uptimeUs = mSecUptime * 1000;
13939         final long realtimeUs = mSecRealtime * 1000;
13940         final int screenState = mScreenState;
13941         if (onBattery) {
13942             // We will reset our status if we are unplugging after the
13943             // battery was last full, or the level is at 100, or
13944             // we have gone through a significant charge (from a very low
13945             // level to a now very high level).
13946             // Also, we will reset the stats if battery got partially charged
13947             // and discharged repeatedly without ever reaching the full charge.
13948             // This reset is done in order to prevent stats sessions from going on forever.
13949             // Exceedingly long battery sessions would lead to an overflow of
13950             // data structures such as mWakeupReasonStats.
13951             boolean reset = false;
13952             if (!mNoAutoReset && mSystemReady
13953                     && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
13954                     || level >= 90
13955                     || (mDischargeCurrentLevel < 20 && level >= 80)
13956                     || getHighDischargeAmountSinceCharge() >= 200)) {
13957                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
13958                         + " dischargeLevel=" + mDischargeCurrentLevel
13959                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
13960                         + " highAmount=" + getHighDischargeAmountSinceCharge());
13961                 // Before we write, collect a snapshot of the final aggregated
13962                 // stats to be reported in the next checkin.  Only do this if we have
13963                 // a sufficient amount of data to make it interesting.
13964                 if (getLowDischargeAmountSinceCharge() >= 20) {
13965                     final long startTimeMs = SystemClock.uptimeMillis();
13966                     final Parcel parcel = Parcel.obtain();
13967                     writeSummaryToParcel(parcel, true);
13968                     final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
13969                     BackgroundThread.getHandler().post(new Runnable() {
13970                         @Override public void run() {
13971                             synchronized (mCheckinFile) {
13972                                 final long startTimeMs2 = SystemClock.uptimeMillis();
13973                                 FileOutputStream stream = null;
13974                                 try {
13975                                     stream = mCheckinFile.startWrite();
13976                                     stream.write(parcel.marshall());
13977                                     stream.flush();
13978                                     mCheckinFile.finishWrite(stream);
13979                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
13980                                             "batterystats-checkin", initialTimeMs
13981                                             + SystemClock.uptimeMillis() - startTimeMs2);
13982                                 } catch (IOException e) {
13983                                     Slog.w("BatteryStats",
13984                                             "Error writing checkin battery statistics", e);
13985                                     mCheckinFile.failWrite(stream);
13986                                 } finally {
13987                                     parcel.recycle();
13988                                 }
13989                             }
13990                         }
13991                     });
13992                 }
13993                 doWrite = true;
13994                 resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_FULL_CHARGE);
13995                 if (chargeUah > 0 && level > 0) {
13996                     // Only use the reported coulomb charge value if it is supported and reported.
13997                     mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
13998                 }
13999                 mDischargeStartLevel = level;
14000                 reset = true;
14001                 mDischargeStepTracker.init();
14002             }
14003             if (mCharging) {
14004                 setChargingLocked(false);
14005             }
14006             mLastChargingStateLevel = level;
14007             mOnBattery = mOnBatteryInternal = true;
14008             mLastDischargeStepLevel = level;
14009             mMinDischargeStepLevel = level;
14010             mDischargeStepTracker.clearTime();
14011             mDailyDischargeStepTracker.clearTime();
14012             mInitStepMode = mCurStepMode;
14013             mModStepMode = 0;
14014             pullPendingStateUpdatesLocked();
14015             mHistoryCur.batteryLevel = (byte)level;
14016             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
14017             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
14018                     + Integer.toHexString(mHistoryCur.states));
14019             if (reset) {
14020                 mRecordingHistory = true;
14021                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
14022             }
14023             addHistoryRecordLocked(mSecRealtime, mSecUptime);
14024             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
14025             if (Display.isOnState(screenState)) {
14026                 mDischargeScreenOnUnplugLevel = level;
14027                 mDischargeScreenDozeUnplugLevel = 0;
14028                 mDischargeScreenOffUnplugLevel = 0;
14029             } else if (Display.isDozeState(screenState)) {
14030                 mDischargeScreenOnUnplugLevel = 0;
14031                 mDischargeScreenDozeUnplugLevel = level;
14032                 mDischargeScreenOffUnplugLevel = 0;
14033             } else {
14034                 mDischargeScreenOnUnplugLevel = 0;
14035                 mDischargeScreenDozeUnplugLevel = 0;
14036                 mDischargeScreenOffUnplugLevel = level;
14037             }
14038             mDischargeAmountScreenOn = 0;
14039             mDischargeAmountScreenDoze = 0;
14040             mDischargeAmountScreenOff = 0;
14041             updateTimeBasesLocked(true, screenState, uptimeUs, realtimeUs);
14042         } else {
14043             mLastChargingStateLevel = level;
14044             mOnBattery = mOnBatteryInternal = false;
14045             pullPendingStateUpdatesLocked();
14046             mHistoryCur.batteryLevel = (byte)level;
14047             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
14048             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
14049                     + Integer.toHexString(mHistoryCur.states));
14050             addHistoryRecordLocked(mSecRealtime, mSecUptime);
14051             mDischargeCurrentLevel = mDischargePlugLevel = level;
14052             if (level < mDischargeUnplugLevel) {
14053                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
14054                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
14055             }
14056             updateDischargeScreenLevelsLocked(screenState, screenState);
14057             updateTimeBasesLocked(false, screenState, uptimeUs, realtimeUs);
14058             mChargeStepTracker.init();
14059             mLastChargeStepLevel = level;
14060             mMaxChargeStepLevel = level;
14061             mInitStepMode = mCurStepMode;
14062             mModStepMode = 0;
14063         }
14064         if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
14065             if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
14066                 writeAsyncLocked();
14067             }
14068         }
14069     }
14070 
14071     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
14072             boolean reset) {
14073         mRecordingHistory = true;
14074         mHistoryCur.currentTime = mClocks.currentTimeMillis();
14075         addHistoryBufferLocked(elapsedRealtimeMs,
14076                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
14077                 mHistoryCur);
14078         mHistoryCur.currentTime = 0;
14079         if (reset) {
14080             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
14081         }
14082     }
14083 
14084     private void recordCurrentTimeChangeLocked(final long currentTimeMs,
14085             final long elapsedRealtimeMs, final long uptimeMs) {
14086         if (mRecordingHistory) {
14087             mHistoryCur.currentTime = currentTimeMs;
14088             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
14089             mHistoryCur.currentTime = 0;
14090         }
14091     }
14092 
14093     private void recordShutdownLocked(final long currentTimeMs, final long elapsedRealtimeMs) {
14094         if (mRecordingHistory) {
14095             mHistoryCur.currentTime = currentTimeMs;
14096             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
14097             mHistoryCur.currentTime = 0;
14098         }
14099     }
14100 
14101     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
14102         if (mExternalSync != null) {
14103             mExternalSync.scheduleSync(reason, updateFlags);
14104         }
14105     }
14106 
14107     // This should probably be exposed in the API, though it's not critical
14108     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
14109 
14110     @GuardedBy("this")
14111     public void setBatteryStateLocked(final int status, final int health, final int plugType,
14112             final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
14113             final int chargeFullUah, final long chargeTimeToFullSeconds) {
14114         setBatteryStateLocked(status, health, plugType, level, temp, voltageMv, chargeUah,
14115                 chargeFullUah, chargeTimeToFullSeconds,
14116                 mClocks.elapsedRealtime(), mClocks.uptimeMillis(), mClocks.currentTimeMillis());
14117     }
14118 
14119     public void setBatteryStateLocked(final int status, final int health, final int plugType,
14120             final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
14121             final int chargeFullUah, final long chargeTimeToFullSeconds,
14122             final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) {
14123         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
14124         temp = Math.max(0, temp);
14125 
14126         reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
14127                 status, plugType, level);
14128 
14129         final boolean onBattery = isOnBattery(plugType, status);
14130         if (!mHaveBatteryLevel) {
14131             mHaveBatteryLevel = true;
14132             // We start out assuming that the device is plugged in (not
14133             // on battery).  If our first report is now that we are indeed
14134             // plugged in, then twiddle our state to correctly reflect that
14135             // since we won't be going through the full setOnBattery().
14136             if (onBattery == mOnBattery) {
14137                 if (onBattery) {
14138                     mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
14139                 } else {
14140                     mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
14141                 }
14142             }
14143             // Always start out assuming charging, that will be updated later.
14144             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
14145             mHistoryCur.batteryStatus = (byte)status;
14146             mHistoryCur.batteryLevel = (byte)level;
14147             mHistoryCur.batteryChargeUah = chargeUah;
14148             mMaxChargeStepLevel = mMinDischargeStepLevel =
14149                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
14150             mLastChargingStateLevel = level;
14151         } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
14152             recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
14153         }
14154         int oldStatus = mHistoryCur.batteryStatus;
14155         if (onBattery) {
14156             mDischargeCurrentLevel = level;
14157             if (!mRecordingHistory) {
14158                 mRecordingHistory = true;
14159                 startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
14160             }
14161         } else if (level < 96 &&
14162                 status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
14163             if (!mRecordingHistory) {
14164                 mRecordingHistory = true;
14165                 startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
14166             }
14167         }
14168         mBatteryVoltageMv = voltageMv;
14169         mCurrentBatteryLevel = level;
14170         if (mDischargePlugLevel < 0) {
14171             mDischargePlugLevel = level;
14172         }
14173 
14174         if (onBattery != mOnBattery) {
14175             mHistoryCur.batteryLevel = (byte)level;
14176             mHistoryCur.batteryStatus = (byte)status;
14177             mHistoryCur.batteryHealth = (byte)health;
14178             mHistoryCur.batteryPlugType = (byte)plugType;
14179             mHistoryCur.batteryTemperature = (short)temp;
14180             mHistoryCur.batteryVoltage = (char) voltageMv;
14181             if (chargeUah < mHistoryCur.batteryChargeUah) {
14182                 // Only record discharges
14183                 final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
14184                 mDischargeCounter.addCountLocked(chargeDiff);
14185                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
14186                 if (Display.isDozeState(mScreenState)) {
14187                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
14188                 }
14189                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
14190                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
14191                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
14192                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
14193                 }
14194             }
14195             mHistoryCur.batteryChargeUah = chargeUah;
14196             setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
14197         } else {
14198             boolean changed = false;
14199             if (mHistoryCur.batteryLevel != level) {
14200                 mHistoryCur.batteryLevel = (byte)level;
14201                 changed = true;
14202 
14203                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
14204                 // which will pull external stats.
14205                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
14206                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
14207             }
14208             if (mHistoryCur.batteryStatus != status) {
14209                 mHistoryCur.batteryStatus = (byte)status;
14210                 changed = true;
14211             }
14212             if (mHistoryCur.batteryHealth != health) {
14213                 mHistoryCur.batteryHealth = (byte)health;
14214                 changed = true;
14215             }
14216             if (mHistoryCur.batteryPlugType != plugType) {
14217                 mHistoryCur.batteryPlugType = (byte)plugType;
14218                 changed = true;
14219             }
14220             if (temp >= (mHistoryCur.batteryTemperature+10)
14221                     || temp <= (mHistoryCur.batteryTemperature-10)) {
14222                 mHistoryCur.batteryTemperature = (short)temp;
14223                 changed = true;
14224             }
14225             if (voltageMv > (mHistoryCur.batteryVoltage + 20)
14226                     || voltageMv < (mHistoryCur.batteryVoltage - 20)) {
14227                 mHistoryCur.batteryVoltage = (char) voltageMv;
14228                 changed = true;
14229             }
14230             if (chargeUah >= (mHistoryCur.batteryChargeUah + 10)
14231                     || chargeUah <= (mHistoryCur.batteryChargeUah - 10)) {
14232                 if (chargeUah < mHistoryCur.batteryChargeUah) {
14233                     // Only record discharges
14234                     final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
14235                     mDischargeCounter.addCountLocked(chargeDiff);
14236                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
14237                     if (Display.isDozeState(mScreenState)) {
14238                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
14239                     }
14240                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
14241                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
14242                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
14243                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
14244                     }
14245                 }
14246                 mHistoryCur.batteryChargeUah = chargeUah;
14247                 changed = true;
14248             }
14249             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
14250                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
14251                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
14252             if (onBattery) {
14253                 changed |= setChargingLocked(false);
14254                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
14255                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
14256                             modeBits, elapsedRealtimeMs);
14257                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
14258                             modeBits, elapsedRealtimeMs);
14259                     mLastDischargeStepLevel = level;
14260                     mMinDischargeStepLevel = level;
14261                     mInitStepMode = mCurStepMode;
14262                     mModStepMode = 0;
14263                 }
14264             } else {
14265                 if (level >= 90) {
14266                     // If the battery level is at least 90%, always consider the device to be
14267                     // charging even if it happens to go down a level.
14268                     changed |= setChargingLocked(true);
14269                 } else if (!mCharging) {
14270                     if (mLastChargeStepLevel < level) {
14271                         // We have not reported that we are charging, but the level has gone up,
14272                         // but we would like to not have tons of activity from charging-constraint
14273                         // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
14274                         if (!mHandler.hasCallbacks(mDeferSetCharging)) {
14275                             mHandler.postDelayed(
14276                                     mDeferSetCharging,
14277                                     mConstants.BATTERY_CHARGED_DELAY_MS);
14278                         }
14279                     } else if (mLastChargeStepLevel > level) {
14280                         // if we had deferred a runnable due to charge level increasing, but then
14281                         // later the charge level drops (could be due to thermal issues), we don't
14282                         // want to trigger the deferred runnable, so remove it here
14283                         mHandler.removeCallbacks(mDeferSetCharging);
14284                     }
14285                 } else {
14286                     if (mLastChargeStepLevel > level) {
14287                         // We had reported that the device was charging, but here we are with
14288                         // power connected and the level going down.  Looks like the current
14289                         // power supplied isn't enough, so consider the device to now be
14290                         // discharging.
14291                         changed |= setChargingLocked(false);
14292                     }
14293                 }
14294                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
14295                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
14296                             modeBits, elapsedRealtimeMs);
14297                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
14298                             modeBits, elapsedRealtimeMs);
14299                     mMaxChargeStepLevel = level;
14300                     mInitStepMode = mCurStepMode;
14301                     mModStepMode = 0;
14302                 }
14303                 mLastChargeStepLevel = level;
14304             }
14305             if (changed) {
14306                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
14307             }
14308         }
14309         if (!onBattery &&
14310                 (status == BatteryManager.BATTERY_STATUS_FULL ||
14311                         status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
14312             // We don't record history while we are plugged in and fully charged
14313             // (or when battery is not present).  The next time we are
14314             // unplugged, history will be cleared.
14315             mRecordingHistory = DEBUG;
14316         }
14317 
14318         mLastLearnedBatteryCapacityUah = chargeFullUah;
14319         if (mMinLearnedBatteryCapacityUah == -1) {
14320             mMinLearnedBatteryCapacityUah = chargeFullUah;
14321         } else {
14322             mMinLearnedBatteryCapacityUah = Math.min(mMinLearnedBatteryCapacityUah, chargeFullUah);
14323         }
14324         mMaxLearnedBatteryCapacityUah = Math.max(mMaxLearnedBatteryCapacityUah, chargeFullUah);
14325 
14326         mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
14327     }
14328 
14329     public static boolean isOnBattery(int plugType, int status) {
14330         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
14331     }
14332 
14333     // Inform StatsLog of setBatteryState changes.
14334     // If this is the first reporting, pass in recentPast == null.
14335     private void reportChangesToStatsLog(HistoryItem recentPast,
14336             final int status, final int plugType, final int level) {
14337 
14338         if (recentPast == null || recentPast.batteryStatus != status) {
14339             FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
14340         }
14341         if (recentPast == null || recentPast.batteryPlugType != plugType) {
14342             FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
14343         }
14344         if (recentPast == null || recentPast.batteryLevel != level) {
14345             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
14346         }
14347     }
14348 
14349     @UnsupportedAppUsage
14350     public long getAwakeTimeBattery() {
14351         // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
14352         // for over a decade, but surely that was a mistake.
14353         return getBatteryUptimeLocked(mClocks.uptimeMillis());
14354     }
14355 
14356     @UnsupportedAppUsage
14357     public long getAwakeTimePlugged() {
14358         return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
14359     }
14360 
14361     @Override
14362     public long computeUptime(long curTimeUs, int which) {
14363         return mUptimeUs + (curTimeUs - mUptimeStartUs);
14364     }
14365 
14366     @Override
14367     public long computeRealtime(long curTimeUs, int which) {
14368         return mRealtimeUs + (curTimeUs - mRealtimeStartUs);
14369     }
14370 
14371     @Override
14372     @UnsupportedAppUsage
14373     public long computeBatteryUptime(long curTimeUs, int which) {
14374         return mOnBatteryTimeBase.computeUptime(curTimeUs, which);
14375     }
14376 
14377     @Override
14378     @UnsupportedAppUsage
14379     public long computeBatteryRealtime(long curTimeUs, int which) {
14380         return mOnBatteryTimeBase.computeRealtime(curTimeUs, which);
14381     }
14382 
14383     @Override
14384     public long computeBatteryScreenOffUptime(long curTimeUs, int which) {
14385         return mOnBatteryScreenOffTimeBase.computeUptime(curTimeUs, which);
14386     }
14387 
14388     @Override
14389     public long computeBatteryScreenOffRealtime(long curTimeUs, int which) {
14390         return mOnBatteryScreenOffTimeBase.computeRealtime(curTimeUs, which);
14391     }
14392 
14393     private long computeTimePerLevel(long[] steps, int numSteps) {
14394         // For now we'll do a simple average across all steps.
14395         if (numSteps <= 0) {
14396             return -1;
14397         }
14398         long total = 0;
14399         for (int i=0; i<numSteps; i++) {
14400             total += steps[i] & STEP_LEVEL_TIME_MASK;
14401         }
14402         return total / numSteps;
14403         /*
14404         long[] buckets = new long[numSteps];
14405         int numBuckets = 0;
14406         int numToAverage = 4;
14407         int i = 0;
14408         while (i < numSteps) {
14409             long totalTime = 0;
14410             int num = 0;
14411             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
14412                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
14413                 num++;
14414             }
14415             buckets[numBuckets] = totalTime / num;
14416             numBuckets++;
14417             numToAverage *= 2;
14418             i += num;
14419         }
14420         if (numBuckets < 1) {
14421             return -1;
14422         }
14423         long averageTime = buckets[numBuckets-1];
14424         for (i=numBuckets-2; i>=0; i--) {
14425             averageTime = (averageTime + buckets[i]) / 2;
14426         }
14427         return averageTime;
14428         */
14429     }
14430 
14431     @Override
14432     @UnsupportedAppUsage
14433     public long computeBatteryTimeRemaining(long curTime) {
14434         if (!mOnBattery) {
14435             return -1;
14436         }
14437         /* Simple implementation just looks at the average discharge per level across the
14438            entire sample period.
14439         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
14440         if (discharge < 2) {
14441             return -1;
14442         }
14443         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
14444         if (duration < 1000*1000) {
14445             return -1;
14446         }
14447         long usPerLevel = duration/discharge;
14448         return usPerLevel * mCurrentBatteryLevel;
14449         */
14450         if (mDischargeStepTracker.mNumStepDurations < 1) {
14451             return -1;
14452         }
14453         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
14454         if (msPerLevel <= 0) {
14455             return -1;
14456         }
14457         return (msPerLevel * mCurrentBatteryLevel) * 1000;
14458     }
14459 
14460     @Override
14461     public LevelStepTracker getDischargeLevelStepTracker() {
14462         return mDischargeStepTracker;
14463     }
14464 
14465     @Override
14466     public LevelStepTracker getDailyDischargeLevelStepTracker() {
14467         return mDailyDischargeStepTracker;
14468     }
14469 
14470     @Override
14471     public long computeChargeTimeRemaining(long curTime) {
14472         if (mOnBattery) {
14473             // Not yet working.
14474             return -1;
14475         }
14476         if (mBatteryTimeToFullSeconds >= 0) {
14477             return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us
14478         }
14479         // Else use algorithmic approach
14480         if (mChargeStepTracker.mNumStepDurations < 1) {
14481             return -1;
14482         }
14483         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
14484         if (msPerLevel <= 0) {
14485             return -1;
14486         }
14487         return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;
14488     }
14489 
14490     /*@hide */
14491     public CellularBatteryStats getCellularBatteryStats() {
14492         final int which = STATS_SINCE_CHARGED;
14493         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
14494         final ControllerActivityCounter counter = getModemControllerActivity();
14495         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
14496         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
14497         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
14498         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
14499         final long monitoredRailChargeConsumedMaMs =
14500                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
14501         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
14502         for (int i = 0; i < timeInRatMs.length; i++) {
14503             timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTimeUs, which) / 1000;
14504         }
14505         long[] timeInRxSignalStrengthLevelMs =
14506                 new long[CellSignalStrength.getNumSignalStrengthLevels()];
14507         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
14508             timeInRxSignalStrengthLevelMs[i] =
14509                 getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
14510         }
14511         long[] txTimeMs = new long[Math.min(ModemActivityInfo.getNumTxPowerLevels(),
14512             counter.getTxTimeCounters().length)];
14513         long totalTxTimeMs = 0;
14514         for (int i = 0; i < txTimeMs.length; i++) {
14515             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
14516             totalTxTimeMs += txTimeMs[i];
14517         }
14518 
14519         return new CellularBatteryStats(computeBatteryRealtime(rawRealTimeUs, which) / 1000,
14520                 getMobileRadioActiveTime(rawRealTimeUs, which) / 1000,
14521                 getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which),
14522                 getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which),
14523                 getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which),
14524                 getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which),
14525                 sleepTimeMs, idleTimeMs, rxTimeMs, energyConsumedMaMs, timeInRatMs,
14526                 timeInRxSignalStrengthLevelMs, txTimeMs,
14527                 monitoredRailChargeConsumedMaMs);
14528     }
14529 
14530     /*@hide */
14531     public WifiBatteryStats getWifiBatteryStats() {
14532         final int which = STATS_SINCE_CHARGED;
14533         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
14534         final ControllerActivityCounter counter = getWifiControllerActivity();
14535         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
14536         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
14537         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
14538         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
14539         final long totalControllerActivityTimeMs
14540                 = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
14541         final long sleepTimeMs
14542                 = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
14543         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
14544         final long monitoredRailChargeConsumedMaMs =
14545                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
14546         long numAppScanRequest = 0;
14547         for (int i = 0; i < mUidStats.size(); i++) {
14548             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
14549         }
14550         long[] timeInStateMs = new long[NUM_WIFI_STATES];
14551         for (int i=0; i<NUM_WIFI_STATES; i++) {
14552             timeInStateMs[i] = getWifiStateTime(i, rawRealTimeUs, which) / 1000;
14553         }
14554         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
14555         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14556             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTimeUs, which) / 1000;
14557         }
14558         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
14559         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14560             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
14561         }
14562         return new WifiBatteryStats(
14563                 computeBatteryRealtime(rawRealTimeUs, which) / 1000,
14564                 getWifiActiveTime(rawRealTimeUs, which) / 1000,
14565                 getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which),
14566                 getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which),
14567                 getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which),
14568                 getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which),
14569                 sleepTimeMs, scanTimeMs, idleTimeMs, rxTimeMs, txTimeMs, energyConsumedMaMs,
14570                 numAppScanRequest, timeInStateMs, timeSignalStrengthTimeMs, timeInSupplStateMs,
14571                 monitoredRailChargeConsumedMaMs);
14572     }
14573 
14574     /*@hide */
14575     public GpsBatteryStats getGpsBatteryStats() {
14576         GpsBatteryStats s = new GpsBatteryStats();
14577         final int which = STATS_SINCE_CHARGED;
14578         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
14579         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000);
14580         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
14581         long[] time = new long[mGpsSignalQualityTimer.length];
14582         for (int i=0; i<time.length; i++) {
14583             time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000;
14584         }
14585         s.setTimeInGpsSignalQualityLevel(time);
14586         return s;
14587     }
14588 
14589     @Override
14590     public LevelStepTracker getChargeLevelStepTracker() {
14591         return mChargeStepTracker;
14592     }
14593 
14594     @Override
14595     public LevelStepTracker getDailyChargeLevelStepTracker() {
14596         return mDailyChargeStepTracker;
14597     }
14598 
14599     @Override
14600     public ArrayList<PackageChange> getDailyPackageChanges() {
14601         return mDailyPackageChanges;
14602     }
14603 
14604     /**
14605      * @return battery uptime in microseconds
14606      */
14607     protected long getBatteryUptimeLocked() {
14608         return getBatteryUptimeLocked(mClocks.uptimeMillis());
14609     }
14610 
14611     /**
14612      * @return battery uptime in microseconds
14613      */
14614     protected long getBatteryUptimeLocked(long uptimeMs) {
14615         return mOnBatteryTimeBase.getUptime(uptimeMs * 1000);
14616     }
14617 
14618     @Override
14619     public long getBatteryUptime(long curTimeUs) {
14620         return mOnBatteryTimeBase.getUptime(curTimeUs);
14621     }
14622 
14623     @Override
14624     @UnsupportedAppUsage
14625     public long getBatteryRealtime(long curTimeUs) {
14626         return mOnBatteryTimeBase.getRealtime(curTimeUs);
14627     }
14628 
14629     @Override
14630     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
14631     public int getDischargeStartLevel() {
14632         synchronized(this) {
14633             return getDischargeStartLevelLocked();
14634         }
14635     }
14636 
14637     public int getDischargeStartLevelLocked() {
14638             return mDischargeUnplugLevel;
14639     }
14640 
14641     @Override
14642     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
14643     public int getDischargeCurrentLevel() {
14644         synchronized(this) {
14645             return getDischargeCurrentLevelLocked();
14646         }
14647     }
14648 
14649     public int getDischargeCurrentLevelLocked() {
14650         return mDischargeCurrentLevel;
14651     }
14652 
14653     @Override
14654     public int getLowDischargeAmountSinceCharge() {
14655         synchronized(this) {
14656             int val = mLowDischargeAmountSinceCharge;
14657             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
14658                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
14659             }
14660             return val;
14661         }
14662     }
14663 
14664     @Override
14665     public int getHighDischargeAmountSinceCharge() {
14666         synchronized(this) {
14667             int val = mHighDischargeAmountSinceCharge;
14668             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
14669                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
14670             }
14671             return val;
14672         }
14673     }
14674 
14675     @Override
14676     @UnsupportedAppUsage
14677     public int getDischargeAmount(int which) {
14678         int dischargeAmount = which == STATS_SINCE_CHARGED
14679                 ? getHighDischargeAmountSinceCharge()
14680                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
14681         if (dischargeAmount < 0) {
14682             dischargeAmount = 0;
14683         }
14684         return dischargeAmount;
14685     }
14686 
14687     @Override
14688     @UnsupportedAppUsage
14689     public int getDischargeAmountScreenOn() {
14690         synchronized(this) {
14691             int val = mDischargeAmountScreenOn;
14692             if (mOnBattery && Display.isOnState(mScreenState)
14693                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
14694                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
14695             }
14696             return val;
14697         }
14698     }
14699 
14700     @Override
14701     public int getDischargeAmountScreenOnSinceCharge() {
14702         synchronized(this) {
14703             int val = mDischargeAmountScreenOnSinceCharge;
14704             if (mOnBattery && Display.isOnState(mScreenState)
14705                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
14706                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
14707             }
14708             return val;
14709         }
14710     }
14711 
14712     @Override
14713     @UnsupportedAppUsage
14714     public int getDischargeAmountScreenOff() {
14715         synchronized(this) {
14716             int val = mDischargeAmountScreenOff;
14717             if (mOnBattery && Display.isOffState(mScreenState)
14718                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
14719                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
14720             }
14721             // For backward compatibility, doze discharge is counted into screen off.
14722             return val + getDischargeAmountScreenDoze();
14723         }
14724     }
14725 
14726     @Override
14727     public int getDischargeAmountScreenOffSinceCharge() {
14728         synchronized(this) {
14729             int val = mDischargeAmountScreenOffSinceCharge;
14730             if (mOnBattery && Display.isOffState(mScreenState)
14731                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
14732                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
14733             }
14734             // For backward compatibility, doze discharge is counted into screen off.
14735             return val + getDischargeAmountScreenDozeSinceCharge();
14736         }
14737     }
14738 
14739     @Override
14740     public int getDischargeAmountScreenDoze() {
14741         synchronized(this) {
14742             int val = mDischargeAmountScreenDoze;
14743             if (mOnBattery && Display.isDozeState(mScreenState)
14744                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
14745                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
14746             }
14747             return val;
14748         }
14749     }
14750 
14751     @Override
14752     public int getDischargeAmountScreenDozeSinceCharge() {
14753         synchronized(this) {
14754             int val = mDischargeAmountScreenDozeSinceCharge;
14755             if (mOnBattery && Display.isDozeState(mScreenState)
14756                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
14757                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
14758             }
14759             return val;
14760         }
14761     }
14762 
14763 
14764     /**
14765      * Estimates the time spent by the system server handling incoming binder requests.
14766      */
14767     @Override
14768     public long[] getSystemServiceTimeAtCpuSpeeds() {
14769         if (mBinderThreadCpuTimesUs == null) {
14770             return null;
14771         }
14772 
14773         return mBinderThreadCpuTimesUs.getCountsLocked(BatteryStats.STATS_SINCE_CHARGED);
14774     }
14775 
14776     /**
14777      * Retrieve the statistics object for a particular uid, creating if needed.
14778      */
14779     @UnsupportedAppUsage
14780     public Uid getUidStatsLocked(int uid) {
14781         return getUidStatsLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
14782     }
14783 
14784     public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
14785         Uid u = mUidStats.get(uid);
14786         if (u == null) {
14787             u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
14788             mUidStats.put(uid, u);
14789         }
14790         return u;
14791     }
14792 
14793     /**
14794      * Retrieve the statistics object for a particular uid. Returns null if the object is not
14795      * available.
14796      */
14797     public Uid getAvailableUidStatsLocked(int uid) {
14798         Uid u = mUidStats.get(uid);
14799         return u;
14800     }
14801 
14802     public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) {
14803         final int firstUidForUser = UserHandle.getUid(userId, 0);
14804         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
14805         mPendingRemovedUids.add(
14806                 new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs));
14807     }
14808 
14809     public void onUserRemovedLocked(int userId) {
14810         final int firstUidForUser = UserHandle.getUid(userId, 0);
14811         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
14812         mUidStats.put(firstUidForUser, null);
14813         mUidStats.put(lastUidForUser, null);
14814         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
14815         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
14816         for (int i = firstIndex; i <= lastIndex; i++) {
14817             final Uid uid = mUidStats.valueAt(i);
14818             if (uid != null) {
14819                 uid.detachFromTimeBase();
14820             }
14821         }
14822         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
14823     }
14824 
14825     /**
14826      * Remove the statistics object for a particular uid.
14827      */
14828     @UnsupportedAppUsage
14829     public void removeUidStatsLocked(int uid) {
14830         removeUidStatsLocked(uid, mClocks.elapsedRealtime());
14831     }
14832 
14833     /**
14834      * @see #removeUidStatsLocked(int)
14835      */
14836     public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) {
14837         final Uid u = mUidStats.get(uid);
14838         if (u != null) {
14839             u.detachFromTimeBase();
14840         }
14841         mUidStats.remove(uid);
14842         mPendingRemovedUids.add(new UidToRemove(uid, elapsedRealtimeMs));
14843     }
14844 
14845     /**
14846      * Retrieve the statistics object for a particular process, creating
14847      * if needed.
14848      */
14849     @UnsupportedAppUsage
14850     public Uid.Proc getProcessStatsLocked(int uid, String name) {
14851         return getProcessStatsLocked(uid, name, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
14852     }
14853 
14854     /**
14855      * @see #getProcessStatsLocked(int, String)
14856      */
14857     public Uid.Proc getProcessStatsLocked(int uid, String name,
14858             long elapsedRealtimeMs, long uptimeMs) {
14859         uid = mapUid(uid);
14860         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
14861         return u.getProcessStatsLocked(name);
14862     }
14863 
14864     /**
14865      * Retrieve the statistics object for a particular process, creating
14866      * if needed.
14867      */
14868     @UnsupportedAppUsage
14869     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
14870         return getPackageStatsLocked(uid, pkg, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
14871     }
14872 
14873     /**
14874      * @see getPackageStatsLocked(int, String)
14875      */
14876     public Uid.Pkg getPackageStatsLocked(int uid, String pkg,
14877             long elapsedRealtimeMs, long uptimeMs) {
14878         uid = mapUid(uid);
14879         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
14880         return u.getPackageStatsLocked(pkg);
14881     }
14882 
14883     /**
14884      * Retrieve the statistics object for a particular service, creating
14885      * if needed.
14886      */
14887     @UnsupportedAppUsage
14888     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
14889         return getServiceStatsLocked(uid, pkg, name,
14890                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
14891     }
14892 
14893     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name,
14894             long elapsedRealtimeMs, long uptimeMs) {
14895         uid = mapUid(uid);
14896         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
14897         return u.getServiceStatsLocked(pkg, name);
14898     }
14899 
14900     public void shutdownLocked() {
14901         recordShutdownLocked(mClocks.currentTimeMillis(), mClocks.elapsedRealtime());
14902         writeSyncLocked();
14903         mShuttingDown = true;
14904     }
14905 
14906     public boolean trackPerProcStateCpuTimes() {
14907         return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
14908     }
14909 
14910     public void systemServicesReady(Context context) {
14911         mConstants.startObserving(context.getContentResolver());
14912         registerUsbStateReceiver(context);
14913     }
14914 
14915     /**
14916      * Initialize the measured charge stats data structures.
14917      *
14918      * @param supportedStandardBuckets boolean array indicating which {@link StandardPowerBucket}s
14919      *                                 are currently supported. If null, none are supported
14920      *                                 (regardless of customBucketNames).
14921      * @param customBucketNames        names of custom (OTHER) EnergyConsumers on this device
14922      */
14923     @GuardedBy("this")
14924     public void initMeasuredEnergyStatsLocked(@Nullable boolean[] supportedStandardBuckets,
14925             String[] customBucketNames) {
14926         boolean supportedBucketMismatch = false;
14927 
14928         final int numDisplays = mPerDisplayBatteryStats.length;
14929         for (int i = 0; i < numDisplays; i++) {
14930             final int screenState = mPerDisplayBatteryStats[i].screenState;
14931             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
14932         }
14933 
14934         if (supportedStandardBuckets == null) {
14935             if (mGlobalMeasuredEnergyStats != null) {
14936                 // Measured energy no longer supported, wipe out the existing data.
14937                 supportedBucketMismatch = true;
14938             }
14939         } else {
14940             if (mGlobalMeasuredEnergyStats == null) {
14941                 mGlobalMeasuredEnergyStats =
14942                         new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
14943             } else {
14944                 supportedBucketMismatch = !mGlobalMeasuredEnergyStats.isSupportEqualTo(
14945                         supportedStandardBuckets, customBucketNames);
14946             }
14947 
14948             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH]) {
14949                 mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
14950             }
14951             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_CPU]) {
14952                 mCpuPowerCalculator = new CpuPowerCalculator(mPowerProfile);
14953             }
14954             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO]) {
14955                 mMobileRadioPowerCalculator = new MobileRadioPowerCalculator(mPowerProfile);
14956             }
14957             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_WIFI]) {
14958                 mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
14959             }
14960         }
14961 
14962         if (supportedBucketMismatch) {
14963             mGlobalMeasuredEnergyStats = supportedStandardBuckets == null
14964                     ? null : new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
14965             // Supported power buckets changed since last boot.
14966             // Existing data is no longer reliable.
14967             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
14968                     RESET_REASON_MEASURED_ENERGY_BUCKETS_CHANGE);
14969         }
14970     }
14971 
14972     /** Get the last known Battery voltage (in millivolts), returns -1 if unknown */
14973     @GuardedBy("this")
14974     public int getBatteryVoltageMvLocked() {
14975         return mBatteryVoltageMv;
14976     }
14977 
14978     @VisibleForTesting
14979     public final class Constants extends ContentObserver {
14980         public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE
14981                 = "track_cpu_times_by_proc_state";
14982         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
14983                 = "track_cpu_active_cluster_time";
14984         public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
14985                 = "proc_state_cpu_times_read_delay_ms";
14986         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
14987                 = "kernel_uid_readers_throttle_time";
14988         public static final String KEY_UID_REMOVE_DELAY_MS
14989                 = "uid_remove_delay_ms";
14990         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
14991                 = "external_stats_collection_rate_limit_ms";
14992         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
14993                 = "battery_level_collection_delay_ms";
14994         public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
14995         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
14996         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
14997                 "battery_charged_delay_ms";
14998 
14999         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = false;
15000         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
15001         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
15002         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
15003         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
15004         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
15005         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
15006         private static final int DEFAULT_MAX_HISTORY_FILES = 32;
15007         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
15008         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
15009         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
15010         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
15011 
15012         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
15013         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
15014         public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
15015         /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
15016          * update when startObserving. */
15017         public long KERNEL_UID_READERS_THROTTLE_TIME;
15018         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
15019         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
15020                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
15021         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
15022                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
15023         public int MAX_HISTORY_FILES;
15024         public int MAX_HISTORY_BUFFER; /*Bytes*/
15025         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
15026 
15027         private ContentResolver mResolver;
15028         private final KeyValueListParser mParser = new KeyValueListParser(',');
15029 
15030         public Constants(Handler handler) {
15031             super(handler);
15032             if (ActivityManager.isLowRamDeviceStatic()) {
15033                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE;
15034                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
15035             } else {
15036                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES;
15037                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
15038             }
15039         }
15040 
15041         public void startObserving(ContentResolver resolver) {
15042             mResolver = resolver;
15043             mResolver.registerContentObserver(
15044                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
15045                     false /* notifyForDescendants */, this);
15046             mResolver.registerContentObserver(
15047                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
15048                     false /* notifyForDescendants */, this);
15049             updateConstants();
15050         }
15051 
15052         @Override
15053         public void onChange(boolean selfChange, Uri uri) {
15054             if (uri.equals(
15055                     Settings.Global.getUriFor(
15056                             Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY))) {
15057                 synchronized (BatteryStatsImpl.this) {
15058                     updateBatteryChargedDelayMsLocked();
15059                 }
15060                 return;
15061             }
15062             updateConstants();
15063         }
15064 
15065         private void updateConstants() {
15066             synchronized (BatteryStatsImpl.this) {
15067                 try {
15068                     mParser.setString(Settings.Global.getString(mResolver,
15069                             Settings.Global.BATTERY_STATS_CONSTANTS));
15070                 } catch (IllegalArgumentException e) {
15071                     // Failed to parse the settings string, log this and move on
15072                     // with defaults.
15073                     Slog.e(TAG, "Bad batterystats settings", e);
15074                 }
15075 
15076                 updateTrackCpuTimesByProcStateLocked(TRACK_CPU_TIMES_BY_PROC_STATE,
15077                         mParser.getBoolean(KEY_TRACK_CPU_TIMES_BY_PROC_STATE,
15078                                 DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE));
15079                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
15080                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
15081                 updateProcStateCpuTimesReadDelayMs(PROC_STATE_CPU_TIMES_READ_DELAY_MS,
15082                         mParser.getLong(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS,
15083                                 DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS));
15084                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
15085                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
15086                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
15087                 updateUidRemoveDelay(
15088                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
15089                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
15090                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
15091                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
15092                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
15093                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
15094                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
15095 
15096                 MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
15097                         ActivityManager.isLowRamDeviceStatic() ?
15098                                 DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
15099                         : DEFAULT_MAX_HISTORY_FILES);
15100                 MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
15101                         ActivityManager.isLowRamDeviceStatic() ?
15102                                 DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
15103                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
15104                         * 1024;
15105                 updateBatteryChargedDelayMsLocked();
15106             }
15107         }
15108 
15109         private void updateBatteryChargedDelayMsLocked() {
15110             // a negative value indicates that we should ignore this override
15111             final int delay = Settings.Global.getInt(mResolver,
15112                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
15113                     -1);
15114 
15115             BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
15116                     KEY_BATTERY_CHARGED_DELAY_MS,
15117                     DEFAULT_BATTERY_CHARGED_DELAY_MS);
15118         }
15119 
15120         private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
15121             TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
15122             if (isEnabled && !wasEnabled) {
15123                 mIsPerProcessStateCpuDataStale = true;
15124                 mExternalSync.scheduleCpuSyncDueToSettingChange();
15125 
15126                 mNumSingleUidCpuTimeReads = 0;
15127                 mNumBatchedSingleUidCpuTimeReads = 0;
15128                 mCpuTimeReadsTrackingStartTimeMs = mClocks.uptimeMillis();
15129             }
15130         }
15131 
15132         private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
15133             PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
15134             if (oldDelayMillis != newDelayMillis) {
15135                 mNumSingleUidCpuTimeReads = 0;
15136                 mNumBatchedSingleUidCpuTimeReads = 0;
15137                 mCpuTimeReadsTrackingStartTimeMs = mClocks.uptimeMillis();
15138             }
15139         }
15140 
15141         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
15142             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
15143             if (oldTimeMs != newTimeMs) {
15144                 mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
15145                 mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
15146                 mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
15147                 mCpuUidClusterTimeReader
15148                         .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
15149             }
15150         }
15151 
15152         private void updateUidRemoveDelay(long newTimeMs) {
15153             UID_REMOVE_DELAY_MS = newTimeMs;
15154             clearPendingRemovedUids();
15155         }
15156 
15157         public void dumpLocked(PrintWriter pw) {
15158             pw.print(KEY_TRACK_CPU_TIMES_BY_PROC_STATE); pw.print("=");
15159             pw.println(TRACK_CPU_TIMES_BY_PROC_STATE);
15160             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
15161             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
15162             pw.print(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS); pw.print("=");
15163             pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
15164             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
15165             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
15166             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
15167             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
15168             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
15169             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
15170             pw.print(KEY_MAX_HISTORY_FILES); pw.print("=");
15171             pw.println(MAX_HISTORY_FILES);
15172             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
15173             pw.println(MAX_HISTORY_BUFFER/1024);
15174             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
15175             pw.println(BATTERY_CHARGED_DELAY_MS);
15176         }
15177     }
15178 
15179     public long getExternalStatsCollectionRateLimitMs() {
15180         synchronized (this) {
15181             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
15182         }
15183     }
15184 
15185     @GuardedBy("this")
15186     public void dumpConstantsLocked(PrintWriter pw) {
15187         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
15188         iPw.println("BatteryStats constants:");
15189         iPw.increaseIndent();
15190         mConstants.dumpLocked(iPw);
15191         iPw.decreaseIndent();
15192     }
15193 
15194     @GuardedBy("this")
15195     public void dumpCpuStatsLocked(PrintWriter pw) {
15196         int size = mUidStats.size();
15197         pw.println("Per UID CPU user & system time in ms:");
15198         for (int i = 0; i < size; i++) {
15199             int u = mUidStats.keyAt(i);
15200             Uid uid = mUidStats.get(u);
15201             pw.print("  "); pw.print(u); pw.print(": ");
15202             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
15203             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
15204         }
15205 
15206         pw.println("Per UID CPU active time in ms:");
15207         for (int i = 0; i < size; i++) {
15208             int u = mUidStats.keyAt(i);
15209             Uid uid = mUidStats.get(u);
15210             if (uid.getCpuActiveTime() > 0) {
15211                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
15212             }
15213         }
15214         pw.println("Per UID CPU cluster time in ms:");
15215         for (int i = 0; i < size; i++) {
15216             int u = mUidStats.keyAt(i);
15217             long[] times = mUidStats.get(u).getCpuClusterTimes();
15218             if (times != null) {
15219                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
15220             }
15221         }
15222         pw.println("Per UID CPU frequency time in ms:");
15223         for (int i = 0; i < size; i++) {
15224             int u = mUidStats.keyAt(i);
15225             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
15226             if (times != null) {
15227                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
15228             }
15229         }
15230 
15231         updateSystemServiceCallStats();
15232         if (mBinderThreadCpuTimesUs != null) {
15233             pw.println("Per UID System server binder time in ms:");
15234             long[] systemServiceTimeAtCpuSpeeds = getSystemServiceTimeAtCpuSpeeds();
15235             for (int i = 0; i < size; i++) {
15236                 int u = mUidStats.keyAt(i);
15237                 Uid uid = mUidStats.get(u);
15238                 double proportionalSystemServiceUsage = uid.getProportionalSystemServiceUsage();
15239                 long timeUs = 0;
15240                 for (int j = systemServiceTimeAtCpuSpeeds.length - 1; j >= 0; j--) {
15241                     timeUs += systemServiceTimeAtCpuSpeeds[j] * proportionalSystemServiceUsage;
15242                 }
15243 
15244                 pw.print("  ");
15245                 pw.print(u);
15246                 pw.print(": ");
15247                 pw.println(timeUs / 1000);
15248             }
15249         }
15250     }
15251 
15252     /**
15253      * Dump measured charge stats
15254      */
15255     @GuardedBy("this")
15256     public void dumpMeasuredEnergyStatsLocked(PrintWriter pw) {
15257         pw.printf("On battery measured charge stats (microcoulombs) \n");
15258         if (mGlobalMeasuredEnergyStats == null) {
15259             pw.printf("    Not supported on this device.\n");
15260             return;
15261         }
15262 
15263         dumpMeasuredEnergyStatsLocked(pw, "global usage", mGlobalMeasuredEnergyStats);
15264 
15265         int size = mUidStats.size();
15266         for (int i = 0; i < size; i++) {
15267             final int u = mUidStats.keyAt(i);
15268             final Uid uid = mUidStats.get(u);
15269             final String name = "uid " + uid.mUid;
15270             dumpMeasuredEnergyStatsLocked(pw, name, uid.mUidMeasuredEnergyStats);
15271         }
15272     }
15273 
15274     /** Dump measured charge stats for the given uid */
15275     @GuardedBy("this")
15276     private void dumpMeasuredEnergyStatsLocked(PrintWriter pw, String name,
15277             MeasuredEnergyStats stats) {
15278         if (stats == null) return;
15279         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
15280         iPw.increaseIndent();
15281         iPw.printf("%s:\n", name);
15282         iPw.increaseIndent();
15283         stats.dump(iPw);
15284         iPw.decreaseIndent();
15285     }
15286 
15287     final ReentrantLock mWriteLock = new ReentrantLock();
15288 
15289     public void writeAsyncLocked() {
15290         writeStatsLocked(false);
15291         writeHistoryLocked(false);
15292     }
15293 
15294     public void writeSyncLocked() {
15295         writeStatsLocked(true);
15296         writeHistoryLocked(true);
15297     }
15298 
15299     void writeStatsLocked(boolean sync) {
15300         if (mStatsFile == null) {
15301             Slog.w(TAG,
15302                     "writeStatsLocked: no file associated with this instance");
15303             return;
15304         }
15305 
15306         if (mShuttingDown) {
15307             return;
15308         }
15309 
15310         final Parcel p = Parcel.obtain();
15311         final long start = SystemClock.uptimeMillis();
15312         writeSummaryToParcel(p, false/*history is in separate file*/);
15313         if (DEBUG) {
15314             Slog.d(TAG, "writeSummaryToParcel duration ms:"
15315                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
15316         }
15317         mLastWriteTimeMs = mClocks.elapsedRealtime();
15318         writeParcelToFileLocked(p, mStatsFile, sync);
15319     }
15320 
15321     void writeHistoryLocked(boolean sync) {
15322         if (mBatteryStatsHistory.getActiveFile() == null) {
15323             Slog.w(TAG,
15324                     "writeHistoryLocked: no history file associated with this instance");
15325             return;
15326         }
15327 
15328         if (mShuttingDown) {
15329             return;
15330         }
15331 
15332         Parcel p = Parcel.obtain();
15333         final long start = SystemClock.uptimeMillis();
15334         writeHistoryBuffer(p, true);
15335         if (DEBUG) {
15336             Slog.d(TAG, "writeHistoryBuffer duration ms:"
15337                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
15338         }
15339         writeParcelToFileLocked(p, mBatteryStatsHistory.getActiveFile(), sync);
15340     }
15341 
15342     void writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync) {
15343         if (sync) {
15344             commitPendingDataToDisk(p, file);
15345         } else {
15346             BackgroundThread.getHandler().post(new Runnable() {
15347                 @Override public void run() {
15348                     commitPendingDataToDisk(p, file);
15349                 }
15350             });
15351         }
15352     }
15353 
15354     private void commitPendingDataToDisk(Parcel p, AtomicFile file) {
15355         mWriteLock.lock();
15356         FileOutputStream fos = null;
15357         try {
15358             final long startTimeMs = SystemClock.uptimeMillis();
15359             fos = file.startWrite();
15360             fos.write(p.marshall());
15361             fos.flush();
15362             file.finishWrite(fos);
15363             if (DEBUG) {
15364                 Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
15365                         + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
15366                         + " bytes:" + p.dataSize());
15367             }
15368             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
15369                     "batterystats", SystemClock.uptimeMillis() - startTimeMs);
15370         } catch (IOException e) {
15371             Slog.w(TAG, "Error writing battery statistics", e);
15372             file.failWrite(fos);
15373         } finally {
15374             p.recycle();
15375             mWriteLock.unlock();
15376         }
15377     }
15378 
15379     @UnsupportedAppUsage
15380     public void readLocked() {
15381         if (mDailyFile != null) {
15382             readDailyStatsLocked();
15383         }
15384 
15385         if (mStatsFile == null) {
15386             Slog.w(TAG, "readLocked: no file associated with this instance");
15387             return;
15388         }
15389 
15390         final AtomicFile activeHistoryFile = mBatteryStatsHistory.getActiveFile();
15391         if (activeHistoryFile == null) {
15392             Slog.w(TAG,
15393                     "readLocked: no history file associated with this instance");
15394             return;
15395         }
15396 
15397         mUidStats.clear();
15398 
15399         Parcel stats = Parcel.obtain();
15400         try {
15401             final long start = SystemClock.uptimeMillis();
15402             if (mStatsFile.exists()) {
15403                 byte[] raw = mStatsFile.readFully();
15404                 stats.unmarshall(raw, 0, raw.length);
15405                 stats.setDataPosition(0);
15406                 readSummaryFromParcel(stats);
15407                 if (DEBUG) {
15408                     Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
15409                             + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
15410                             - start));
15411                 }
15412             }
15413         } catch (Exception e) {
15414             Slog.e(TAG, "Error reading battery statistics", e);
15415             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
15416                     RESET_REASON_CORRUPT_FILE);
15417         } finally {
15418             stats.recycle();
15419         }
15420 
15421         Parcel history = Parcel.obtain();
15422         try {
15423             final long start = SystemClock.uptimeMillis();
15424             if (activeHistoryFile.exists()) {
15425                 byte[] raw = activeHistoryFile.readFully();
15426                 if (raw.length > 0) {
15427                     history.unmarshall(raw, 0, raw.length);
15428                     history.setDataPosition(0);
15429                     readHistoryBuffer(history);
15430                 }
15431                 if (DEBUG) {
15432                     Slog.d(TAG, "readLocked history file::"
15433                             + activeHistoryFile.getBaseFile().getPath()
15434                             + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
15435                             - start));
15436                 }
15437             }
15438         } catch (Exception e) {
15439             Slog.e(TAG, "Error reading battery history", e);
15440             clearHistoryLocked();
15441             mBatteryStatsHistory.resetAllFiles();
15442         } finally {
15443             history.recycle();
15444         }
15445 
15446         mEndPlatformVersion = Build.ID;
15447 
15448         if (mHistoryBuffer.dataPosition() > 0
15449                 || mBatteryStatsHistory.getFilesNumbers().size() > 1) {
15450             mRecordingHistory = true;
15451             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
15452             final long uptimeMs = mClocks.uptimeMillis();
15453             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_START, mHistoryCur);
15454             startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
15455         }
15456 
15457         recordDailyStatsIfNeededLocked(false, mClocks.currentTimeMillis());
15458     }
15459 
15460     public int describeContents() {
15461         return 0;
15462     }
15463 
15464     void  readHistoryBuffer(Parcel in) throws ParcelFormatException {
15465         final int version = in.readInt();
15466         if (version != VERSION) {
15467             Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
15468                     + ", expected " + VERSION + "; erasing old stats");
15469             return;
15470         }
15471 
15472         final long historyBaseTime = in.readLong();
15473 
15474         mHistoryBuffer.setDataSize(0);
15475         mHistoryBuffer.setDataPosition(0);
15476 
15477         int bufSize = in.readInt();
15478         int curPos = in.dataPosition();
15479         if (bufSize >= (mConstants.MAX_HISTORY_BUFFER*100)) {
15480             throw new ParcelFormatException("File corrupt: history data buffer too large " +
15481                     bufSize);
15482         } else if ((bufSize&~3) != bufSize) {
15483             throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
15484                     bufSize);
15485         } else {
15486             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
15487                     + " bytes at " + curPos);
15488             mHistoryBuffer.appendFrom(in, curPos, bufSize);
15489             in.setDataPosition(curPos + bufSize);
15490         }
15491 
15492         if (DEBUG_HISTORY) {
15493             StringBuilder sb = new StringBuilder(128);
15494             sb.append("****************** OLD mHistoryBaseTimeMs: ");
15495             TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
15496             Slog.i(TAG, sb.toString());
15497         }
15498         mHistoryBaseTimeMs = historyBaseTime;
15499         if (DEBUG_HISTORY) {
15500             StringBuilder sb = new StringBuilder(128);
15501             sb.append("****************** NEW mHistoryBaseTimeMs: ");
15502             TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
15503             Slog.i(TAG, sb.toString());
15504         }
15505 
15506         // We are just arbitrarily going to insert 1 minute from the sample of
15507         // the last run until samples in this run.
15508         if (mHistoryBaseTimeMs > 0) {
15509             long oldnow = mClocks.elapsedRealtime();
15510             mHistoryBaseTimeMs = mHistoryBaseTimeMs - oldnow + 1;
15511             if (DEBUG_HISTORY) {
15512                 StringBuilder sb = new StringBuilder(128);
15513                 sb.append("****************** ADJUSTED mHistoryBaseTimeMs: ");
15514                 TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
15515                 Slog.i(TAG, sb.toString());
15516             }
15517         }
15518     }
15519 
15520     void writeHistoryBuffer(Parcel out, boolean inclData) {
15521         if (DEBUG_HISTORY) {
15522             StringBuilder sb = new StringBuilder(128);
15523             sb.append("****************** WRITING mHistoryBaseTimeMs: ");
15524             TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
15525             sb.append(" mLastHistoryElapsedRealtimeMs: ");
15526             TimeUtils.formatDuration(mLastHistoryElapsedRealtimeMs, sb);
15527             Slog.i(TAG, sb.toString());
15528         }
15529         out.writeInt(VERSION);
15530         out.writeLong(mHistoryBaseTimeMs + mLastHistoryElapsedRealtimeMs);
15531         if (!inclData) {
15532             out.writeInt(0);
15533             out.writeInt(0);
15534             return;
15535         }
15536 
15537         out.writeInt(mHistoryBuffer.dataSize());
15538         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
15539                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
15540         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
15541     }
15542 
15543     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
15544         final int version = in.readInt();
15545         if (version != VERSION) {
15546             Slog.w("BatteryStats", "readFromParcel: version got " + version
15547                 + ", expected " + VERSION + "; erasing old stats");
15548             return;
15549         }
15550 
15551         boolean inclHistory = in.readBoolean();
15552         if (inclHistory) {
15553             readHistoryBuffer(in);
15554             mBatteryStatsHistory.readFromParcel(in);
15555         }
15556 
15557         mHistoryTagPool.clear();
15558         mNextHistoryTagIdx = 0;
15559         mNumHistoryTagChars = 0;
15560 
15561         int numTags = in.readInt();
15562         for (int i=0; i<numTags; i++) {
15563             int idx = in.readInt();
15564             String str = in.readString();
15565             if (str == null) {
15566                 throw new ParcelFormatException("null history tag string");
15567             }
15568             int uid = in.readInt();
15569             HistoryTag tag = new HistoryTag();
15570             tag.string = str;
15571             tag.uid = uid;
15572             tag.poolIdx = idx;
15573             mHistoryTagPool.put(tag, idx);
15574             if (idx >= mNextHistoryTagIdx) {
15575                 mNextHistoryTagIdx = idx+1;
15576             }
15577             mNumHistoryTagChars += tag.string.length() + 1;
15578         }
15579 
15580         mStartCount = in.readInt();
15581         mUptimeUs = in.readLong();
15582         mRealtimeUs = in.readLong();
15583         mStartClockTimeMs = in.readLong();
15584         mStartPlatformVersion = in.readString();
15585         mEndPlatformVersion = in.readString();
15586         mOnBatteryTimeBase.readSummaryFromParcel(in);
15587         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
15588         mDischargeUnplugLevel = in.readInt();
15589         mDischargePlugLevel = in.readInt();
15590         mDischargeCurrentLevel = in.readInt();
15591         mCurrentBatteryLevel = in.readInt();
15592         mEstimatedBatteryCapacityMah = in.readInt();
15593         mLastLearnedBatteryCapacityUah = in.readInt();
15594         mMinLearnedBatteryCapacityUah = in.readInt();
15595         mMaxLearnedBatteryCapacityUah = in.readInt();
15596         mLowDischargeAmountSinceCharge = in.readInt();
15597         mHighDischargeAmountSinceCharge = in.readInt();
15598         mDischargeAmountScreenOnSinceCharge = in.readInt();
15599         mDischargeAmountScreenOffSinceCharge = in.readInt();
15600         mDischargeAmountScreenDozeSinceCharge = in.readInt();
15601         mDischargeStepTracker.readFromParcel(in);
15602         mChargeStepTracker.readFromParcel(in);
15603         mDailyDischargeStepTracker.readFromParcel(in);
15604         mDailyChargeStepTracker.readFromParcel(in);
15605         mDischargeCounter.readSummaryFromParcelLocked(in);
15606         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
15607         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
15608         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
15609         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
15610         int NPKG = in.readInt();
15611         if (NPKG > 0) {
15612             mDailyPackageChanges = new ArrayList<>(NPKG);
15613             while (NPKG > 0) {
15614                 NPKG--;
15615                 PackageChange pc = new PackageChange();
15616                 pc.mPackageName = in.readString();
15617                 pc.mUpdate = in.readInt() != 0;
15618                 pc.mVersionCode = in.readLong();
15619                 mDailyPackageChanges.add(pc);
15620             }
15621         } else {
15622             mDailyPackageChanges = null;
15623         }
15624         mDailyStartTimeMs = in.readLong();
15625         mNextMinDailyDeadlineMs = in.readLong();
15626         mNextMaxDailyDeadlineMs = in.readLong();
15627         mBatteryTimeToFullSeconds = in.readLong();
15628 
15629         /**
15630          * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
15631          *          later when {@link #initMeasuredEnergyStatsLocked} is called.
15632          */
15633         mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in);
15634 
15635         mStartCount++;
15636 
15637         mScreenState = Display.STATE_UNKNOWN;
15638         mScreenOnTimer.readSummaryFromParcelLocked(in);
15639         mScreenDozeTimer.readSummaryFromParcelLocked(in);
15640         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
15641             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
15642         }
15643         mInteractive = false;
15644         mInteractiveTimer.readSummaryFromParcelLocked(in);
15645         mPhoneOn = false;
15646         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
15647         mLongestLightIdleTimeMs = in.readLong();
15648         mLongestFullIdleTimeMs = in.readLong();
15649         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
15650         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
15651         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
15652         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
15653         mPhoneOnTimer.readSummaryFromParcelLocked(in);
15654         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
15655             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
15656         }
15657         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
15658         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
15659             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
15660         }
15661         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
15662             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
15663             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
15664         }
15665         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
15666         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
15667         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
15668         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
15669         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
15670         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
15671         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
15672         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
15673         mWifiOn = false;
15674         mWifiOnTimer.readSummaryFromParcelLocked(in);
15675         mGlobalWifiRunning = false;
15676         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
15677         for (int i=0; i<NUM_WIFI_STATES; i++) {
15678             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
15679         }
15680         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15681             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
15682         }
15683         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15684             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
15685         }
15686         mWifiActiveTimer.readSummaryFromParcelLocked(in);
15687         mWifiActivity.readSummaryFromParcel(in);
15688         for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
15689             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
15690         }
15691         mBluetoothActivity.readSummaryFromParcel(in);
15692         mModemActivity.readSummaryFromParcel(in);
15693         mHasWifiReporting = in.readInt() != 0;
15694         mHasBluetoothReporting = in.readInt() != 0;
15695         mHasModemReporting = in.readInt() != 0;
15696 
15697         mNumConnectivityChange = in.readInt();
15698         mFlashlightOnNesting = 0;
15699         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
15700         mCameraOnNesting = 0;
15701         mCameraOnTimer.readSummaryFromParcelLocked(in);
15702         mBluetoothScanNesting = 0;
15703         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
15704 
15705         int NRPMS = in.readInt();
15706         if (NRPMS > 10000) {
15707             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
15708         }
15709         for (int irpm = 0; irpm < NRPMS; irpm++) {
15710             if (in.readInt() != 0) {
15711                 String rpmName = in.readString();
15712                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
15713             }
15714         }
15715         int NSORPMS = in.readInt();
15716         if (NSORPMS > 10000) {
15717             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
15718         }
15719         for (int irpm = 0; irpm < NSORPMS; irpm++) {
15720             if (in.readInt() != 0) {
15721                 String rpmName = in.readString();
15722                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
15723             }
15724         }
15725 
15726         int NKW = in.readInt();
15727         if (NKW > 10000) {
15728             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
15729         }
15730         for (int ikw = 0; ikw < NKW; ikw++) {
15731             if (in.readInt() != 0) {
15732                 String kwltName = in.readString();
15733                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
15734             }
15735         }
15736 
15737         int NWR = in.readInt();
15738         if (NWR > 10000) {
15739             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
15740         }
15741         for (int iwr = 0; iwr < NWR; iwr++) {
15742             if (in.readInt() != 0) {
15743                 String reasonName = in.readString();
15744                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
15745             }
15746         }
15747 
15748         int NMS = in.readInt();
15749         for (int ims = 0; ims < NMS; ims++) {
15750             if (in.readInt() != 0) {
15751                 long kmstName = in.readLong();
15752                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
15753             }
15754         }
15755 
15756         final int NU = in.readInt();
15757         if (NU > 10000) {
15758             throw new ParcelFormatException("File corrupt: too many uids " + NU);
15759         }
15760         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
15761         final long uptimeMs = mClocks.uptimeMillis();
15762         for (int iu = 0; iu < NU; iu++) {
15763             int uid = in.readInt();
15764             Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
15765             mUidStats.put(uid, u);
15766 
15767             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
15768             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
15769 
15770             u.mWifiRunning = false;
15771             if (in.readInt() != 0) {
15772                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
15773             }
15774             u.mFullWifiLockOut = false;
15775             if (in.readInt() != 0) {
15776                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
15777             }
15778             u.mWifiScanStarted = false;
15779             if (in.readInt() != 0) {
15780                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
15781             }
15782             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
15783             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
15784                 if (in.readInt() != 0) {
15785                     u.makeWifiBatchedScanBin(i, null);
15786                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
15787                 }
15788             }
15789             u.mWifiMulticastWakelockCount = 0;
15790             if (in.readInt() != 0) {
15791                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
15792             }
15793             if (in.readInt() != 0) {
15794                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
15795             }
15796             if (in.readInt() != 0) {
15797                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
15798             }
15799             if (in.readInt() != 0) {
15800                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
15801             }
15802             if (in.readInt() != 0) {
15803                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
15804             }
15805             if (in.readInt() != 0) {
15806                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
15807             }
15808             if (in.readInt() != 0) {
15809                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
15810             }
15811             if (in.readInt() != 0) {
15812                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
15813             }
15814             if (in.readInt() != 0) {
15815                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
15816             }
15817             if (in.readInt() != 0) {
15818                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
15819             }
15820             if (in.readInt() != 0) {
15821                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
15822             }
15823             if (in.readInt() != 0) {
15824                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
15825             }
15826             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
15827             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
15828                 if (in.readInt() != 0) {
15829                     u.makeProcessState(i, null);
15830                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
15831                 }
15832             }
15833             if (in.readInt() != 0) {
15834                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
15835             }
15836 
15837             if (in.readInt() != 0) {
15838                 if (u.mUserActivityCounters == null) {
15839                     u.initUserActivityLocked();
15840                 }
15841                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
15842                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
15843                 }
15844             }
15845 
15846             if (in.readInt() != 0) {
15847                 if (u.mNetworkByteActivityCounters == null) {
15848                     u.initNetworkActivityLocked();
15849                 }
15850                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
15851                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
15852                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
15853                 }
15854                 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
15855                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
15856             }
15857 
15858             u.mUserCpuTime.readSummaryFromParcelLocked(in);
15859             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
15860 
15861             if (in.readInt() != 0) {
15862                 final int numClusters = in.readInt();
15863                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
15864                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
15865                 }
15866                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
15867                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
15868                 for (int cluster = 0; cluster < numClusters; cluster++) {
15869                     if (in.readInt() != 0) {
15870                         final int NSB = in.readInt();
15871                         if (mPowerProfile != null &&
15872                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
15873                             throw new ParcelFormatException("File corrupt: too many speed bins " +
15874                                     NSB);
15875                         }
15876 
15877                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
15878                         for (int speed = 0; speed < NSB; speed++) {
15879                             if (in.readInt() != 0) {
15880                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
15881                                         mOnBatteryTimeBase);
15882                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
15883                             }
15884                         }
15885                     } else {
15886                         u.mCpuClusterSpeedTimesUs[cluster] = null;
15887                     }
15888                 }
15889             } else {
15890                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
15891                 u.mCpuClusterSpeedTimesUs = null;
15892             }
15893 
15894             detachIfNotNull(u.mCpuFreqTimeMs);
15895             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
15896                     in, mOnBatteryTimeBase);
15897             detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
15898             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
15899                     in, mOnBatteryScreenOffTimeBase);
15900 
15901             u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
15902             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
15903 
15904             int length = in.readInt();
15905             if (length == Uid.NUM_PROCESS_STATE) {
15906                 detachIfNotNull(u.mProcStateTimeMs);
15907                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
15908                 for (int procState = 0; procState < length; ++procState) {
15909                     u.mProcStateTimeMs[procState]
15910                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
15911                                     in, mOnBatteryTimeBase);
15912                 }
15913             } else {
15914                 detachIfNotNull(u.mProcStateTimeMs);
15915                 u.mProcStateTimeMs = null;
15916             }
15917             length = in.readInt();
15918             if (length == Uid.NUM_PROCESS_STATE) {
15919                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
15920                 u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
15921                 for (int procState = 0; procState < length; ++procState) {
15922                     u.mProcStateScreenOffTimeMs[procState]
15923                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
15924                                     in, mOnBatteryScreenOffTimeBase);
15925                 }
15926             } else {
15927                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
15928                 u.mProcStateScreenOffTimeMs = null;
15929             }
15930 
15931             if (in.readInt() != 0) {
15932                 detachIfNotNull(u.mMobileRadioApWakeupCount);
15933                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
15934                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
15935             } else {
15936                 detachIfNotNull(u.mMobileRadioApWakeupCount);
15937                 u.mMobileRadioApWakeupCount = null;
15938             }
15939 
15940             if (in.readInt() != 0) {
15941                 detachIfNotNull(u.mWifiRadioApWakeupCount);
15942                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
15943                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
15944             } else {
15945                 detachIfNotNull(u.mWifiRadioApWakeupCount);
15946                 u.mWifiRadioApWakeupCount = null;
15947             }
15948 
15949             u.mUidMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in,
15950                     /* template */ mGlobalMeasuredEnergyStats);
15951 
15952             int NW = in.readInt();
15953             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
15954                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
15955             }
15956             for (int iw = 0; iw < NW; iw++) {
15957                 String wlName = in.readString();
15958                 u.readWakeSummaryFromParcelLocked(wlName, in);
15959             }
15960 
15961             int NS = in.readInt();
15962             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
15963                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
15964             }
15965             for (int is = 0; is < NS; is++) {
15966                 String name = in.readString();
15967                 u.readSyncSummaryFromParcelLocked(name, in);
15968             }
15969 
15970             int NJ = in.readInt();
15971             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
15972                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
15973             }
15974             for (int ij = 0; ij < NJ; ij++) {
15975                 String name = in.readString();
15976                 u.readJobSummaryFromParcelLocked(name, in);
15977             }
15978 
15979             u.readJobCompletionsFromParcelLocked(in);
15980 
15981             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
15982             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
15983             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
15984             detachIfNotNull(u.mJobsFreshnessBuckets);
15985             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
15986                 if (in.readInt() != 0) {
15987                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
15988                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
15989                 }
15990             }
15991 
15992             int NP = in.readInt();
15993             if (NP > 1000) {
15994                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
15995             }
15996             for (int is = 0; is < NP; is++) {
15997                 int seNumber = in.readInt();
15998                 if (in.readInt() != 0) {
15999                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
16000                 }
16001             }
16002 
16003             NP = in.readInt();
16004             if (NP > 1000) {
16005                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
16006             }
16007             for (int ip = 0; ip < NP; ip++) {
16008                 String procName = in.readString();
16009                 Uid.Proc p = u.getProcessStatsLocked(procName);
16010                 p.mUserTimeMs = in.readLong();
16011                 p.mSystemTimeMs = in.readLong();
16012                 p.mForegroundTimeMs = in.readLong();
16013                 p.mStarts = in.readInt();
16014                 p.mNumCrashes = in.readInt();
16015                 p.mNumAnrs = in.readInt();
16016                 p.readExcessivePowerFromParcelLocked(in);
16017             }
16018 
16019             NP = in.readInt();
16020             if (NP > 10000) {
16021                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
16022             }
16023             for (int ip = 0; ip < NP; ip++) {
16024                 String pkgName = in.readString();
16025                 detachIfNotNull(u.mPackageStats.get(pkgName));
16026                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
16027                 final int NWA = in.readInt();
16028                 if (NWA > 10000) {
16029                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
16030                 }
16031                 p.mWakeupAlarms.clear();
16032                 for (int iwa = 0; iwa < NWA; iwa++) {
16033                     String tag = in.readString();
16034                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
16035                     c.readSummaryFromParcelLocked(in);
16036                     p.mWakeupAlarms.put(tag, c);
16037                 }
16038                 NS = in.readInt();
16039                 if (NS > 10000) {
16040                     throw new ParcelFormatException("File corrupt: too many services " + NS);
16041                 }
16042                 for (int is = 0; is < NS; is++) {
16043                     String servName = in.readString();
16044                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
16045                     s.mStartTimeMs = in.readLong();
16046                     s.mStarts = in.readInt();
16047                     s.mLaunches = in.readInt();
16048                 }
16049             }
16050         }
16051 
16052         mBinderThreadCpuTimesUs =
16053                 LongSamplingCounterArray.readSummaryFromParcelLocked(in, mOnBatteryTimeBase);
16054     }
16055 
16056     /**
16057      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
16058      * disk.  This format does not allow a lossless round-trip.
16059      *
16060      * @param out the Parcel to be written to.
16061      */
16062     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
16063         pullPendingStateUpdatesLocked();
16064 
16065         // Pull the clock time.  This may update the time and make a new history entry
16066         // if we had originally pulled a time before the RTC was set.
16067         getStartClockTime();
16068 
16069         final long NOW_SYS = mClocks.uptimeMillis() * 1000;
16070         final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
16071 
16072         out.writeInt(VERSION);
16073 
16074         out.writeBoolean(inclHistory);
16075         if (inclHistory) {
16076             writeHistoryBuffer(out, true);
16077             mBatteryStatsHistory.writeToParcel(out);
16078         }
16079 
16080         out.writeInt(mHistoryTagPool.size());
16081         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
16082             HistoryTag tag = ent.getKey();
16083             out.writeInt(ent.getValue());
16084             out.writeString(tag.string);
16085             out.writeInt(tag.uid);
16086         }
16087 
16088         out.writeInt(mStartCount);
16089         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
16090         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
16091         out.writeLong(mStartClockTimeMs);
16092         out.writeString(mStartPlatformVersion);
16093         out.writeString(mEndPlatformVersion);
16094         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
16095         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
16096         out.writeInt(mDischargeUnplugLevel);
16097         out.writeInt(mDischargePlugLevel);
16098         out.writeInt(mDischargeCurrentLevel);
16099         out.writeInt(mCurrentBatteryLevel);
16100         out.writeInt(mEstimatedBatteryCapacityMah);
16101         out.writeInt(mLastLearnedBatteryCapacityUah);
16102         out.writeInt(mMinLearnedBatteryCapacityUah);
16103         out.writeInt(mMaxLearnedBatteryCapacityUah);
16104         out.writeInt(getLowDischargeAmountSinceCharge());
16105         out.writeInt(getHighDischargeAmountSinceCharge());
16106         out.writeInt(getDischargeAmountScreenOnSinceCharge());
16107         out.writeInt(getDischargeAmountScreenOffSinceCharge());
16108         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
16109         mDischargeStepTracker.writeToParcel(out);
16110         mChargeStepTracker.writeToParcel(out);
16111         mDailyDischargeStepTracker.writeToParcel(out);
16112         mDailyChargeStepTracker.writeToParcel(out);
16113         mDischargeCounter.writeSummaryFromParcelLocked(out);
16114         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
16115         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
16116         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
16117         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
16118         if (mDailyPackageChanges != null) {
16119             final int NPKG = mDailyPackageChanges.size();
16120             out.writeInt(NPKG);
16121             for (int i=0; i<NPKG; i++) {
16122                 PackageChange pc = mDailyPackageChanges.get(i);
16123                 out.writeString(pc.mPackageName);
16124                 out.writeInt(pc.mUpdate ? 1 : 0);
16125                 out.writeLong(pc.mVersionCode);
16126             }
16127         } else {
16128             out.writeInt(0);
16129         }
16130         out.writeLong(mDailyStartTimeMs);
16131         out.writeLong(mNextMinDailyDeadlineMs);
16132         out.writeLong(mNextMaxDailyDeadlineMs);
16133         out.writeLong(mBatteryTimeToFullSeconds);
16134 
16135         MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out, false, false);
16136 
16137         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16138         mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16139         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16140             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16141         }
16142         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16143         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16144         out.writeLong(mLongestLightIdleTimeMs);
16145         out.writeLong(mLongestFullIdleTimeMs);
16146         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16147         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16148         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16149         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16150         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16151         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
16152             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16153         }
16154         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16155         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
16156             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16157         }
16158         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16159             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
16160             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
16161         }
16162         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16163         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16164         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
16165         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
16166         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
16167         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16168         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16169         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16170         for (int i=0; i<NUM_WIFI_STATES; i++) {
16171             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16172         }
16173         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
16174             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16175         }
16176         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16177             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16178         }
16179         mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16180         mWifiActivity.writeSummaryToParcel(out);
16181         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
16182             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16183         }
16184         mBluetoothActivity.writeSummaryToParcel(out);
16185         mModemActivity.writeSummaryToParcel(out);
16186         out.writeInt(mHasWifiReporting ? 1 : 0);
16187         out.writeInt(mHasBluetoothReporting ? 1 : 0);
16188         out.writeInt(mHasModemReporting ? 1 : 0);
16189 
16190         out.writeInt(mNumConnectivityChange);
16191         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16192         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16193         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16194 
16195         out.writeInt(mRpmStats.size());
16196         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
16197             Timer rpmt = ent.getValue();
16198             if (rpmt != null) {
16199                 out.writeInt(1);
16200                 out.writeString(ent.getKey());
16201                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16202             } else {
16203                 out.writeInt(0);
16204             }
16205         }
16206         out.writeInt(mScreenOffRpmStats.size());
16207         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
16208             Timer rpmt = ent.getValue();
16209             if (rpmt != null) {
16210                 out.writeInt(1);
16211                 out.writeString(ent.getKey());
16212                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16213             } else {
16214                 out.writeInt(0);
16215             }
16216         }
16217 
16218         out.writeInt(mKernelWakelockStats.size());
16219         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
16220             Timer kwlt = ent.getValue();
16221             if (kwlt != null) {
16222                 out.writeInt(1);
16223                 out.writeString(ent.getKey());
16224                 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16225             } else {
16226                 out.writeInt(0);
16227             }
16228         }
16229 
16230         out.writeInt(mWakeupReasonStats.size());
16231         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
16232             SamplingTimer timer = ent.getValue();
16233             if (timer != null) {
16234                 out.writeInt(1);
16235                 out.writeString(ent.getKey());
16236                 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16237             } else {
16238                 out.writeInt(0);
16239             }
16240         }
16241 
16242         out.writeInt(mKernelMemoryStats.size());
16243         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
16244             Timer kmt = mKernelMemoryStats.valueAt(i);
16245             if (kmt != null) {
16246                 out.writeInt(1);
16247                 out.writeLong(mKernelMemoryStats.keyAt(i));
16248                 kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16249             } else {
16250                 out.writeInt(0);
16251             }
16252         }
16253 
16254         final int NU = mUidStats.size();
16255         out.writeInt(NU);
16256         for (int iu = 0; iu < NU; iu++) {
16257             out.writeInt(mUidStats.keyAt(iu));
16258             Uid u = mUidStats.valueAt(iu);
16259 
16260             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
16261             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
16262 
16263             if (u.mWifiRunningTimer != null) {
16264                 out.writeInt(1);
16265                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16266             } else {
16267                 out.writeInt(0);
16268             }
16269             if (u.mFullWifiLockTimer != null) {
16270                 out.writeInt(1);
16271                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16272             } else {
16273                 out.writeInt(0);
16274             }
16275             if (u.mWifiScanTimer != null) {
16276                 out.writeInt(1);
16277                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16278             } else {
16279                 out.writeInt(0);
16280             }
16281             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
16282                 if (u.mWifiBatchedScanTimer[i] != null) {
16283                     out.writeInt(1);
16284                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16285                 } else {
16286                     out.writeInt(0);
16287                 }
16288             }
16289             if (u.mWifiMulticastTimer != null) {
16290                 out.writeInt(1);
16291                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16292             } else {
16293                 out.writeInt(0);
16294             }
16295             if (u.mAudioTurnedOnTimer != null) {
16296                 out.writeInt(1);
16297                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16298             } else {
16299                 out.writeInt(0);
16300             }
16301             if (u.mVideoTurnedOnTimer != null) {
16302                 out.writeInt(1);
16303                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16304             } else {
16305                 out.writeInt(0);
16306             }
16307             if (u.mFlashlightTurnedOnTimer != null) {
16308                 out.writeInt(1);
16309                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16310             } else {
16311                 out.writeInt(0);
16312             }
16313             if (u.mCameraTurnedOnTimer != null) {
16314                 out.writeInt(1);
16315                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16316             } else {
16317                 out.writeInt(0);
16318             }
16319             if (u.mForegroundActivityTimer != null) {
16320                 out.writeInt(1);
16321                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16322             } else {
16323                 out.writeInt(0);
16324             }
16325             if (u.mForegroundServiceTimer != null) {
16326                 out.writeInt(1);
16327                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16328             } else {
16329                 out.writeInt(0);
16330             }
16331             if (u.mAggregatedPartialWakelockTimer != null) {
16332                 out.writeInt(1);
16333                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16334             } else {
16335                 out.writeInt(0);
16336             }
16337             if (u.mBluetoothScanTimer != null) {
16338                 out.writeInt(1);
16339                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16340             } else {
16341                 out.writeInt(0);
16342             }
16343             if (u.mBluetoothUnoptimizedScanTimer != null) {
16344                 out.writeInt(1);
16345                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16346             } else {
16347                 out.writeInt(0);
16348             }
16349             if (u.mBluetoothScanResultCounter != null) {
16350                 out.writeInt(1);
16351                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
16352             } else {
16353                 out.writeInt(0);
16354             }
16355             if (u.mBluetoothScanResultBgCounter != null) {
16356                 out.writeInt(1);
16357                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
16358             } else {
16359                 out.writeInt(0);
16360             }
16361             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
16362                 if (u.mProcessStateTimer[i] != null) {
16363                     out.writeInt(1);
16364                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16365                 } else {
16366                     out.writeInt(0);
16367                 }
16368             }
16369             if (u.mVibratorOnTimer != null) {
16370                 out.writeInt(1);
16371                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16372             } else {
16373                 out.writeInt(0);
16374             }
16375 
16376             if (u.mUserActivityCounters == null) {
16377                 out.writeInt(0);
16378             } else {
16379                 out.writeInt(1);
16380                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
16381                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
16382                 }
16383             }
16384 
16385             if (u.mNetworkByteActivityCounters == null) {
16386                 out.writeInt(0);
16387             } else {
16388                 out.writeInt(1);
16389                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16390                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
16391                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
16392                 }
16393                 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
16394                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
16395             }
16396 
16397             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
16398             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
16399 
16400             if (u.mCpuClusterSpeedTimesUs != null) {
16401                 out.writeInt(1);
16402                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
16403                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
16404                     if (cpuSpeeds != null) {
16405                         out.writeInt(1);
16406                         out.writeInt(cpuSpeeds.length);
16407                         for (LongSamplingCounter c : cpuSpeeds) {
16408                             if (c != null) {
16409                                 out.writeInt(1);
16410                                 c.writeSummaryFromParcelLocked(out);
16411                             } else {
16412                                 out.writeInt(0);
16413                             }
16414                         }
16415                     } else {
16416                         out.writeInt(0);
16417                     }
16418                 }
16419             } else {
16420                 out.writeInt(0);
16421             }
16422 
16423             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
16424             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
16425 
16426             u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
16427             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
16428 
16429             if (u.mProcStateTimeMs != null) {
16430                 out.writeInt(u.mProcStateTimeMs.length);
16431                 for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
16432                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
16433                 }
16434             } else {
16435                 out.writeInt(0);
16436             }
16437             if (u.mProcStateScreenOffTimeMs != null) {
16438                 out.writeInt(u.mProcStateScreenOffTimeMs.length);
16439                 for (LongSamplingCounterArray counters : u.mProcStateScreenOffTimeMs) {
16440                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
16441                 }
16442             } else {
16443                 out.writeInt(0);
16444             }
16445 
16446             if (u.mMobileRadioApWakeupCount != null) {
16447                 out.writeInt(1);
16448                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
16449             } else {
16450                 out.writeInt(0);
16451             }
16452 
16453             if (u.mWifiRadioApWakeupCount != null) {
16454                 out.writeInt(1);
16455                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
16456             } else {
16457                 out.writeInt(0);
16458             }
16459 
16460             MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out, true, true);
16461 
16462             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
16463             int NW = wakeStats.size();
16464             out.writeInt(NW);
16465             for (int iw=0; iw<NW; iw++) {
16466                 out.writeString(wakeStats.keyAt(iw));
16467                 Uid.Wakelock wl = wakeStats.valueAt(iw);
16468                 if (wl.mTimerFull != null) {
16469                     out.writeInt(1);
16470                     wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16471                 } else {
16472                     out.writeInt(0);
16473                 }
16474                 if (wl.mTimerPartial != null) {
16475                     out.writeInt(1);
16476                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16477                 } else {
16478                     out.writeInt(0);
16479                 }
16480                 if (wl.mTimerWindow != null) {
16481                     out.writeInt(1);
16482                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16483                 } else {
16484                     out.writeInt(0);
16485                 }
16486                 if (wl.mTimerDraw != null) {
16487                     out.writeInt(1);
16488                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16489                 } else {
16490                     out.writeInt(0);
16491                 }
16492             }
16493 
16494             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
16495             int NS = syncStats.size();
16496             out.writeInt(NS);
16497             for (int is=0; is<NS; is++) {
16498                 out.writeString(syncStats.keyAt(is));
16499                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16500             }
16501 
16502             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
16503             int NJ = jobStats.size();
16504             out.writeInt(NJ);
16505             for (int ij=0; ij<NJ; ij++) {
16506                 out.writeString(jobStats.keyAt(ij));
16507                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16508             }
16509 
16510             u.writeJobCompletionsToParcelLocked(out);
16511 
16512             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
16513             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
16514             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
16515             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
16516                 if (u.mJobsFreshnessBuckets[i] != null) {
16517                     out.writeInt(1);
16518                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
16519                 } else {
16520                     out.writeInt(0);
16521                 }
16522             }
16523 
16524             int NSE = u.mSensorStats.size();
16525             out.writeInt(NSE);
16526             for (int ise=0; ise<NSE; ise++) {
16527                 out.writeInt(u.mSensorStats.keyAt(ise));
16528                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
16529                 if (se.mTimer != null) {
16530                     out.writeInt(1);
16531                     se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16532                 } else {
16533                     out.writeInt(0);
16534                 }
16535             }
16536 
16537             int NP = u.mProcessStats.size();
16538             out.writeInt(NP);
16539             for (int ip=0; ip<NP; ip++) {
16540                 out.writeString(u.mProcessStats.keyAt(ip));
16541                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
16542                 out.writeLong(ps.mUserTimeMs);
16543                 out.writeLong(ps.mSystemTimeMs);
16544                 out.writeLong(ps.mForegroundTimeMs);
16545                 out.writeInt(ps.mStarts);
16546                 out.writeInt(ps.mNumCrashes);
16547                 out.writeInt(ps.mNumAnrs);
16548                 ps.writeExcessivePowerToParcelLocked(out);
16549             }
16550 
16551             NP = u.mPackageStats.size();
16552             out.writeInt(NP);
16553             if (NP > 0) {
16554                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
16555                     : u.mPackageStats.entrySet()) {
16556                     out.writeString(ent.getKey());
16557                     Uid.Pkg ps = ent.getValue();
16558                     final int NWA = ps.mWakeupAlarms.size();
16559                     out.writeInt(NWA);
16560                     for (int iwa=0; iwa<NWA; iwa++) {
16561                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
16562                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
16563                     }
16564                     NS = ps.mServiceStats.size();
16565                     out.writeInt(NS);
16566                     for (int is=0; is<NS; is++) {
16567                         out.writeString(ps.mServiceStats.keyAt(is));
16568                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
16569                         long time = ss.getStartTimeToNowLocked(
16570                                 mOnBatteryTimeBase.getUptime(NOW_SYS) / 1000);
16571                         out.writeLong(time);
16572                         out.writeInt(ss.mStarts);
16573                         out.writeInt(ss.mLaunches);
16574                     }
16575                 }
16576             }
16577         }
16578 
16579         LongSamplingCounterArray.writeSummaryToParcelLocked(out, mBinderThreadCpuTimesUs);
16580     }
16581 
16582     public void readFromParcel(Parcel in) {
16583         readFromParcelLocked(in);
16584     }
16585 
16586     void readFromParcelLocked(Parcel in) {
16587         int magic = in.readInt();
16588         if (magic != MAGIC) {
16589             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
16590         }
16591 
16592         readHistoryBuffer(in);
16593         mBatteryStatsHistory.readFromParcel(in);
16594 
16595         mStartCount = in.readInt();
16596         mStartClockTimeMs = in.readLong();
16597         mStartPlatformVersion = in.readString();
16598         mEndPlatformVersion = in.readString();
16599         mUptimeUs = in.readLong();
16600         mUptimeStartUs = in.readLong();
16601         mRealtimeUs = in.readLong();
16602         mRealtimeStartUs = in.readLong();
16603         mOnBattery = in.readInt() != 0;
16604         mEstimatedBatteryCapacityMah = in.readInt();
16605         mLastLearnedBatteryCapacityUah = in.readInt();
16606         mMinLearnedBatteryCapacityUah = in.readInt();
16607         mMaxLearnedBatteryCapacityUah = in.readInt();
16608         mOnBatteryInternal = false; // we are no longer really running.
16609         mOnBatteryTimeBase.readFromParcel(in);
16610         mOnBatteryScreenOffTimeBase.readFromParcel(in);
16611 
16612         mScreenState = Display.STATE_UNKNOWN;
16613         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
16614         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
16615         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16616             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
16617                     mOnBatteryTimeBase, in);
16618         }
16619         mInteractive = false;
16620         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
16621         mPhoneOn = false;
16622         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
16623                 mOnBatteryTimeBase, in);
16624         mLongestLightIdleTimeMs = in.readLong();
16625         mLongestFullIdleTimeMs = in.readLong();
16626         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
16627                 mOnBatteryTimeBase, in);
16628         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
16629                 mOnBatteryTimeBase, in);
16630         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
16631                 mOnBatteryTimeBase, in);
16632         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
16633         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
16634         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
16635             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
16636                     null, mOnBatteryTimeBase, in);
16637         }
16638         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
16639                 mOnBatteryTimeBase, in);
16640         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
16641             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
16642                     null, mOnBatteryTimeBase, in);
16643         }
16644         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16645             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
16646             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
16647         }
16648         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
16649         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
16650                 mOnBatteryTimeBase, in);
16651         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
16652                 mOnBatteryTimeBase, in);
16653         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
16654         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
16655         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
16656         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null, -4, null,
16657                 mOnBatteryTimeBase, in);
16658         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
16659         mWifiOn = false;
16660         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
16661         mGlobalWifiRunning = false;
16662         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
16663                 mOnBatteryTimeBase, in);
16664         for (int i=0; i<NUM_WIFI_STATES; i++) {
16665             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
16666                     null, mOnBatteryTimeBase, in);
16667         }
16668         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
16669             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
16670                     null, mOnBatteryTimeBase, in);
16671         }
16672         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16673             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
16674                     null, mOnBatteryTimeBase, in);
16675         }
16676         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null,
16677             mOnBatteryTimeBase, in);
16678         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
16679                 NUM_WIFI_TX_LEVELS, in);
16680         for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
16681             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
16682                 null, mOnBatteryTimeBase, in);
16683         }
16684         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
16685                 NUM_BT_TX_LEVELS, in);
16686         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
16687                 ModemActivityInfo.getNumTxPowerLevels(), in);
16688         mHasWifiReporting = in.readInt() != 0;
16689         mHasBluetoothReporting = in.readInt() != 0;
16690         mHasModemReporting = in.readInt() != 0;
16691 
16692         mNumConnectivityChange = in.readInt();
16693         mAudioOnNesting = 0;
16694         // TODO: It's likely a mistake that mAudioOnTimer/mVideoOnTimer don't write/read to parcel!
16695         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
16696         mVideoOnNesting = 0;
16697         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
16698         mFlashlightOnNesting = 0;
16699         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
16700         mCameraOnNesting = 0;
16701         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
16702         mBluetoothScanNesting = 0;
16703         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
16704         mDischargeUnplugLevel = in.readInt();
16705         mDischargePlugLevel = in.readInt();
16706         mDischargeCurrentLevel = in.readInt();
16707         mCurrentBatteryLevel = in.readInt();
16708         mLowDischargeAmountSinceCharge = in.readInt();
16709         mHighDischargeAmountSinceCharge = in.readInt();
16710         mDischargeAmountScreenOn = in.readInt();
16711         mDischargeAmountScreenOnSinceCharge = in.readInt();
16712         mDischargeAmountScreenOff = in.readInt();
16713         mDischargeAmountScreenOffSinceCharge = in.readInt();
16714         mDischargeAmountScreenDoze = in.readInt();
16715         mDischargeAmountScreenDozeSinceCharge = in.readInt();
16716         mDischargeStepTracker.readFromParcel(in);
16717         mChargeStepTracker.readFromParcel(in);
16718         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
16719         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
16720         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
16721         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
16722         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
16723         mLastWriteTimeMs = in.readLong();
16724         mBatteryTimeToFullSeconds = in.readLong();
16725 
16726         if (in.readInt() != 0) {
16727             mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(in);
16728         }
16729 
16730         mRpmStats.clear();
16731         int NRPMS = in.readInt();
16732         for (int irpm = 0; irpm < NRPMS; irpm++) {
16733             if (in.readInt() != 0) {
16734                 String rpmName = in.readString();
16735                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
16736                 mRpmStats.put(rpmName, rpmt);
16737             }
16738         }
16739         mScreenOffRpmStats.clear();
16740         int NSORPMS = in.readInt();
16741         for (int irpm = 0; irpm < NSORPMS; irpm++) {
16742             if (in.readInt() != 0) {
16743                 String rpmName = in.readString();
16744                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
16745                 mScreenOffRpmStats.put(rpmName, rpmt);
16746             }
16747         }
16748 
16749         mKernelWakelockStats.clear();
16750         int NKW = in.readInt();
16751         for (int ikw = 0; ikw < NKW; ikw++) {
16752             if (in.readInt() != 0) {
16753                 String wakelockName = in.readString();
16754                 SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
16755                 mKernelWakelockStats.put(wakelockName, kwlt);
16756             }
16757         }
16758 
16759         mWakeupReasonStats.clear();
16760         int NWR = in.readInt();
16761         for (int iwr = 0; iwr < NWR; iwr++) {
16762             if (in.readInt() != 0) {
16763                 String reasonName = in.readString();
16764                 SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
16765                 mWakeupReasonStats.put(reasonName, timer);
16766             }
16767         }
16768 
16769         mKernelMemoryStats.clear();
16770         int nmt = in.readInt();
16771         for (int imt = 0; imt < nmt; imt++) {
16772             if (in.readInt() != 0) {
16773                 Long bucket = in.readLong();
16774                 SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
16775                 mKernelMemoryStats.put(bucket, kmt);
16776             }
16777         }
16778 
16779         mPartialTimers.clear();
16780         mFullTimers.clear();
16781         mWindowTimers.clear();
16782         mWifiRunningTimers.clear();
16783         mFullWifiLockTimers.clear();
16784         mWifiScanTimers.clear();
16785         mWifiBatchedScanTimers.clear();
16786         mWifiMulticastTimers.clear();
16787         mAudioTurnedOnTimers.clear();
16788         mVideoTurnedOnTimers.clear();
16789         mFlashlightTurnedOnTimers.clear();
16790         mCameraTurnedOnTimers.clear();
16791 
16792         int numUids = in.readInt();
16793         mUidStats.clear();
16794         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
16795         final long uptimeMs = mClocks.uptimeMillis();
16796         for (int i = 0; i < numUids; i++) {
16797             int uid = in.readInt();
16798             Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
16799             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
16800             mUidStats.append(uid, u);
16801         }
16802 
16803         mBinderThreadCpuTimesUs = LongSamplingCounterArray.readFromParcel(in, mOnBatteryTimeBase);
16804     }
16805 
16806     public void writeToParcel(Parcel out, int flags) {
16807         writeToParcelLocked(out, true, flags);
16808     }
16809 
16810     public void writeToParcelWithoutUids(Parcel out, int flags) {
16811         writeToParcelLocked(out, false, flags);
16812     }
16813 
16814     @SuppressWarnings("unused")
16815     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
16816         // Need to update with current kernel wake lock counts.
16817         pullPendingStateUpdatesLocked();
16818 
16819         updateSystemServiceCallStats();
16820 
16821         // Pull the clock time.  This may update the time and make a new history entry
16822         // if we had originally pulled a time before the RTC was set.
16823         getStartClockTime();
16824 
16825         final long uSecUptime = mClocks.uptimeMillis() * 1000;
16826         final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
16827         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
16828         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
16829 
16830         out.writeInt(MAGIC);
16831 
16832         writeHistoryBuffer(out, true);
16833         mBatteryStatsHistory.writeToParcel(out);
16834 
16835         out.writeInt(mStartCount);
16836         out.writeLong(mStartClockTimeMs);
16837         out.writeString(mStartPlatformVersion);
16838         out.writeString(mEndPlatformVersion);
16839         out.writeLong(mUptimeUs);
16840         out.writeLong(mUptimeStartUs);
16841         out.writeLong(mRealtimeUs);
16842         out.writeLong(mRealtimeStartUs);
16843         out.writeInt(mOnBattery ? 1 : 0);
16844         out.writeInt(mEstimatedBatteryCapacityMah);
16845         out.writeInt(mLastLearnedBatteryCapacityUah);
16846         out.writeInt(mMinLearnedBatteryCapacityUah);
16847         out.writeInt(mMaxLearnedBatteryCapacityUah);
16848         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
16849         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
16850 
16851         mScreenOnTimer.writeToParcel(out, uSecRealtime);
16852         mScreenDozeTimer.writeToParcel(out, uSecRealtime);
16853         for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16854             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
16855         }
16856         mInteractiveTimer.writeToParcel(out, uSecRealtime);
16857         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
16858         out.writeLong(mLongestLightIdleTimeMs);
16859         out.writeLong(mLongestFullIdleTimeMs);
16860         mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
16861         mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
16862         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
16863         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
16864         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
16865         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
16866             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
16867         }
16868         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
16869         for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; i++) {
16870             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
16871         }
16872         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16873             mNetworkByteActivityCounters[i].writeToParcel(out);
16874             mNetworkPacketActivityCounters[i].writeToParcel(out);
16875         }
16876         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
16877         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
16878         mMobileRadioActiveAdjustedTime.writeToParcel(out);
16879         mMobileRadioActiveUnknownTime.writeToParcel(out);
16880         mMobileRadioActiveUnknownCount.writeToParcel(out);
16881         mWifiMulticastWakelockTimer.writeToParcel(out, uSecRealtime);
16882         mWifiOnTimer.writeToParcel(out, uSecRealtime);
16883         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
16884         for (int i = 0; i < NUM_WIFI_STATES; i++) {
16885             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
16886         }
16887         for (int i = 0; i < NUM_WIFI_SUPPL_STATES; i++) {
16888             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
16889         }
16890         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16891             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
16892         }
16893         mWifiActiveTimer.writeToParcel(out, uSecRealtime);
16894         mWifiActivity.writeToParcel(out, 0);
16895         for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
16896             mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
16897         }
16898         mBluetoothActivity.writeToParcel(out, 0);
16899         mModemActivity.writeToParcel(out, 0);
16900         out.writeInt(mHasWifiReporting ? 1 : 0);
16901         out.writeInt(mHasBluetoothReporting ? 1 : 0);
16902         out.writeInt(mHasModemReporting ? 1 : 0);
16903 
16904         out.writeInt(mNumConnectivityChange);
16905         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
16906         mCameraOnTimer.writeToParcel(out, uSecRealtime);
16907         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
16908         out.writeInt(mDischargeUnplugLevel);
16909         out.writeInt(mDischargePlugLevel);
16910         out.writeInt(mDischargeCurrentLevel);
16911         out.writeInt(mCurrentBatteryLevel);
16912         out.writeInt(mLowDischargeAmountSinceCharge);
16913         out.writeInt(mHighDischargeAmountSinceCharge);
16914         out.writeInt(mDischargeAmountScreenOn);
16915         out.writeInt(mDischargeAmountScreenOnSinceCharge);
16916         out.writeInt(mDischargeAmountScreenOff);
16917         out.writeInt(mDischargeAmountScreenOffSinceCharge);
16918         out.writeInt(mDischargeAmountScreenDoze);
16919         out.writeInt(mDischargeAmountScreenDozeSinceCharge);
16920         mDischargeStepTracker.writeToParcel(out);
16921         mChargeStepTracker.writeToParcel(out);
16922         mDischargeCounter.writeToParcel(out);
16923         mDischargeScreenOffCounter.writeToParcel(out);
16924         mDischargeScreenDozeCounter.writeToParcel(out);
16925         mDischargeLightDozeCounter.writeToParcel(out);
16926         mDischargeDeepDozeCounter.writeToParcel(out);
16927         out.writeLong(mLastWriteTimeMs);
16928         out.writeLong(mBatteryTimeToFullSeconds);
16929 
16930         if (mGlobalMeasuredEnergyStats != null) {
16931             out.writeInt(1);
16932             mGlobalMeasuredEnergyStats.writeToParcel(out);
16933         } else {
16934             out.writeInt(0);
16935         }
16936 
16937         out.writeInt(mRpmStats.size());
16938         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
16939             SamplingTimer rpmt = ent.getValue();
16940             if (rpmt != null) {
16941                 out.writeInt(1);
16942                 out.writeString(ent.getKey());
16943                 rpmt.writeToParcel(out, uSecRealtime);
16944             } else {
16945                 out.writeInt(0);
16946             }
16947         }
16948         out.writeInt(mScreenOffRpmStats.size());
16949         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
16950             SamplingTimer rpmt = ent.getValue();
16951             if (rpmt != null) {
16952                 out.writeInt(1);
16953                 out.writeString(ent.getKey());
16954                 rpmt.writeToParcel(out, uSecRealtime);
16955             } else {
16956                 out.writeInt(0);
16957             }
16958         }
16959 
16960         if (inclUids) {
16961             out.writeInt(mKernelWakelockStats.size());
16962             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
16963                 SamplingTimer kwlt = ent.getValue();
16964                 if (kwlt != null) {
16965                     out.writeInt(1);
16966                     out.writeString(ent.getKey());
16967                     kwlt.writeToParcel(out, uSecRealtime);
16968                 } else {
16969                     out.writeInt(0);
16970                 }
16971             }
16972             out.writeInt(mWakeupReasonStats.size());
16973             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
16974                 SamplingTimer timer = ent.getValue();
16975                 if (timer != null) {
16976                     out.writeInt(1);
16977                     out.writeString(ent.getKey());
16978                     timer.writeToParcel(out, uSecRealtime);
16979                 } else {
16980                     out.writeInt(0);
16981                 }
16982             }
16983         } else {
16984             out.writeInt(0);
16985             out.writeInt(0);
16986         }
16987 
16988         out.writeInt(mKernelMemoryStats.size());
16989         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
16990             SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
16991             if (kmt != null) {
16992                 out.writeInt(1);
16993                 out.writeLong(mKernelMemoryStats.keyAt(i));
16994                 kmt.writeToParcel(out, uSecRealtime);
16995             } else {
16996                 out.writeInt(0);
16997             }
16998         }
16999 
17000         if (inclUids) {
17001             int size = mUidStats.size();
17002             out.writeInt(size);
17003             for (int i = 0; i < size; i++) {
17004                 out.writeInt(mUidStats.keyAt(i));
17005                 Uid uid = mUidStats.valueAt(i);
17006 
17007                 uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
17008             }
17009         } else {
17010             out.writeInt(0);
17011         }
17012         LongSamplingCounterArray.writeToParcel(out, mBinderThreadCpuTimesUs);
17013     }
17014 
17015     private void writeCpuSpeedCountersToParcel(Parcel out, LongSamplingCounter[][] counters) {
17016         if (counters == null) {
17017             out.writeInt(0);
17018             return;
17019         }
17020 
17021         out.writeInt(1);
17022         out.writeInt(counters.length);
17023         for (int i = 0; i < counters.length; i++) {
17024             LongSamplingCounter[] counterArray = counters[i];
17025             if (counterArray == null) {
17026                 out.writeInt(0);
17027                 continue;
17028             }
17029 
17030             out.writeInt(1);
17031             out.writeInt(counterArray.length);
17032             for (int j = 0; j < counterArray.length; j++) {
17033                 LongSamplingCounter c = counterArray[j];
17034                 if (c != null) {
17035                     out.writeInt(1);
17036                     c.writeToParcel(out);
17037                 } else {
17038                     out.writeInt(0);
17039                 }
17040             }
17041         }
17042     }
17043 
17044     private LongSamplingCounter[][] readCpuSpeedCountersFromParcel(Parcel in) {
17045         LongSamplingCounter[][] counters;
17046         if (in.readInt() != 0) {
17047             int numCpuClusters = in.readInt();
17048             if (mPowerProfile != null
17049                     && mPowerProfile.getNumCpuClusters() != numCpuClusters) {
17050                 throw new ParcelFormatException("Incompatible number of cpu clusters");
17051             }
17052 
17053             counters = new LongSamplingCounter[numCpuClusters][];
17054             for (int cluster = 0; cluster < numCpuClusters; cluster++) {
17055                 if (in.readInt() != 0) {
17056                     int numSpeeds = in.readInt();
17057                     if (mPowerProfile != null
17058                             && mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
17059                         throw new ParcelFormatException("Incompatible number of cpu speeds");
17060                     }
17061 
17062                     final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
17063                     counters[cluster] = cpuSpeeds;
17064                     for (int speed = 0; speed < numSpeeds; speed++) {
17065                         if (in.readInt() != 0) {
17066                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase, in);
17067                         }
17068                     }
17069                 } else {
17070                     counters[cluster] = null;
17071                 }
17072             }
17073         } else {
17074             counters = null;
17075         }
17076 
17077         return counters;
17078     }
17079 
17080     @UnsupportedAppUsage
17081     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
17082         new Parcelable.Creator<BatteryStatsImpl>() {
17083         public BatteryStatsImpl createFromParcel(Parcel in) {
17084             return new BatteryStatsImpl(in);
17085         }
17086 
17087         public BatteryStatsImpl[] newArray(int size) {
17088             return new BatteryStatsImpl[size];
17089         }
17090     };
17091 
17092     public void prepareForDumpLocked() {
17093         // Need to retrieve current kernel wake lock stats before printing.
17094         pullPendingStateUpdatesLocked();
17095 
17096         // Pull the clock time.  This may update the time and make a new history entry
17097         // if we had originally pulled a time before the RTC was set.
17098         getStartClockTime();
17099 
17100         updateSystemServiceCallStats();
17101     }
17102 
17103     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
17104         if (DEBUG) {
17105             pw.println("mOnBatteryTimeBase:");
17106             mOnBatteryTimeBase.dump(pw, "  ");
17107             pw.println("mOnBatteryScreenOffTimeBase:");
17108             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
17109             Printer pr = new PrintWriterPrinter(pw);
17110             pr.println("*** Screen on timer:");
17111             mScreenOnTimer.logState(pr, "  ");
17112             pr.println("*** Screen doze timer:");
17113             mScreenDozeTimer.logState(pr, "  ");
17114             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
17115                 pr.println("*** Screen brightness #" + i + ":");
17116                 mScreenBrightnessTimer[i].logState(pr, "  ");
17117             }
17118             pr.println("*** Interactive timer:");
17119             mInteractiveTimer.logState(pr, "  ");
17120             pr.println("*** Power save mode timer:");
17121             mPowerSaveModeEnabledTimer.logState(pr, "  ");
17122             pr.println("*** Device idle mode light timer:");
17123             mDeviceIdleModeLightTimer.logState(pr, "  ");
17124             pr.println("*** Device idle mode full timer:");
17125             mDeviceIdleModeFullTimer.logState(pr, "  ");
17126             pr.println("*** Device light idling timer:");
17127             mDeviceLightIdlingTimer.logState(pr, "  ");
17128             pr.println("*** Device idling timer:");
17129             mDeviceIdlingTimer.logState(pr, "  ");
17130             pr.println("*** Phone timer:");
17131             mPhoneOnTimer.logState(pr, "  ");
17132             for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
17133                 pr.println("*** Phone signal strength #" + i + ":");
17134                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
17135             }
17136             pr.println("*** Signal scanning :");
17137             mPhoneSignalScanningTimer.logState(pr, "  ");
17138             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
17139                 pr.println("*** Data connection type #" + i + ":");
17140                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
17141             }
17142             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
17143             pr.println("*** Mobile network active timer:");
17144             mMobileRadioActiveTimer.logState(pr, "  ");
17145             pr.println("*** Mobile network active adjusted timer:");
17146             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
17147             pr.println("*** Wifi Multicast WakeLock Timer:");
17148             mWifiMulticastWakelockTimer.logState(pr, "  ");
17149             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
17150             pr.println("*** Wifi timer:");
17151             mWifiOnTimer.logState(pr, "  ");
17152             pr.println("*** WifiRunning timer:");
17153             mGlobalWifiRunningTimer.logState(pr, "  ");
17154             for (int i=0; i<NUM_WIFI_STATES; i++) {
17155                 pr.println("*** Wifi state #" + i + ":");
17156                 mWifiStateTimer[i].logState(pr, "  ");
17157             }
17158             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
17159                 pr.println("*** Wifi suppl state #" + i + ":");
17160                 mWifiSupplStateTimer[i].logState(pr, "  ");
17161             }
17162             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
17163                 pr.println("*** Wifi signal strength #" + i + ":");
17164                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
17165             }
17166             for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
17167                 pr.println("*** GPS signal quality #" + i + ":");
17168                 mGpsSignalQualityTimer[i].logState(pr, "  ");
17169             }
17170             pr.println("*** Flashlight timer:");
17171             mFlashlightOnTimer.logState(pr, "  ");
17172             pr.println("*** Camera timer:");
17173             mCameraOnTimer.logState(pr, "  ");
17174         }
17175         super.dumpLocked(context, pw, flags, reqUid, histStart);
17176 
17177         pw.print("Total cpu time reads: ");
17178         pw.println(mNumSingleUidCpuTimeReads);
17179         pw.print("Batched cpu time reads: ");
17180         pw.println(mNumBatchedSingleUidCpuTimeReads);
17181         pw.print("Batching Duration (min): ");
17182         pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTimeMs) / (60 * 1000));
17183         pw.print("All UID cpu time reads since the later of device start or stats reset: ");
17184         pw.println(mNumAllUidCpuTimeReads);
17185         pw.print("UIDs removed since the later of device start or stats reset: ");
17186         pw.println(mNumUidsRemoved);
17187 
17188         pw.println("Currently mapped isolated uids:");
17189         final int numIsolatedUids = mIsolatedUids.size();
17190         for (int i = 0; i < numIsolatedUids; i++) {
17191             final int isolatedUid = mIsolatedUids.keyAt(i);
17192             final int ownerUid = mIsolatedUids.valueAt(i);
17193             final int refCount = mIsolatedUidRefCounts.get(isolatedUid);
17194             pw.println("  " + isolatedUid + "->" + ownerUid + " (ref count = " + refCount + ")");
17195         }
17196 
17197         pw.println();
17198         dumpConstantsLocked(pw);
17199 
17200         pw.println();
17201         dumpMeasuredEnergyStatsLocked(pw);
17202     }
17203 }
17204