• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.BatteryStats.Uid.NUM_PROCESS_STATE;
22 import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
23 import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
24 
25 import android.annotation.IntDef;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.app.ActivityManager;
29 import android.app.usage.NetworkStatsManager;
30 import android.bluetooth.BluetoothActivityEnergyInfo;
31 import android.bluetooth.UidTraffic;
32 import android.compat.annotation.UnsupportedAppUsage;
33 import android.content.BroadcastReceiver;
34 import android.content.ContentResolver;
35 import android.content.Context;
36 import android.content.Intent;
37 import android.content.IntentFilter;
38 import android.database.ContentObserver;
39 import android.hardware.usb.UsbManager;
40 import android.location.GnssSignalQuality;
41 import android.net.NetworkStats;
42 import android.net.Uri;
43 import android.net.wifi.WifiManager;
44 import android.os.BatteryConsumer;
45 import android.os.BatteryManager;
46 import android.os.BatteryStats;
47 import android.os.Binder;
48 import android.os.BluetoothBatteryStats;
49 import android.os.Build;
50 import android.os.Handler;
51 import android.os.IBatteryPropertiesRegistrar;
52 import android.os.Looper;
53 import android.os.Message;
54 import android.os.OsProtoEnums;
55 import android.os.Parcel;
56 import android.os.ParcelFormatException;
57 import android.os.Parcelable;
58 import android.os.PowerManager;
59 import android.os.Process;
60 import android.os.RemoteException;
61 import android.os.ServiceManager;
62 import android.os.SystemClock;
63 import android.os.UserHandle;
64 import android.os.WakeLockStats;
65 import android.os.WorkSource;
66 import android.os.WorkSource.WorkChain;
67 import android.os.connectivity.CellularBatteryStats;
68 import android.os.connectivity.GpsBatteryStats;
69 import android.os.connectivity.WifiActivityEnergyInfo;
70 import android.os.connectivity.WifiBatteryStats;
71 import android.provider.Settings;
72 import android.telephony.AccessNetworkConstants;
73 import android.telephony.Annotation.NetworkType;
74 import android.telephony.CellSignalStrength;
75 import android.telephony.CellSignalStrengthLte;
76 import android.telephony.CellSignalStrengthNr;
77 import android.telephony.DataConnectionRealTimeInfo;
78 import android.telephony.ModemActivityInfo;
79 import android.telephony.ServiceState;
80 import android.telephony.ServiceState.RegState;
81 import android.telephony.SignalStrength;
82 import android.telephony.TelephonyManager;
83 import android.text.TextUtils;
84 import android.util.ArrayMap;
85 import android.util.ArraySet;
86 import android.util.AtomicFile;
87 import android.util.IndentingPrintWriter;
88 import android.util.KeyValueListParser;
89 import android.util.Log;
90 import android.util.LongSparseArray;
91 import android.util.LongSparseLongArray;
92 import android.util.MutableInt;
93 import android.util.PrintWriterPrinter;
94 import android.util.Printer;
95 import android.util.Slog;
96 import android.util.SparseArray;
97 import android.util.SparseDoubleArray;
98 import android.util.SparseIntArray;
99 import android.util.SparseLongArray;
100 import android.util.TimeUtils;
101 import android.util.TypedXmlPullParser;
102 import android.util.TypedXmlSerializer;
103 import android.util.Xml;
104 import android.view.Display;
105 
106 import com.android.internal.annotations.GuardedBy;
107 import com.android.internal.annotations.VisibleForTesting;
108 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
109 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
110 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
111 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
112 import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
113 import com.android.internal.power.MeasuredEnergyStats;
114 import com.android.internal.power.MeasuredEnergyStats.StandardPowerBucket;
115 import com.android.internal.util.ArrayUtils;
116 import com.android.internal.util.FrameworkStatsLog;
117 import com.android.internal.util.XmlUtils;
118 import com.android.net.module.util.NetworkCapabilitiesUtils;
119 
120 import libcore.util.EmptyArray;
121 
122 import org.xmlpull.v1.XmlPullParser;
123 import org.xmlpull.v1.XmlPullParserException;
124 
125 import java.io.ByteArrayOutputStream;
126 import java.io.File;
127 import java.io.FileInputStream;
128 import java.io.FileNotFoundException;
129 import java.io.FileOutputStream;
130 import java.io.IOException;
131 import java.io.PrintWriter;
132 import java.lang.annotation.Retention;
133 import java.lang.annotation.RetentionPolicy;
134 import java.util.ArrayList;
135 import java.util.Arrays;
136 import java.util.Calendar;
137 import java.util.Collection;
138 import java.util.Comparator;
139 import java.util.HashMap;
140 import java.util.HashSet;
141 import java.util.Iterator;
142 import java.util.LinkedList;
143 import java.util.List;
144 import java.util.Map;
145 import java.util.Queue;
146 import java.util.concurrent.Future;
147 import java.util.concurrent.atomic.AtomicInteger;
148 import java.util.concurrent.locks.ReentrantLock;
149 
150 /**
151  * All information we are collecting about things that can happen that impact
152  * battery life.  All times are represented in microseconds except where indicated
153  * otherwise.
154  */
155 public class BatteryStatsImpl extends BatteryStats {
156     private static final String TAG = "BatteryStatsImpl";
157     private static final boolean DEBUG = false;
158     public static final boolean DEBUG_ENERGY = false;
159     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
160     private static final boolean DEBUG_BINDER_STATS = false;
161     private static final boolean DEBUG_MEMORY = false;
162     private static final boolean DEBUG_HISTORY = false;
163 
164     // TODO: remove "tcp" from network methods, since we measure total stats.
165 
166     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
167     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
168 
169     // Current on-disk Parcel version. Must be updated when the format of the parcelable changes
170     public static final int VERSION = 211;
171 
172     // The maximum number of names wakelocks we will keep track of
173     // per uid; once the limit is reached, we batch the remaining wakelocks
174     // in to one common name.
175     private static final int MAX_WAKELOCKS_PER_UID;
176 
177     static {
178         if (ActivityManager.isLowRamDeviceStatic()) {
179             MAX_WAKELOCKS_PER_UID = 40;
180         } else {
181             MAX_WAKELOCKS_PER_UID = 200;
182         }
183     }
184 
185     // Number of transmit power states the Wifi controller can be in.
186     private static final int NUM_WIFI_TX_LEVELS = 1;
187 
188     // Number of transmit power states the Bluetooth controller can be in.
189     private static final int NUM_BT_TX_LEVELS = 1;
190 
191     /**
192      * Holding a wakelock costs more than just using the cpu.
193      * Currently, we assign only half the cpu time to an app that is running but
194      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
195      * If no app is holding a wakelock, then the distribution is normal.
196      */
197     @VisibleForTesting
198     public static final int WAKE_LOCK_WEIGHT = 50;
199 
200     public static final int RESET_REASON_CORRUPT_FILE = 1;
201     public static final int RESET_REASON_ADB_COMMAND = 2;
202     public static final int RESET_REASON_FULL_CHARGE = 3;
203     public static final int RESET_REASON_MEASURED_ENERGY_BUCKETS_CHANGE = 4;
204 
205     protected Clock mClock;
206 
207     private final AtomicFile mStatsFile;
208     public final AtomicFile mCheckinFile;
209     public final AtomicFile mDailyFile;
210 
211     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
212     static final int MSG_REPORT_POWER_CHANGE = 2;
213     static final int MSG_REPORT_CHARGING = 3;
214     static final int MSG_REPORT_RESET_STATS = 4;
215     static final long DELAY_UPDATE_WAKELOCKS = 60 * 1000;
216 
217     private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
218     private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
219 
220     private static final LongCounter ZERO_LONG_COUNTER = new LongCounter() {
221         @Override
222         public long getCountLocked(int which) {
223             return 0;
224         }
225 
226         @Override
227         public long getCountForProcessState(int procState) {
228             return 0;
229         }
230 
231         @Override
232         public void logState(Printer pw, String prefix) {
233             pw.println(prefix + "mCount=0");
234         }
235     };
236 
237     private static final LongCounter[] ZERO_LONG_COUNTER_ARRAY =
238             new LongCounter[]{ZERO_LONG_COUNTER};
239 
240     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
241     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
242 
243     @VisibleForTesting
244     protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
245     @VisibleForTesting
246     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
247     @VisibleForTesting
248     protected KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader;
249     @VisibleForTesting
250     protected KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader;
251     @VisibleForTesting
252     protected KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader;
253     @VisibleForTesting
254     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
255     @VisibleForTesting
256     protected SystemServerCpuThreadReader mSystemServerCpuThreadReader =
257             SystemServerCpuThreadReader.create();
258 
259     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
260             = new KernelMemoryBandwidthStats();
261     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
262 
getKernelMemoryStats()263     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
264         return mKernelMemoryStats;
265     }
266 
267     private static final int[] SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS = {
268             MeasuredEnergyStats.POWER_BUCKET_CPU,
269             MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO,
270             MeasuredEnergyStats.POWER_BUCKET_WIFI,
271             MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH,
272     };
273 
274     // TimeInState counters need NUM_PROCESS_STATE states in order to accommodate
275     // Uid.PROCESS_STATE_NONEXISTENT, which is outside the range of legitimate proc states.
276     private static final int PROC_STATE_TIME_COUNTER_STATE_COUNT = NUM_PROCESS_STATE + 1;
277 
278     @GuardedBy("this")
279     public boolean mPerProcStateCpuTimesAvailable = true;
280 
281     @GuardedBy("this")
282     private long mNumSingleUidCpuTimeReads;
283     @GuardedBy("this")
284     private long mCpuTimeReadsTrackingStartTimeMs = SystemClock.uptimeMillis();
285     @GuardedBy("this")
286     private int mNumUidsRemoved;
287     @GuardedBy("this")
288     private int mNumAllUidCpuTimeReads;
289 
290     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
291     private RpmStats mTmpRpmStats = null;
292     /** The soonest the RPM stats can be updated after it was last updated. */
293     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
294     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
295     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
296 
297     /** Container for Rail Energy Data stats. */
298     private final RailStats mTmpRailStats = new RailStats();
299 
300     /**
301      * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
302      * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
303      * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
304      *
305      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
306      * Batterystats both need to access UID cpu time. To resolve this race condition, only
307      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
308      * implemented so that STATSD can capture those UID times before they are deleted.
309      */
310     @GuardedBy("this")
311     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
312     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
313 
314     @VisibleForTesting
315     public final class UidToRemove {
316         private final int mStartUid;
317         private final int mEndUid;
318         private final long mUidRemovalTimestamp;
319 
320         /** Remove just one UID */
UidToRemove(int uid, long timestamp)321         public UidToRemove(int uid, long timestamp) {
322             this(uid, uid, timestamp);
323         }
324 
325         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)326         public UidToRemove(int startUid, int endUid, long timestamp) {
327             mStartUid = startUid;
328             mEndUid = endUid;
329             mUidRemovalTimestamp = timestamp;
330         }
331 
getUidRemovalTimestamp()332         public long getUidRemovalTimestamp() {
333             return mUidRemovalTimestamp;
334         }
335 
336         @GuardedBy("BatteryStatsImpl.this")
removeLocked()337         void removeLocked() {
338             removeCpuStatsForUidRangeLocked(mStartUid, mEndUid);
339         }
340     }
341 
342     /**
343      * Listener for the battery stats reset.
344      */
345     public interface BatteryResetListener {
346 
347         /**
348          * Callback invoked immediately prior to resetting battery stats.
349          * @param resetReason One of the RESET_REASON_* constants.
350          */
prepareForBatteryStatsReset(int resetReason)351         void prepareForBatteryStatsReset(int resetReason);
352     }
353 
354     private BatteryResetListener mBatteryResetListener;
355 
356     public interface BatteryCallback {
batteryNeedsCpuUpdate()357         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)358         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)359         public void batterySendBroadcast(Intent intent);
batteryStatsReset()360         public void batteryStatsReset();
361     }
362 
363     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)364         public void fillLowPowerStats(RpmStats rpmStats);
getSubsystemLowPowerStats()365         public String getSubsystemLowPowerStats();
366     }
367 
368     /** interface to update rail information for power monitor */
369     public interface MeasuredEnergyRetriever {
370         /** Function to fill the map for the rail data stats
371          * Used for power monitoring feature
372          * @param railStats
373          */
fillRailDataStats(RailStats railStats)374         void fillRailDataStats(RailStats railStats);
375     }
376 
377     public static abstract class UserInfoProvider {
378         private int[] userIds;
getUserIds()379         protected abstract @Nullable int[] getUserIds();
380         @VisibleForTesting
refreshUserIds()381         public final void refreshUserIds() {
382             userIds = getUserIds();
383         }
384         @VisibleForTesting
exists(int userId)385         public boolean exists(int userId) {
386             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
387         }
388     }
389 
390     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
391 
392     private final Runnable mDeferSetCharging = new Runnable() {
393         @Override
394         public void run() {
395             synchronized (BatteryStatsImpl.this) {
396                 if (mOnBattery) {
397                     // if the device gets unplugged in the time between this runnable being
398                     // executed and the lock being taken, we don't want to set charging state
399                     return;
400                 }
401                 boolean changed = setChargingLocked(true);
402                 if (changed) {
403                     final long uptimeMs = mClock.uptimeMillis();
404                     final long elapsedRealtimeMs = mClock.elapsedRealtime();
405                     addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
406                 }
407             }
408         }
409     };
410 
411     public final MeasuredEnergyRetriever mMeasuredEnergyRetriever;
412 
413     /**
414      * This handler is running on {@link BackgroundThread}.
415      */
416     final class MyHandler extends Handler {
MyHandler(Looper looper)417         public MyHandler(Looper looper) {
418             super(looper, null, true);
419         }
420 
421         @Override
handleMessage(Message msg)422         public void handleMessage(Message msg) {
423             BatteryCallback cb = mCallback;
424             switch (msg.what) {
425                 case MSG_REPORT_CPU_UPDATE_NEEDED:
426                     if (cb != null) {
427                         cb.batteryNeedsCpuUpdate();
428                     }
429                     break;
430                 case MSG_REPORT_POWER_CHANGE:
431                     if (cb != null) {
432                         cb.batteryPowerChanged(msg.arg1 != 0);
433                     }
434                     break;
435                 case MSG_REPORT_CHARGING:
436                     if (cb != null) {
437                         final String action;
438                         synchronized (BatteryStatsImpl.this) {
439                             action = mCharging ? BatteryManager.ACTION_CHARGING
440                                     : BatteryManager.ACTION_DISCHARGING;
441                         }
442                         Intent intent = new Intent(action);
443                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
444                         cb.batterySendBroadcast(intent);
445                     }
446                     break;
447                 case MSG_REPORT_RESET_STATS:
448                     if (cb != null) {
449                         cb.batteryStatsReset();
450                     }
451                 }
452         }
453     }
454 
postBatteryNeedsCpuUpdateMsg()455     public void postBatteryNeedsCpuUpdateMsg() {
456         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
457     }
458 
459     /**
460      * Update per-freq cpu times for the supplied UID.
461      */
462     @GuardedBy("this")
463     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
464     @VisibleForTesting
updateProcStateCpuTimesLocked(int uid, long timestampMs)465     public void updateProcStateCpuTimesLocked(int uid, long timestampMs) {
466         if (!initKernelSingleUidTimeReaderLocked()) {
467             return;
468         }
469 
470         final Uid u = getUidStatsLocked(uid);
471 
472         mNumSingleUidCpuTimeReads++;
473 
474         LongArrayMultiStateCounter onBatteryCounter =
475                 u.getProcStateTimeCounter(timestampMs).getCounter();
476         LongArrayMultiStateCounter onBatteryScreenOffCounter =
477                 u.getProcStateScreenOffTimeCounter(timestampMs).getCounter();
478 
479         mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, timestampMs);
480         mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, timestampMs);
481 
482         if (u.mChildUids != null) {
483             LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
484                     getCpuTimeInFreqContainer();
485             int childUidCount = u.mChildUids.size();
486             for (int j = childUidCount - 1; j >= 0; --j) {
487                 LongArrayMultiStateCounter cpuTimeInFreqCounter =
488                         u.mChildUids.valueAt(j).cpuTimeInFreqCounter;
489                 if (cpuTimeInFreqCounter != null) {
490                     mKernelSingleUidTimeReader.addDelta(u.mChildUids.keyAt(j),
491                             cpuTimeInFreqCounter, timestampMs, deltaContainer);
492                     onBatteryCounter.addCounts(deltaContainer);
493                     onBatteryScreenOffCounter.addCounts(deltaContainer);
494                 }
495             }
496         }
497     }
498 
499     /**
500      * Removes kernel CPU stats for removed UIDs, in the order they were added to the
501      * mPendingRemovedUids queue.
502      */
503     @GuardedBy("this")
504     @SuppressWarnings("GuardedBy")    // errorprone false positive on removeLocked
clearPendingRemovedUidsLocked()505     public void clearPendingRemovedUidsLocked() {
506         long cutOffTimeMs = mClock.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
507         while (!mPendingRemovedUids.isEmpty()
508                 && mPendingRemovedUids.peek().getUidRemovalTimestamp() < cutOffTimeMs) {
509             mPendingRemovedUids.poll().removeLocked();
510         }
511     }
512 
513     /**
514      * When the battery/screen state changes, we don't attribute the cpu times to any process
515      * but we still need to take snapshots of all uids to get correct deltas later on.
516      */
517     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
updateCpuTimesForAllUids()518     public void updateCpuTimesForAllUids() {
519         synchronized (BatteryStatsImpl.this) {
520             if (!trackPerProcStateCpuTimes()) {
521                 return;
522             }
523 
524             if(!initKernelSingleUidTimeReaderLocked()) {
525                 return;
526             }
527 
528             // TODO(b/197162116): just get a list of UIDs
529             final SparseArray<long[]> allUidCpuFreqTimesMs =
530                     mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
531             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
532                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
533                 final int parentUid = mapUid(uid);
534                 final Uid u = getAvailableUidStatsLocked(parentUid);
535                 if (u == null) {
536                     continue;
537                 }
538 
539                 final int procState = u.mProcessState;
540                 if (procState == Uid.PROCESS_STATE_NONEXISTENT) {
541                     continue;
542                 }
543 
544                 final long timestampMs = mClock.elapsedRealtime();
545                 final LongArrayMultiStateCounter onBatteryCounter =
546                         u.getProcStateTimeCounter(timestampMs).getCounter();
547                 final LongArrayMultiStateCounter onBatteryScreenOffCounter =
548                         u.getProcStateScreenOffTimeCounter(timestampMs).getCounter();
549 
550                 if (uid == parentUid || Process.isSdkSandboxUid(uid)) {
551                     mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter, timestampMs);
552                     mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryScreenOffCounter,
553                             timestampMs);
554                 } else {
555                     Uid.ChildUid childUid = u.getChildUid(uid);
556                     if (childUid != null) {
557                         final LongArrayMultiStateCounter counter = childUid.cpuTimeInFreqCounter;
558                         if (counter != null) {
559                             final LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
560                                     getCpuTimeInFreqContainer();
561                             mKernelSingleUidTimeReader.addDelta(uid, counter, timestampMs,
562                                     deltaContainer);
563                             onBatteryCounter.addCounts(deltaContainer);
564                             onBatteryScreenOffCounter.addCounts(deltaContainer);
565                         }
566                     }
567                 }
568             }
569         }
570     }
571 
572     @VisibleForTesting
addCpuTimes(long[] timesA, long[] timesB)573     public static long[] addCpuTimes(long[] timesA, long[] timesB) {
574         if (timesA != null && timesB != null) {
575             for (int i = timesA.length - 1; i >= 0; --i) {
576                 timesA[i] += timesB[i];
577             }
578             return timesA;
579         }
580         return timesA == null ? (timesB == null ? null : timesB) : timesA;
581     }
582 
583     @GuardedBy("this")
initKernelSingleUidTimeReaderLocked()584     private boolean initKernelSingleUidTimeReaderLocked() {
585         if (mKernelSingleUidTimeReader == null) {
586             if (mPowerProfile == null) {
587                 return false;
588             }
589             if (mCpuFreqs == null) {
590                 mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
591             }
592             if (mCpuFreqs != null) {
593                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
594             } else {
595                 mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable();
596                 return false;
597             }
598         }
599         mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable()
600                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
601         return true;
602     }
603 
604     public interface ExternalStatsSync {
605         int UPDATE_CPU = 0x01;
606         int UPDATE_WIFI = 0x02;
607         int UPDATE_RADIO = 0x04;
608         int UPDATE_BT = 0x08;
609         int UPDATE_RPM = 0x10;
610         int UPDATE_DISPLAY = 0x20;
611         int RESET = 0x40;
612 
613         int UPDATE_ALL =
614                 UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY;
615 
616         int UPDATE_ON_PROC_STATE_CHANGE = UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
617 
618         int UPDATE_ON_RESET = UPDATE_ALL | RESET;
619 
620         @IntDef(flag = true, prefix = "UPDATE_", value = {
621                 UPDATE_CPU,
622                 UPDATE_WIFI,
623                 UPDATE_RADIO,
624                 UPDATE_BT,
625                 UPDATE_RPM,
626                 UPDATE_DISPLAY,
627                 UPDATE_ALL,
628         })
629         @Retention(RetentionPolicy.SOURCE)
630         public @interface ExternalUpdateFlag {
631         }
632 
scheduleSync(String reason, int flags)633         Future<?> scheduleSync(String reason, int flags);
scheduleCpuSyncDueToRemovedUid(int uid)634         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
scheduleCpuSyncDueToSettingChange()635         Future<?> scheduleCpuSyncDueToSettingChange();
636         /**
637          * Schedule a sync because of a screen state change.
638          */
scheduleSyncDueToScreenStateChange(int flags, boolean onBattery, boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates)639         Future<?> scheduleSyncDueToScreenStateChange(int flags, boolean onBattery,
640                 boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates);
scheduleCpuSyncDueToWakelockChange(long delayMillis)641         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
cancelCpuSyncDueToWakelockChange()642         void cancelCpuSyncDueToWakelockChange();
scheduleSyncDueToBatteryLevelChange(long delayMillis)643         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
644         /** Schedule removal of UIDs corresponding to a removed user */
scheduleCleanupDueToRemovedUser(int userId)645         Future<?> scheduleCleanupDueToRemovedUser(int userId);
646         /** Schedule a sync because of a process state change */
scheduleSyncDueToProcessStateChange(int flags, long delayMillis)647         void scheduleSyncDueToProcessStateChange(int flags, long delayMillis);
648     }
649 
650     public Handler mHandler;
651     private ExternalStatsSync mExternalSync = null;
652     @VisibleForTesting
653     protected UserInfoProvider mUserInfoProvider = null;
654 
655     private BatteryCallback mCallback;
656 
657     /**
658      * Mapping isolated uids to the actual owning app uid.
659      */
660     final SparseIntArray mIsolatedUids = new SparseIntArray();
661     /**
662      * Internal reference count of isolated uids.
663      */
664     final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray();
665 
666     /**
667      * The statistics we have collected organized by uids.
668      */
669     final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
670 
671     // A set of pools of currently active timers.  When a timer is queried, we will divide the
672     // elapsed time by the number of active timers to arrive at that timer's share of the time.
673     // In order to do this, we must refresh each timer whenever the number of active timers
674     // changes.
675     @VisibleForTesting
676     @UnsupportedAppUsage
677     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
678     @UnsupportedAppUsage
679     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
680     @UnsupportedAppUsage
681     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
682     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
683     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
684     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
685     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
686     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
687     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
688     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
689     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
690     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
691     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
692     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
693     final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
694 
695     // Last partial timers we use for distributing CPU usage.
696     @VisibleForTesting
697     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
698 
699     // These are the objects that will want to do something when the device
700     // is unplugged from power.
701     protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
702 
703     // These are the objects that will want to do something when the device
704     // is unplugged from power *and* the screen is off or doze.
705     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
706 
707     // Set to true when we want to distribute CPU across wakelocks for the next
708     // CPU update, even if we aren't currently running wake locks.
709     boolean mDistributeWakelockCpu;
710 
711     private boolean mSystemReady;
712     boolean mShuttingDown;
713 
714     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
715 
716     long mHistoryBaseTimeMs;
717     protected boolean mHaveBatteryLevel = false;
718     protected boolean mRecordingHistory = false;
719     int mNumHistoryItems;
720 
721     private static final int HISTORY_TAG_INDEX_LIMIT = 0x7ffe;
722     private static final int MAX_HISTORY_TAG_STRING_LENGTH = 1024;
723 
724     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
725     private SparseArray<HistoryTag> mHistoryTags;
726     final Parcel mHistoryBuffer = Parcel.obtain();
727     final HistoryItem mHistoryLastWritten = new HistoryItem();
728     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
729     final HistoryItem mHistoryAddTmp = new HistoryItem();
730     int mNextHistoryTagIdx = 0;
731     int mNumHistoryTagChars = 0;
732     int mHistoryBufferLastPos = -1;
733     int mActiveHistoryStates = 0xffffffff;
734     int mActiveHistoryStates2 = 0xffffffff;
735     long mLastHistoryElapsedRealtimeMs = 0;
736     long mTrackRunningHistoryElapsedRealtimeMs = 0;
737     long mTrackRunningHistoryUptimeMs = 0;
738 
739     @NonNull
740     final BatteryStatsHistory mBatteryStatsHistory;
741 
742     final HistoryItem mHistoryCur = new HistoryItem();
743 
744     HistoryItem mHistory;
745     HistoryItem mHistoryEnd;
746     HistoryItem mHistoryLastEnd;
747     HistoryItem mHistoryCache;
748 
749     // Used by computeHistoryStepDetails
750     HistoryStepDetails mLastHistoryStepDetails = null;
751     byte mLastHistoryStepLevel = 0;
752     final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
753     final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
754     final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
755 
756     /**
757      * Total time (in milliseconds) spent executing in user code.
758      */
759     long mLastStepCpuUserTimeMs;
760     long mCurStepCpuUserTimeMs;
761     /**
762      * Total time (in milliseconds) spent executing in kernel code.
763      */
764     long mLastStepCpuSystemTimeMs;
765     long mCurStepCpuSystemTimeMs;
766     /**
767      * Times from /proc/stat (but measured in milliseconds).
768      */
769     long mLastStepStatUserTimeMs;
770     long mLastStepStatSystemTimeMs;
771     long mLastStepStatIOWaitTimeMs;
772     long mLastStepStatIrqTimeMs;
773     long mLastStepStatSoftIrqTimeMs;
774     long mLastStepStatIdleTimeMs;
775     long mCurStepStatUserTimeMs;
776     long mCurStepStatSystemTimeMs;
777     long mCurStepStatIOWaitTimeMs;
778     long mCurStepStatIrqTimeMs;
779     long mCurStepStatSoftIrqTimeMs;
780     long mCurStepStatIdleTimeMs;
781 
782     private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator;
783     private HistoryItem mHistoryIterator;
784 
785     int mStartCount;
786 
787     /**
788      * Set to true when a reset occurs, informing us that the next time BatteryExternalStatsWorker
789      * gives us data, we mustn't process it since this data includes pre-reset-period data.
790      */
791     @GuardedBy("this")
792     boolean mIgnoreNextExternalStats = false;
793 
794     long mStartClockTimeMs;
795     String mStartPlatformVersion;
796     String mEndPlatformVersion;
797 
798     long mUptimeUs;
799     long mUptimeStartUs;
800     long mRealtimeUs;
801     long mRealtimeStartUs;
802 
803     int mWakeLockNesting;
804     boolean mWakeLockImportant;
805     public boolean mRecordAllHistory;
806     boolean mNoAutoReset;
807 
808     /**
809      * Overall screen state. For multidisplay devices, this represents the current highest screen
810      * state of the displays.
811      */
812     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
813     protected int mScreenState = Display.STATE_UNKNOWN;
814     /**
815      * Overall screen on timer. For multidisplay devices, this represents the time spent with at
816      * least one display in the screen on state.
817      */
818     StopwatchTimer mScreenOnTimer;
819     /**
820      * Overall screen doze timer. For multidisplay devices, this represents the time spent with
821      * screen doze being the highest screen state.
822      */
823     StopwatchTimer mScreenDozeTimer;
824     /**
825      * Overall screen brightness bin. For multidisplay devices, this represents the current
826      * brightest screen.
827      */
828     int mScreenBrightnessBin = -1;
829     /**
830      * Overall screen brightness timers. For multidisplay devices, the {@link mScreenBrightnessBin}
831      * timer will be active at any given time
832      */
833     final StopwatchTimer[] mScreenBrightnessTimer =
834             new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
835 
836     boolean mPretendScreenOff;
837 
838     private static class DisplayBatteryStats {
839         /**
840          * Per display screen state.
841          */
842         public int screenState = Display.STATE_UNKNOWN;
843         /**
844          * Per display screen on timers.
845          */
846         public StopwatchTimer screenOnTimer;
847         /**
848          * Per display screen doze timers.
849          */
850         public StopwatchTimer screenDozeTimer;
851         /**
852          * Per display screen brightness bins.
853          */
854         public int screenBrightnessBin = -1;
855         /**
856          * Per display screen brightness timers.
857          */
858         public StopwatchTimer[] screenBrightnessTimers =
859                 new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
860         /**
861          * Per display screen state the last time {@link #updateDisplayMeasuredEnergyStatsLocked}
862          * was called.
863          */
864         public int screenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
865 
DisplayBatteryStats(Clock clock, TimeBase timeBase)866         DisplayBatteryStats(Clock clock, TimeBase timeBase) {
867             screenOnTimer = new StopwatchTimer(clock, null, -1, null,
868                     timeBase);
869             screenDozeTimer = new StopwatchTimer(clock, null, -1, null,
870                     timeBase);
871             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
872                 screenBrightnessTimers[i] = new StopwatchTimer(clock, null, -100 - i, null,
873                         timeBase);
874             }
875         }
876 
877         /**
878          * Reset display timers.
879          */
reset(long elapsedRealtimeUs)880         public void reset(long elapsedRealtimeUs) {
881             screenOnTimer.reset(false, elapsedRealtimeUs);
882             screenDozeTimer.reset(false, elapsedRealtimeUs);
883             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
884                 screenBrightnessTimers[i].reset(false, elapsedRealtimeUs);
885             }
886         }
887     }
888 
889     DisplayBatteryStats[] mPerDisplayBatteryStats;
890 
891     private int mDisplayMismatchWtfCount = 0;
892 
893     boolean mInteractive;
894     StopwatchTimer mInteractiveTimer;
895 
896     boolean mPowerSaveModeEnabled;
897     StopwatchTimer mPowerSaveModeEnabledTimer;
898 
899     boolean mDeviceIdling;
900     StopwatchTimer mDeviceIdlingTimer;
901 
902     boolean mDeviceLightIdling;
903     StopwatchTimer mDeviceLightIdlingTimer;
904 
905     int mDeviceIdleMode;
906     long mLastIdleTimeStartMs;
907     long mLongestLightIdleTimeMs;
908     long mLongestFullIdleTimeMs;
909     StopwatchTimer mDeviceIdleModeLightTimer;
910     StopwatchTimer mDeviceIdleModeFullTimer;
911 
912     boolean mPhoneOn;
913     StopwatchTimer mPhoneOnTimer;
914 
915     int mAudioOnNesting;
916     StopwatchTimer mAudioOnTimer;
917 
918     int mVideoOnNesting;
919     StopwatchTimer mVideoOnTimer;
920 
921     int mFlashlightOnNesting;
922     StopwatchTimer mFlashlightOnTimer;
923 
924     int mCameraOnNesting;
925     StopwatchTimer mCameraOnTimer;
926 
927     private static final int USB_DATA_UNKNOWN = 0;
928     private static final int USB_DATA_DISCONNECTED = 1;
929     private static final int USB_DATA_CONNECTED = 2;
930     int mUsbDataState = USB_DATA_UNKNOWN;
931 
932     int mGpsSignalQualityBin = -1;
933     final StopwatchTimer[] mGpsSignalQualityTimer =
934         new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
935 
936     int mPhoneSignalStrengthBin = -1;
937     int mPhoneSignalStrengthBinRaw = -1;
938     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
939             new StopwatchTimer[CellSignalStrength.getNumSignalStrengthLevels()];
940 
941     StopwatchTimer mPhoneSignalScanningTimer;
942 
943     int mPhoneDataConnectionType = -1;
944     final StopwatchTimer[] mPhoneDataConnectionsTimer =
945             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
946 
947     @RadioAccessTechnology
948     int mActiveRat = RADIO_ACCESS_TECHNOLOGY_OTHER;
949 
950     private static class RadioAccessTechnologyBatteryStats {
951         /**
952          * This RAT is currently being used.
953          */
954         private boolean mActive = false;
955         /**
956          * Current active frequency range for this RAT.
957          */
958         @ServiceState.FrequencyRange
959         private int mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
960         /**
961          * Current signal strength for this RAT.
962          */
963         private int mSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
964         /**
965          * Timers for each combination of frequency range and signal strength.
966          */
967         public final StopwatchTimer[][] perStateTimers;
968         /**
969          * Counters tracking the time (in milliseconds) spent transmitting data in a given state.
970          */
971         @Nullable
972         private LongSamplingCounter[][] mPerStateTxDurationMs = null;
973         /**
974          * Counters tracking the time (in milliseconds) spent receiving data in at given frequency.
975          */
976         @Nullable
977         private LongSamplingCounter[] mPerFrequencyRxDurationMs = null;
978 
RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase)979         RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
980             perStateTimers =
981                     new StopwatchTimer[freqCount][CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS];
982             for (int i = 0; i < freqCount; i++) {
983                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
984                     perStateTimers[i][j] = new StopwatchTimer(clock, null, -1, null, timeBase);
985                 }
986             }
987         }
988 
989         /**
990          * Note this RAT is currently being used.
991          */
noteActive(boolean active, long elapsedRealtimeMs)992         public void noteActive(boolean active, long elapsedRealtimeMs) {
993             if (mActive == active) return;
994             mActive = active;
995             if (mActive) {
996                 perStateTimers[mFrequencyRange][mSignalStrength].startRunningLocked(
997                         elapsedRealtimeMs);
998             } else {
999                 perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(
1000                         elapsedRealtimeMs);
1001             }
1002         }
1003 
1004         /**
1005          * Note current frequency range has changed.
1006          */
noteFrequencyRange(@erviceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs)1007         public void noteFrequencyRange(@ServiceState.FrequencyRange int frequencyRange,
1008                 long elapsedRealtimeMs) {
1009             if (mFrequencyRange == frequencyRange) return;
1010 
1011             if (!mActive) {
1012                 // RAT not in use, note the frequency change and move on.
1013                 mFrequencyRange = frequencyRange;
1014                 return;
1015             }
1016             perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
1017             perStateTimers[frequencyRange][mSignalStrength].startRunningLocked(elapsedRealtimeMs);
1018             mFrequencyRange = frequencyRange;
1019         }
1020 
1021         /**
1022          * Note current signal strength has changed.
1023          */
noteSignalStrength(int signalStrength, long elapsedRealtimeMs)1024         public void noteSignalStrength(int signalStrength, long elapsedRealtimeMs) {
1025             if (mSignalStrength == signalStrength) return;
1026 
1027             if (!mActive) {
1028                 // RAT not in use, note the signal strength change and move on.
1029                 mSignalStrength = signalStrength;
1030                 return;
1031             }
1032             perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
1033             perStateTimers[mFrequencyRange][signalStrength].startRunningLocked(elapsedRealtimeMs);
1034             mSignalStrength = signalStrength;
1035         }
1036 
1037         /**
1038          * Returns the duration in milliseconds spent in a given state since the last mark.
1039          */
getTimeSinceMark(@erviceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)1040         public long getTimeSinceMark(@ServiceState.FrequencyRange int frequencyRange,
1041                 int signalStrength, long elapsedRealtimeMs) {
1042             return perStateTimers[frequencyRange][signalStrength].getTimeSinceMarkLocked(
1043                     elapsedRealtimeMs * 1000) / 1000;
1044         }
1045 
1046         /**
1047          * Set mark for all timers.
1048          */
setMark(long elapsedRealtimeMs)1049         public void setMark(long elapsedRealtimeMs) {
1050             final int size = perStateTimers.length;
1051             for (int i = 0; i < size; i++) {
1052                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1053                     perStateTimers[i][j].setMark(elapsedRealtimeMs);
1054                 }
1055             }
1056         }
1057 
1058         /**
1059          * Returns numbers of frequencies tracked for this RAT.
1060          */
getFrequencyRangeCount()1061         public int getFrequencyRangeCount() {
1062             return perStateTimers.length;
1063         }
1064 
1065         /**
1066          * Add TX time for a given state.
1067          */
incrementTxDuration(@erviceState.FrequencyRange int frequencyRange, int signalStrength, long durationMs)1068         public void incrementTxDuration(@ServiceState.FrequencyRange int frequencyRange,
1069                 int signalStrength, long durationMs) {
1070             getTxDurationCounter(frequencyRange, signalStrength, true).addCountLocked(durationMs);
1071         }
1072 
1073         /**
1074          * Add TX time for a given frequency.
1075          */
incrementRxDuration(@erviceState.FrequencyRange int frequencyRange, long durationMs)1076         public void incrementRxDuration(@ServiceState.FrequencyRange int frequencyRange,
1077                 long durationMs) {
1078             getRxDurationCounter(frequencyRange, true).addCountLocked(durationMs);
1079         }
1080 
1081         /**
1082          * Reset radio access technology timers and counts.
1083          */
reset(long elapsedRealtimeUs)1084         public void reset(long elapsedRealtimeUs) {
1085             final int size = perStateTimers.length;
1086             for (int i = 0; i < size; i++) {
1087                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1088                     perStateTimers[i][j].reset(false, elapsedRealtimeUs);
1089                     if (mPerStateTxDurationMs == null) continue;
1090                     mPerStateTxDurationMs[i][j].reset(false, elapsedRealtimeUs);
1091                 }
1092                 if (mPerFrequencyRxDurationMs == null) continue;
1093                 mPerFrequencyRxDurationMs[i].reset(false, elapsedRealtimeUs);
1094             }
1095         }
1096 
1097         /**
1098          * Write data to summary parcel
1099          */
writeSummaryToParcel(Parcel out, long elapsedRealtimeUs)1100         public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
1101             final int freqCount = perStateTimers.length;
1102             out.writeInt(freqCount);
1103             out.writeInt(CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS);
1104             for (int i = 0; i < freqCount; i++) {
1105                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1106                     perStateTimers[i][j].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1107                 }
1108             }
1109 
1110             if (mPerStateTxDurationMs == null) {
1111                 out.writeInt(0);
1112             } else {
1113                 out.writeInt(1);
1114                 for (int i = 0; i < freqCount; i++) {
1115                     for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1116                         mPerStateTxDurationMs[i][j].writeSummaryFromParcelLocked(out);
1117                     }
1118                 }
1119             }
1120 
1121             if (mPerFrequencyRxDurationMs == null) {
1122                 out.writeInt(0);
1123             } else {
1124                 out.writeInt(1);
1125                 for (int i = 0; i < freqCount; i++) {
1126                     mPerFrequencyRxDurationMs[i].writeSummaryFromParcelLocked(out);
1127                 }
1128             }
1129         }
1130 
1131         /**
1132          * Read data from summary parcel
1133          */
readSummaryFromParcel(Parcel in)1134         public void readSummaryFromParcel(Parcel in) {
1135             final int oldFreqCount = in.readInt();
1136             final int oldSignalStrengthCount = in.readInt();
1137             final int currFreqCount = perStateTimers.length;
1138             final int currSignalStrengthCount = CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS;
1139 
1140             for (int freq = 0; freq < oldFreqCount; freq++) {
1141                 for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
1142                     if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
1143                         // Mismatch with the summary parcel. Consume the data but don't use it.
1144                         final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
1145                                 new TimeBase());
1146                         // Consume perStateTimers data.
1147                         temp.readSummaryFromParcelLocked(in);
1148                     } else {
1149                         perStateTimers[freq][strength].readSummaryFromParcelLocked(in);
1150                     }
1151                 }
1152             }
1153 
1154             if (in.readInt() == 1) {
1155                 for (int freq = 0; freq < oldFreqCount; freq++) {
1156                     for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
1157                         if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
1158                             // Mismatch with the summary parcel. Consume the data but don't use it.
1159                             final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
1160                                     new TimeBase());
1161                             // Consume mPerStateTxDurationMs data.
1162                             temp.readSummaryFromParcelLocked(in);
1163                         }
1164                         getTxDurationCounter(freq, strength, true).readSummaryFromParcelLocked(in);
1165                     }
1166                 }
1167             }
1168 
1169             if (in.readInt() == 1) {
1170                 for (int freq = 0; freq < oldFreqCount; freq++) {
1171                     if (freq >= currFreqCount) {
1172                         // Mismatch with the summary parcel. Consume the data but don't use it.
1173                         final StopwatchTimer
1174                                 temp = new StopwatchTimer(null, null, -1, null, new TimeBase());
1175                         // Consume mPerFrequencyRxDurationMs data.
1176                         temp.readSummaryFromParcelLocked(in);
1177                         continue;
1178                     }
1179                     getRxDurationCounter(freq, true).readSummaryFromParcelLocked(in);
1180                 }
1181             }
1182         }
1183 
getTxDurationCounter( @erviceState.FrequencyRange int frequencyRange, int signalStrength, boolean make)1184         private LongSamplingCounter getTxDurationCounter(
1185                 @ServiceState.FrequencyRange int frequencyRange, int signalStrength, boolean make) {
1186             if (mPerStateTxDurationMs == null) {
1187                 if (!make) return null;
1188 
1189                 final int freqCount = getFrequencyRangeCount();
1190                 final int signalStrengthCount = perStateTimers[0].length;
1191                 final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
1192                 mPerStateTxDurationMs = new LongSamplingCounter[freqCount][signalStrengthCount];
1193                 for (int freq = 0; freq < freqCount; freq++) {
1194                     for (int strength = 0; strength < signalStrengthCount; strength++) {
1195                         mPerStateTxDurationMs[freq][strength] = new LongSamplingCounter(timeBase);
1196                     }
1197                 }
1198             }
1199             if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
1200                 Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
1201                         + ") requested in getTxDurationCounter");
1202                 return null;
1203             }
1204             if (signalStrength < 0 || signalStrength >= perStateTimers[0].length) {
1205                 Slog.w(TAG, "Unexpected signal strength (" + signalStrength
1206                         + ") requested in getTxDurationCounter");
1207                 return null;
1208             }
1209             return mPerStateTxDurationMs[frequencyRange][signalStrength];
1210         }
1211 
getRxDurationCounter( @erviceState.FrequencyRange int frequencyRange, boolean make)1212         private LongSamplingCounter getRxDurationCounter(
1213                 @ServiceState.FrequencyRange int frequencyRange, boolean make) {
1214             if (mPerFrequencyRxDurationMs == null) {
1215                 if (!make) return null;
1216 
1217                 final int freqCount = getFrequencyRangeCount();
1218                 final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
1219                 mPerFrequencyRxDurationMs = new LongSamplingCounter[freqCount];
1220                 for (int freq = 0; freq < freqCount; freq++) {
1221                     mPerFrequencyRxDurationMs[freq] = new LongSamplingCounter(timeBase);
1222                 }
1223             }
1224             if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
1225                 Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
1226                         + ") requested in getRxDurationCounter");
1227                 return null;
1228             }
1229             return mPerFrequencyRxDurationMs[frequencyRange];
1230         }
1231     }
1232 
1233     /**
1234      * Number of frequency ranges, keep in sync with {@link ServiceState.FrequencyRange}
1235      */
1236     private static final int NR_FREQUENCY_COUNT = 5;
1237 
1238     RadioAccessTechnologyBatteryStats[] mPerRatBatteryStats =
1239             new RadioAccessTechnologyBatteryStats[RADIO_ACCESS_TECHNOLOGY_COUNT];
1240 
1241     @GuardedBy("this")
getRatBatteryStatsLocked( @adioAccessTechnology int rat)1242     private RadioAccessTechnologyBatteryStats getRatBatteryStatsLocked(
1243             @RadioAccessTechnology int rat) {
1244         RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
1245         if (stats == null) {
1246             final int freqCount = rat == RADIO_ACCESS_TECHNOLOGY_NR ? NR_FREQUENCY_COUNT : 1;
1247             stats = new RadioAccessTechnologyBatteryStats(freqCount, mClock, mOnBatteryTimeBase);
1248             mPerRatBatteryStats[rat] = stats;
1249         }
1250         return stats;
1251     }
1252 
1253     final LongSamplingCounter[] mNetworkByteActivityCounters =
1254             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
1255 
1256     final LongSamplingCounter[] mNetworkPacketActivityCounters =
1257             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
1258 
1259     /**
1260      * The WiFi Overall wakelock timer
1261      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
1262      * since addition of per UID timers would not result in an accurate value due to overlapp of
1263      * per uid wakelock timers
1264      */
1265     StopwatchTimer mWifiMulticastWakelockTimer;
1266 
1267     /**
1268      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
1269      */
1270     ControllerActivityCounterImpl mWifiActivity;
1271 
1272     /**
1273      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
1274      */
1275     ControllerActivityCounterImpl mBluetoothActivity;
1276 
1277     /**
1278      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
1279      */
1280     ControllerActivityCounterImpl mModemActivity;
1281 
1282     /**
1283      * Whether the device supports WiFi controller energy reporting. This is set to true on
1284      * the first WiFi energy report. See {@link #mWifiActivity}.
1285      */
1286     boolean mHasWifiReporting = false;
1287 
1288     /**
1289      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
1290      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
1291      */
1292     boolean mHasBluetoothReporting = false;
1293 
1294     /**
1295      * Whether the device supports Modem controller energy reporting. This is set to true on
1296      * the first Modem energy report. See {@link #mModemActivity}.
1297      */
1298     boolean mHasModemReporting = false;
1299 
1300     boolean mWifiOn;
1301     StopwatchTimer mWifiOnTimer;
1302 
1303     boolean mGlobalWifiRunning;
1304     StopwatchTimer mGlobalWifiRunningTimer;
1305 
1306     int mWifiState = -1;
1307     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
1308 
1309     int mWifiSupplState = -1;
1310     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
1311 
1312     int mWifiSignalStrengthBin = -1;
1313     final StopwatchTimer[] mWifiSignalStrengthsTimer =
1314             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
1315 
1316     StopwatchTimer mWifiActiveTimer;
1317 
1318     int mBluetoothScanNesting;
1319     StopwatchTimer mBluetoothScanTimer;
1320 
1321     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1322     long mMobileRadioActiveStartTimeMs;
1323     StopwatchTimer mMobileRadioActiveTimer;
1324     StopwatchTimer mMobileRadioActivePerAppTimer;
1325     LongSamplingCounter mMobileRadioActiveAdjustedTime;
1326     LongSamplingCounter mMobileRadioActiveUnknownTime;
1327     LongSamplingCounter mMobileRadioActiveUnknownCount;
1328 
1329     /**
1330      * The soonest the Mobile Radio stats can be updated due to a mobile radio power state change
1331      * after it was last updated.
1332      */
1333     @VisibleForTesting
1334     protected static final long MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS = 1000 * 60 * 10;
1335 
1336     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1337 
1338     @GuardedBy("this")
1339     @VisibleForTesting
1340     protected @Nullable MeasuredEnergyStats.Config mMeasuredEnergyStatsConfig;
1341 
1342     /**
1343      * Accumulated global (generally, device-wide total) charge consumption of various consumers
1344      * while on battery.
1345      * Its '<b>custom</b> power buckets' correspond to the
1346      * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
1347      * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
1348      *
1349      * If energy consumer data is completely unavailable this will be null.
1350      */
1351     @GuardedBy("this")
1352     @VisibleForTesting
1353     protected @Nullable MeasuredEnergyStats mGlobalMeasuredEnergyStats;
1354     /** Bluetooth Power calculator for attributing measured bluetooth charge consumption to uids */
1355     @Nullable BluetoothPowerCalculator mBluetoothPowerCalculator = null;
1356     /** Cpu Power calculator for attributing measured cpu charge consumption to uids */
1357     @Nullable CpuPowerCalculator mCpuPowerCalculator = null;
1358     /** Mobile Radio Power calculator for attributing measured radio charge consumption to uids */
1359     @Nullable
1360     MobileRadioPowerCalculator mMobileRadioPowerCalculator = null;
1361     /** Wifi Power calculator for attributing measured wifi charge consumption to uids */
1362     @Nullable WifiPowerCalculator mWifiPowerCalculator = null;
1363 
1364     /**
1365      * These provide time bases that discount the time the device is plugged
1366      * in to power.
1367      */
1368     boolean mOnBattery;
1369     @VisibleForTesting
1370     protected boolean mOnBatteryInternal;
1371 
1372     /**
1373      * External reporting of whether the device is actually charging.
1374      */
1375     boolean mCharging = true;
1376     int mLastChargingStateLevel;
1377 
1378     /*
1379      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
1380      */
1381     int mDischargeStartLevel;
1382     int mDischargeUnplugLevel;
1383     int mDischargePlugLevel;
1384     int mDischargeCurrentLevel;
1385     int mCurrentBatteryLevel;
1386     int mLowDischargeAmountSinceCharge;
1387     int mHighDischargeAmountSinceCharge;
1388     int mDischargeScreenOnUnplugLevel;
1389     int mDischargeScreenOffUnplugLevel;
1390     int mDischargeScreenDozeUnplugLevel;
1391     int mDischargeAmountScreenOn;
1392     int mDischargeAmountScreenOnSinceCharge;
1393     int mDischargeAmountScreenOff;
1394     int mDischargeAmountScreenOffSinceCharge;
1395     int mDischargeAmountScreenDoze;
1396     int mDischargeAmountScreenDozeSinceCharge;
1397 
1398     private LongSamplingCounter mDischargeScreenOffCounter;
1399     private LongSamplingCounter mDischargeScreenDozeCounter;
1400     private LongSamplingCounter mDischargeCounter;
1401     private LongSamplingCounter mDischargeLightDozeCounter;
1402     private LongSamplingCounter mDischargeDeepDozeCounter;
1403 
1404     static final int MAX_LEVEL_STEPS = 200;
1405 
1406     int mInitStepMode = 0;
1407     int mCurStepMode = 0;
1408     int mModStepMode = 0;
1409 
1410     int mLastDischargeStepLevel;
1411     int mMinDischargeStepLevel;
1412     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1413     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1414     ArrayList<PackageChange> mDailyPackageChanges;
1415 
1416     int mLastChargeStepLevel;
1417     int mMaxChargeStepLevel;
1418     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1419     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1420 
1421     static final int MAX_DAILY_ITEMS = 10;
1422 
1423     long mDailyStartTimeMs = 0;
1424     long mNextMinDailyDeadlineMs = 0;
1425     long mNextMaxDailyDeadlineMs = 0;
1426 
1427     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
1428 
1429     long mLastWriteTimeMs = 0; // Milliseconds
1430 
1431     private int mPhoneServiceState = -1;
1432     private int mPhoneServiceStateRaw = -1;
1433     private int mPhoneSimStateRaw = -1;
1434 
1435     private int mNumConnectivityChange;
1436 
1437     private int mBatteryVoltageMv = -1;
1438     private int mEstimatedBatteryCapacityMah = -1;
1439 
1440     private int mLastLearnedBatteryCapacityUah = -1;
1441     private int mMinLearnedBatteryCapacityUah = -1;
1442     private int mMaxLearnedBatteryCapacityUah = -1;
1443 
1444     private long mBatteryTimeToFullSeconds = -1;
1445 
1446     private boolean mCpuFreqsInitialized;
1447     private long[] mCpuFreqs;
1448     private LongArrayMultiStateCounter.LongArrayContainer mTmpCpuTimeInFreq;
1449 
1450     /**
1451      * Times spent by the system server threads handling incoming binder requests.
1452      */
1453     private LongSamplingCounterArray mBinderThreadCpuTimesUs;
1454 
1455     @VisibleForTesting
1456     protected PowerProfile mPowerProfile;
1457 
1458     @VisibleForTesting
1459     @GuardedBy("this")
1460     protected final Constants mConstants;
1461 
1462     /*
1463      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
1464      * recording their times when on-battery (regardless of screen state).
1465      */
1466     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
1467     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
1468     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
1469 
1470     @Override
getRpmStats()1471     public Map<String, ? extends Timer> getRpmStats() {
1472         return mRpmStats;
1473     }
1474 
1475     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
1476     @Override
getScreenOffRpmStats()1477     public Map<String, ? extends Timer> getScreenOffRpmStats() {
1478         return mScreenOffRpmStats;
1479     }
1480 
1481     /*
1482      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
1483      */
1484     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
1485 
1486     @UnsupportedAppUsage
getKernelWakelockStats()1487     public Map<String, ? extends Timer> getKernelWakelockStats() {
1488         return mKernelWakelockStats;
1489     }
1490 
1491     @Override
getWakeLockStats()1492     public WakeLockStats getWakeLockStats() {
1493         final long realtimeMs = mClock.elapsedRealtime();
1494         final long realtimeUs = realtimeMs * 1000;
1495         List<WakeLockStats.WakeLock> uidWakeLockStats = new ArrayList<>();
1496         for (int i = mUidStats.size() - 1; i >= 0; i--) {
1497             final Uid uid = mUidStats.valueAt(i);
1498             final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats =
1499                     uid.mWakelockStats.getMap();
1500             for (int j = wakelockStats.size() - 1; j >= 0; j--) {
1501                 final String name = wakelockStats.keyAt(j);
1502                 final Uid.Wakelock wakelock = (Uid.Wakelock) wakelockStats.valueAt(j);
1503                 final DualTimer timer = wakelock.mTimerPartial;
1504                 if (timer != null) {
1505                     final long totalTimeLockHeldMs =
1506                             timer.getTotalTimeLocked(realtimeUs, STATS_SINCE_CHARGED) / 1000;
1507                     if (totalTimeLockHeldMs != 0) {
1508                         uidWakeLockStats.add(
1509                                 new WakeLockStats.WakeLock(uid.getUid(), name,
1510                                         timer.getCountLocked(STATS_SINCE_CHARGED),
1511                                         totalTimeLockHeldMs,
1512                                         timer.isRunningLocked()
1513                                                 ? timer.getCurrentDurationMsLocked(realtimeMs)
1514                                                 : 0));
1515                     }
1516                 }
1517             }
1518         }
1519         return new WakeLockStats(uidWakeLockStats);
1520     }
1521 
1522     @Override
1523     @GuardedBy("this")
getBluetoothBatteryStats()1524     public BluetoothBatteryStats getBluetoothBatteryStats() {
1525         final long elapsedRealtimeUs = mClock.elapsedRealtime() * 1000;
1526         ArrayList<BluetoothBatteryStats.UidStats> uidStats = new ArrayList<>();
1527         for (int i = mUidStats.size() - 1; i >= 0; i--) {
1528             final Uid uid = mUidStats.valueAt(i);
1529             final Timer scanTimer = uid.getBluetoothScanTimer();
1530             final long scanTimeMs =
1531                     scanTimer != null ? scanTimer.getTotalTimeLocked(
1532                             elapsedRealtimeUs, STATS_SINCE_CHARGED) / 1000 : 0;
1533 
1534             final Timer unoptimizedScanTimer = uid.getBluetoothUnoptimizedScanTimer();
1535             final long unoptimizedScanTimeMs =
1536                     unoptimizedScanTimer != null ? unoptimizedScanTimer.getTotalTimeLocked(
1537                             elapsedRealtimeUs, STATS_SINCE_CHARGED) / 1000 : 0;
1538 
1539             final Counter scanResultCounter = uid.getBluetoothScanResultCounter();
1540             final int scanResultCount =
1541                     scanResultCounter != null ? scanResultCounter.getCountLocked(
1542                             STATS_SINCE_CHARGED) : 0;
1543 
1544             final ControllerActivityCounter counter = uid.getBluetoothControllerActivity();
1545             final long rxTimeMs =  counter != null ? counter.getRxTimeCounter().getCountLocked(
1546                     STATS_SINCE_CHARGED) : 0;
1547             final long txTimeMs =  counter != null ? counter.getTxTimeCounters()[0].getCountLocked(
1548                     STATS_SINCE_CHARGED) : 0;
1549 
1550             if (scanTimeMs != 0 || unoptimizedScanTimeMs != 0 || scanResultCount != 0
1551                     || rxTimeMs != 0 || txTimeMs != 0) {
1552                 uidStats.add(new BluetoothBatteryStats.UidStats(uid.getUid(),
1553                         scanTimeMs,
1554                         unoptimizedScanTimeMs,
1555                         scanResultCount,
1556                         rxTimeMs,
1557                         txTimeMs));
1558             }
1559         }
1560 
1561         return new BluetoothBatteryStats(uidStats);
1562     }
1563 
1564     String mLastWakeupReason = null;
1565     long mLastWakeupUptimeMs = 0;
1566     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
1567 
getWakeupReasonStats()1568     public Map<String, ? extends Timer> getWakeupReasonStats() {
1569         return mWakeupReasonStats;
1570     }
1571 
1572     @Override
getUahDischarge(int which)1573     public long getUahDischarge(int which) {
1574         return mDischargeCounter.getCountLocked(which);
1575     }
1576 
1577     @Override
getUahDischargeScreenOff(int which)1578     public long getUahDischargeScreenOff(int which) {
1579         return mDischargeScreenOffCounter.getCountLocked(which);
1580     }
1581 
1582     @Override
getUahDischargeScreenDoze(int which)1583     public long getUahDischargeScreenDoze(int which) {
1584         return mDischargeScreenDozeCounter.getCountLocked(which);
1585     }
1586 
1587     @Override
getUahDischargeLightDoze(int which)1588     public long getUahDischargeLightDoze(int which) {
1589         return mDischargeLightDozeCounter.getCountLocked(which);
1590     }
1591 
1592     @Override
getUahDischargeDeepDoze(int which)1593     public long getUahDischargeDeepDoze(int which) {
1594         return mDischargeDeepDozeCounter.getCountLocked(which);
1595     }
1596 
1597     @Override
getEstimatedBatteryCapacity()1598     public int getEstimatedBatteryCapacity() {
1599         return mEstimatedBatteryCapacityMah;
1600     }
1601 
1602     @Override
getLearnedBatteryCapacity()1603     public int getLearnedBatteryCapacity() {
1604         return mLastLearnedBatteryCapacityUah;
1605     }
1606 
1607     @Override
getMinLearnedBatteryCapacity()1608     public int getMinLearnedBatteryCapacity() {
1609         return mMinLearnedBatteryCapacityUah;
1610     }
1611 
1612     @Override
getMaxLearnedBatteryCapacity()1613     public int getMaxLearnedBatteryCapacity() {
1614         return mMaxLearnedBatteryCapacityUah;
1615     }
1616 
BatteryStatsImpl()1617     public BatteryStatsImpl() {
1618         this(Clock.SYSTEM_CLOCK);
1619     }
1620 
BatteryStatsImpl(Clock clock)1621     public BatteryStatsImpl(Clock clock) {
1622         this(clock, (File) null);
1623     }
1624 
BatteryStatsImpl(Clock clock, File historyDirectory)1625     public BatteryStatsImpl(Clock clock, File historyDirectory) {
1626         init(clock);
1627         mStartClockTimeMs = clock.currentTimeMillis();
1628         mCheckinFile = null;
1629         mDailyFile = null;
1630         if (historyDirectory == null) {
1631             mStatsFile = null;
1632             mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
1633         } else {
1634             mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
1635             mBatteryStatsHistory = new BatteryStatsHistory(this, historyDirectory, mHistoryBuffer);
1636         }
1637         mHandler = null;
1638         mPlatformIdleStateCallback = null;
1639         mMeasuredEnergyRetriever = null;
1640         mUserInfoProvider = null;
1641         mConstants = new Constants(mHandler);
1642         clearHistoryLocked();
1643     }
1644 
init(Clock clock)1645     private void init(Clock clock) {
1646         mClock = clock;
1647         mCpuUidUserSysTimeReader = new KernelCpuUidUserSysTimeReader(true, clock);
1648         mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(true, clock);
1649         mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(true, clock);
1650         mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(true, clock);
1651     }
1652 
1653     /**
1654      * TimeBase observer.
1655      */
1656     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1657         void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1658         void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
1659 
1660         /**
1661          * Reset the observer's state, returns true if the timer/counter is inactive
1662          * so it can be destroyed.
1663          * @param detachIfReset detach if true, no-op if false.
1664          * @return Returns true if the timer/counter is inactive and can be destroyed.
1665          */
reset(boolean detachIfReset)1666         default boolean reset(boolean detachIfReset) {
1667             return reset(detachIfReset, SystemClock.elapsedRealtime() * 1000);
1668         }
1669 
1670         /**
1671          * @see #reset(boolean)
1672          * @param detachIfReset detach if true, no-op if false.
1673          * @param elapsedRealtimeUs the timestamp when this reset is actually reequested
1674          * @return Returns true if the timer/counter is inactive and can be destroyed.
1675          */
reset(boolean detachIfReset, long elapsedRealtimeUs)1676         boolean reset(boolean detachIfReset, long elapsedRealtimeUs);
1677 
1678         /**
1679          * Detach the observer from TimeBase.
1680          */
detach()1681         void detach();
1682     }
1683 
1684     // methods are protected not private to be VisibleForTesting
1685     public static class TimeBase {
1686         protected final Collection<TimeBaseObs> mObservers;
1687 
1688         // All below time metrics are in microseconds.
1689         protected long mUptimeUs;
1690         protected long mRealtimeUs;
1691 
1692         protected boolean mRunning;
1693 
1694         protected long mPastUptimeUs;
1695         protected long mUptimeStartUs;
1696         protected long mPastRealtimeUs;
1697         protected long mRealtimeStartUs;
1698         protected long mUnpluggedUptimeUs;
1699         protected long mUnpluggedRealtimeUs;
1700 
dump(PrintWriter pw, String prefix)1701         public void dump(PrintWriter pw, String prefix) {
1702             StringBuilder sb = new StringBuilder(128);
1703             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
1704             sb.setLength(0);
1705             sb.append(prefix);
1706                     sb.append("mUptime=");
1707                     formatTimeMs(sb, mUptimeUs / 1000);
1708             pw.println(sb.toString());
1709             sb.setLength(0);
1710             sb.append(prefix);
1711                     sb.append("mRealtime=");
1712                     formatTimeMs(sb, mRealtimeUs / 1000);
1713             pw.println(sb.toString());
1714             sb.setLength(0);
1715             sb.append(prefix);
1716                     sb.append("mPastUptime=");
1717                     formatTimeMs(sb, mPastUptimeUs / 1000); sb.append("mUptimeStart=");
1718                     formatTimeMs(sb, mUptimeStartUs / 1000);
1719                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptimeUs / 1000);
1720             pw.println(sb.toString());
1721             sb.setLength(0);
1722             sb.append(prefix);
1723                     sb.append("mPastRealtime=");
1724                     formatTimeMs(sb, mPastRealtimeUs / 1000); sb.append("mRealtimeStart=");
1725                     formatTimeMs(sb, mRealtimeStartUs / 1000);
1726                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtimeUs / 1000);
1727             pw.println(sb.toString());
1728         }
1729         /**
1730          * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
1731          * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
1732          * entries.
1733          * mObservers must have good performance on add(), remove(), also be memory efficient.
1734          * This is why we provide isLongList parameter for long and short list user cases.
1735          * @param isLongList If true, use HashSet for mObservers list.
1736          *                   If false, use ArrayList for mObservers list.
1737         */
TimeBase(boolean isLongList)1738         public TimeBase(boolean isLongList) {
1739             mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
1740         }
1741 
TimeBase()1742         public TimeBase() {
1743             this(false);
1744         }
1745 
add(TimeBaseObs observer)1746         public void add(TimeBaseObs observer) {
1747             mObservers.add(observer);
1748         }
1749 
remove(TimeBaseObs observer)1750         public void remove(TimeBaseObs observer) {
1751             mObservers.remove(observer);
1752         }
1753 
hasObserver(TimeBaseObs observer)1754         public boolean hasObserver(TimeBaseObs observer) {
1755             return mObservers.contains(observer);
1756         }
1757 
init(long uptimeUs, long elapsedRealtimeUs)1758         public void init(long uptimeUs, long elapsedRealtimeUs) {
1759             mRealtimeUs = 0;
1760             mUptimeUs = 0;
1761             mPastUptimeUs = 0;
1762             mPastRealtimeUs = 0;
1763             mUptimeStartUs = uptimeUs;
1764             mRealtimeStartUs = elapsedRealtimeUs;
1765             mUnpluggedUptimeUs = getUptime(mUptimeStartUs);
1766             mUnpluggedRealtimeUs = getRealtime(mRealtimeStartUs);
1767         }
1768 
reset(long uptimeUs, long elapsedRealtimeUs)1769         public void reset(long uptimeUs, long elapsedRealtimeUs) {
1770             if (!mRunning) {
1771                 mPastUptimeUs = 0;
1772                 mPastRealtimeUs = 0;
1773             } else {
1774                 mUptimeStartUs = uptimeUs;
1775                 mRealtimeStartUs = elapsedRealtimeUs;
1776                 // TODO: Since mUptimeStartUs was just reset and we are running, getUptime will
1777                 // just return mPastUptimeUs. Also, are we sure we don't want to reset that?
1778                 mUnpluggedUptimeUs = getUptime(uptimeUs);
1779                 // TODO: likewise.
1780                 mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
1781             }
1782         }
1783 
computeUptime(long curTimeUs, int which)1784         public long computeUptime(long curTimeUs, int which) {
1785             return mUptimeUs + getUptime(curTimeUs);
1786         }
1787 
computeRealtime(long curTimeUs, int which)1788         public long computeRealtime(long curTimeUs, int which) {
1789             return mRealtimeUs + getRealtime(curTimeUs);
1790         }
1791 
getUptime(long curTimeUs)1792         public long getUptime(long curTimeUs) {
1793             long time = mPastUptimeUs;
1794             if (mRunning) {
1795                 time += curTimeUs - mUptimeStartUs;
1796             }
1797             return time;
1798         }
1799 
getRealtime(long curTimeUs)1800         public long getRealtime(long curTimeUs) {
1801             long time = mPastRealtimeUs;
1802             if (mRunning) {
1803                 time += curTimeUs - mRealtimeStartUs;
1804             }
1805             return time;
1806         }
1807 
getUptimeStart()1808         public long getUptimeStart() {
1809             return mUptimeStartUs;
1810         }
1811 
getRealtimeStart()1812         public long getRealtimeStart() {
1813             return mRealtimeStartUs;
1814         }
1815 
isRunning()1816         public boolean isRunning() {
1817             return mRunning;
1818         }
1819 
setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs)1820         public boolean setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs) {
1821             if (mRunning != running) {
1822                 mRunning = running;
1823                 if (running) {
1824                     mUptimeStartUs = uptimeUs;
1825                     mRealtimeStartUs = elapsedRealtimeUs;
1826                     long batteryUptimeUs = mUnpluggedUptimeUs = getUptime(uptimeUs);
1827                     long batteryRealtimeUs = mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
1828                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1829                     // Iterator object, here is an exception because mObservers' type is Collection
1830                     // instead of list.
1831                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1832                     while (iter.hasNext()) {
1833                         iter.next().onTimeStarted(
1834                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
1835                     }
1836                 } else {
1837                     mPastUptimeUs += uptimeUs - mUptimeStartUs;
1838                     mPastRealtimeUs += elapsedRealtimeUs - mRealtimeStartUs;
1839                     long batteryUptimeUs = getUptime(uptimeUs);
1840                     long batteryRealtimeUs = getRealtime(elapsedRealtimeUs);
1841                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1842                     // Iterator object, here is an exception because mObservers' type is Collection
1843                     // instead of list.
1844                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1845                     while (iter.hasNext()) {
1846                         iter.next().onTimeStopped(
1847                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
1848                     }
1849                 }
1850                 return true;
1851             }
1852             return false;
1853         }
1854 
readSummaryFromParcel(Parcel in)1855         public void readSummaryFromParcel(Parcel in) {
1856             mUptimeUs = in.readLong();
1857             mRealtimeUs = in.readLong();
1858         }
1859 
writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)1860         public void writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
1861             out.writeLong(computeUptime(uptimeUs, STATS_SINCE_CHARGED));
1862             out.writeLong(computeRealtime(elapsedRealtimeUs, STATS_SINCE_CHARGED));
1863         }
1864 
readFromParcel(Parcel in)1865         public void readFromParcel(Parcel in) {
1866             mRunning = false;
1867             mUptimeUs = in.readLong();
1868             mPastUptimeUs = in.readLong();
1869             mUptimeStartUs = in.readLong();
1870             mRealtimeUs = in.readLong();
1871             mPastRealtimeUs = in.readLong();
1872             mRealtimeStartUs = in.readLong();
1873             mUnpluggedUptimeUs = in.readLong();
1874             mUnpluggedRealtimeUs = in.readLong();
1875         }
1876 
writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)1877         public void writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
1878             final long runningUptime = getUptime(uptimeUs);
1879             final long runningRealtime = getRealtime(elapsedRealtimeUs);
1880             out.writeLong(mUptimeUs);
1881             out.writeLong(runningUptime);
1882             out.writeLong(mUptimeStartUs);
1883             out.writeLong(mRealtimeUs);
1884             out.writeLong(runningRealtime);
1885             out.writeLong(mRealtimeStartUs);
1886             out.writeLong(mUnpluggedUptimeUs);
1887             out.writeLong(mUnpluggedRealtimeUs);
1888         }
1889     }
1890 
1891     /**
1892      * State for keeping track of counting information.
1893      */
1894     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
1895         @UnsupportedAppUsage
1896         final AtomicInteger mCount = new AtomicInteger();
1897         final TimeBase mTimeBase;
1898 
Counter(TimeBase timeBase, Parcel in)1899         public Counter(TimeBase timeBase, Parcel in) {
1900             mTimeBase = timeBase;
1901             mCount.set(in.readInt());
1902             timeBase.add(this);
1903         }
1904 
Counter(TimeBase timeBase)1905         public Counter(TimeBase timeBase) {
1906             mTimeBase = timeBase;
1907             timeBase.add(this);
1908         }
1909 
writeToParcel(Parcel out)1910         public void writeToParcel(Parcel out) {
1911             out.writeInt(mCount.get());
1912         }
1913 
1914         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1915         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1916         }
1917 
1918         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1919         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1920         }
1921 
1922         /**
1923          * Writes a possibly null Counter to a Parcel.
1924          *
1925          * @param out the Parcel to be written to.
1926          * @param counter a Counter, or null.
1927          */
writeCounterToParcel(Parcel out, @Nullable Counter counter)1928         public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
1929             if (counter == null) {
1930                 out.writeInt(0); // indicates null
1931                 return;
1932             }
1933             out.writeInt(1); // indicates non-null
1934 
1935             counter.writeToParcel(out);
1936         }
1937 
1938         /**
1939          * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
1940          * @param timeBase the timebase to assign to the Counter
1941          * @param in the parcel to read from
1942          * @return the Counter or null.
1943          */
1944         @Nullable
readCounterFromParcel(TimeBase timeBase, Parcel in)1945         public static Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
1946             if (in.readInt() == 0) {
1947                 return null;
1948             }
1949             return new Counter(timeBase, in);
1950         }
1951 
1952         @Override
getCountLocked(int which)1953         public int getCountLocked(int which) {
1954             return mCount.get();
1955         }
1956 
logState(Printer pw, String prefix)1957         public void logState(Printer pw, String prefix) {
1958             pw.println(prefix + "mCount=" + mCount.get());
1959         }
1960 
1961         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()1962         public void stepAtomic() {
1963             if (mTimeBase.isRunning()) {
1964                 mCount.incrementAndGet();
1965             }
1966         }
1967 
addAtomic(int delta)1968         void addAtomic(int delta) {
1969             if (mTimeBase.isRunning()) {
1970                 mCount.addAndGet(delta);
1971             }
1972         }
1973 
1974         /**
1975          * Clear state of this counter.
1976          */
1977         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )1978         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
1979             mCount.set(0);
1980             if (detachIfReset) {
1981                 detach();
1982             }
1983             return true;
1984         }
1985 
1986         @Override
detach()1987         public void detach() {
1988             mTimeBase.remove(this);
1989         }
1990 
1991         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)1992         public void writeSummaryFromParcelLocked(Parcel out) {
1993             out.writeInt(mCount.get());
1994         }
1995 
1996         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)1997         public void readSummaryFromParcelLocked(Parcel in) {
1998             mCount.set(in.readInt());
1999         }
2000     }
2001 
2002     @VisibleForTesting
2003     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
2004         final TimeBase mTimeBase;
2005         public long[] mCounts;
2006 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)2007         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
2008             mTimeBase = timeBase;
2009             mCounts = in.createLongArray();
2010             timeBase.add(this);
2011         }
2012 
LongSamplingCounterArray(TimeBase timeBase)2013         public LongSamplingCounterArray(TimeBase timeBase) {
2014             mTimeBase = timeBase;
2015             timeBase.add(this);
2016         }
2017 
writeToParcel(Parcel out)2018         private void writeToParcel(Parcel out) {
2019             out.writeLongArray(mCounts);
2020         }
2021 
2022         @Override
onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs)2023         public void onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs) {
2024         }
2025 
2026         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2027         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2028         }
2029 
2030         @Override
getCountsLocked(int which)2031         public long[] getCountsLocked(int which) {
2032             return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
2033         }
2034 
2035         @Override
logState(Printer pw, String prefix)2036         public void logState(Printer pw, String prefix) {
2037             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
2038         }
2039 
addCountLocked(long[] counts)2040         public void addCountLocked(long[] counts) {
2041             addCountLocked(counts, mTimeBase.isRunning());
2042         }
2043 
addCountLocked(long[] counts, boolean isRunning)2044         public void addCountLocked(long[] counts, boolean isRunning) {
2045             if (counts == null) {
2046                 return;
2047             }
2048             if (isRunning) {
2049                 if (mCounts == null) {
2050                     mCounts = new long[counts.length];
2051                 }
2052                 for (int i = 0; i < counts.length; ++i) {
2053                     mCounts[i] += counts[i];
2054                 }
2055             }
2056         }
2057 
getSize()2058         public int getSize() {
2059             return mCounts == null ? 0 : mCounts.length;
2060         }
2061 
2062         /**
2063          * Clear state of this counter.
2064          */
2065         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2066         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2067             if (mCounts != null) {
2068                 Arrays.fill(mCounts, 0);
2069             }
2070             if (detachIfReset) {
2071                 detach();
2072             }
2073             return true;
2074         }
2075 
2076         @Override
detach()2077         public void detach() {
2078             mTimeBase.remove(this);
2079         }
2080 
writeSummaryToParcelLocked(Parcel out)2081         private void writeSummaryToParcelLocked(Parcel out) {
2082             out.writeLongArray(mCounts);
2083         }
2084 
readSummaryFromParcelLocked(Parcel in)2085         private void readSummaryFromParcelLocked(Parcel in) {
2086             mCounts = in.createLongArray();
2087         }
2088 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)2089         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
2090             if (counterArray != null) {
2091                 out.writeInt(1);
2092                 counterArray.writeToParcel(out);
2093             } else {
2094                 out.writeInt(0);
2095             }
2096         }
2097 
readFromParcel(Parcel in, TimeBase timeBase)2098         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
2099             if (in.readInt() != 0) {
2100                 return new LongSamplingCounterArray(timeBase, in);
2101             } else {
2102                 return null;
2103             }
2104         }
2105 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)2106         public static void writeSummaryToParcelLocked(Parcel out,
2107                 LongSamplingCounterArray counterArray) {
2108             if (counterArray != null) {
2109                 out.writeInt(1);
2110                 counterArray.writeSummaryToParcelLocked(out);
2111             } else {
2112                 out.writeInt(0);
2113             }
2114         }
2115 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)2116         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
2117                 TimeBase timeBase) {
2118             if (in.readInt() != 0) {
2119                 final LongSamplingCounterArray counterArray
2120                         = new LongSamplingCounterArray(timeBase);
2121                 counterArray.readSummaryFromParcelLocked(in);
2122                 return counterArray;
2123             } else {
2124                 return null;
2125             }
2126         }
2127     }
2128 
2129     private static class TimeMultiStateCounter extends LongCounter implements TimeBaseObs {
2130         private final TimeBase mTimeBase;
2131         private final LongMultiStateCounter mCounter;
2132 
TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs)2133         private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) {
2134             this(timeBase, new LongMultiStateCounter(stateCount), timestampMs);
2135         }
2136 
TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter, long timestampMs)2137         private TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter,
2138                 long timestampMs) {
2139             mTimeBase = timeBase;
2140             mCounter = counter;
2141             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
2142             timeBase.add(this);
2143         }
2144 
2145         @Nullable
readFromParcel(Parcel in, TimeBase timeBase, int stateCount, long timestampMs)2146         private static TimeMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
2147                 int stateCount, long timestampMs) {
2148             LongMultiStateCounter counter = LongMultiStateCounter.CREATOR.createFromParcel(in);
2149             if (counter.getStateCount() != stateCount) {
2150                 return null;
2151             }
2152             return new TimeMultiStateCounter(timeBase, counter, timestampMs);
2153         }
2154 
writeToParcel(Parcel out)2155         private void writeToParcel(Parcel out) {
2156             mCounter.writeToParcel(out, 0);
2157         }
2158 
2159         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2160         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2161             mCounter.setEnabled(true, elapsedRealtimeUs / 1000);
2162         }
2163 
2164         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2165         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2166             mCounter.setEnabled(false, elapsedRealtimeUs / 1000);
2167         }
2168 
getStateCount()2169         public int getStateCount() {
2170             return mCounter.getStateCount();
2171         }
2172 
setState(@atteryConsumer.ProcessState int processState, long elapsedRealtimeMs)2173         private void setState(@BatteryConsumer.ProcessState int processState,
2174                 long elapsedRealtimeMs) {
2175             mCounter.setState(processState, elapsedRealtimeMs);
2176         }
2177 
update(long value, long timestampMs)2178         private long update(long value, long timestampMs) {
2179             return mCounter.updateValue(value, timestampMs);
2180         }
2181 
increment(long increment, long timestampMs)2182         private void increment(long increment, long timestampMs) {
2183             mCounter.incrementValue(increment, timestampMs);
2184         }
2185 
2186         /**
2187          * Returns accumulated count for the specified state.
2188          */
getCountForProcessState(@atteryConsumer.ProcessState int procState)2189         public long getCountForProcessState(@BatteryConsumer.ProcessState int procState) {
2190             return mCounter.getCount(procState);
2191         }
2192 
getTotalCountLocked()2193         public long getTotalCountLocked() {
2194             return mCounter.getTotalCount();
2195         }
2196 
2197         @Override
getCountLocked(int statsType)2198         public long getCountLocked(int statsType) {
2199             return getTotalCountLocked();
2200         }
2201 
2202         @Override
logState(Printer pw, String prefix)2203         public void logState(Printer pw, String prefix) {
2204             pw.println(prefix + "mCounter=" + mCounter);
2205         }
2206 
2207         /**
2208          * Clears state of this counter.
2209          */
2210         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2211         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2212             mCounter.reset();
2213             if (detachIfReset) {
2214                 detach();
2215             }
2216             return true;
2217         }
2218 
2219         @Override
detach()2220         public void detach() {
2221             mTimeBase.remove(this);
2222         }
2223     }
2224 
2225     private static class TimeInFreqMultiStateCounter implements TimeBaseObs {
2226         private final TimeBase mTimeBase;
2227         private final LongArrayMultiStateCounter mCounter;
2228 
TimeInFreqMultiStateCounter(TimeBase timeBase, int stateCount, int cpuFreqCount, long timestampMs)2229         private TimeInFreqMultiStateCounter(TimeBase timeBase, int stateCount, int cpuFreqCount,
2230                 long timestampMs) {
2231             this(timeBase, new LongArrayMultiStateCounter(stateCount, cpuFreqCount), timestampMs);
2232         }
2233 
TimeInFreqMultiStateCounter(TimeBase timeBase, LongArrayMultiStateCounter counter, long timestampMs)2234         private TimeInFreqMultiStateCounter(TimeBase timeBase, LongArrayMultiStateCounter counter,
2235                 long timestampMs) {
2236             mTimeBase = timeBase;
2237             mCounter = counter;
2238             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
2239             timeBase.add(this);
2240         }
2241 
writeToParcel(Parcel out)2242         private void writeToParcel(Parcel out) {
2243             mCounter.writeToParcel(out, 0);
2244         }
2245 
2246         @Nullable
readFromParcel(Parcel in, TimeBase timeBase, int stateCount, int cpuFreqCount, long timestampMs)2247         private static TimeInFreqMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
2248                 int stateCount, int cpuFreqCount, long timestampMs) {
2249             // Read the object from the Parcel, whether it's usable or not
2250             LongArrayMultiStateCounter counter =
2251                     LongArrayMultiStateCounter.CREATOR.createFromParcel(in);
2252             if (counter.getStateCount() != stateCount
2253                     || counter.getArrayLength() != cpuFreqCount) {
2254                 return null;
2255             }
2256             return new TimeInFreqMultiStateCounter(timeBase, counter, timestampMs);
2257         }
2258 
2259         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2260         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2261             mCounter.setEnabled(true, elapsedRealtimeUs / 1000);
2262         }
2263 
2264         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2265         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2266             mCounter.setEnabled(false, elapsedRealtimeUs / 1000);
2267         }
2268 
getCounter()2269         public LongArrayMultiStateCounter getCounter() {
2270             return mCounter;
2271         }
2272 
getStateCount()2273         public int getStateCount() {
2274             return mCounter.getStateCount();
2275         }
2276 
setTrackingEnabled(boolean enabled, long timestampMs)2277         public void setTrackingEnabled(boolean enabled, long timestampMs) {
2278             mCounter.setEnabled(enabled && mTimeBase.isRunning(), timestampMs);
2279         }
2280 
setState(int uidRunningState, long elapsedRealtimeMs)2281         private void setState(int uidRunningState, long elapsedRealtimeMs) {
2282             mCounter.setState(uidRunningState, elapsedRealtimeMs);
2283         }
2284 
2285         /**
2286          * Returns accumulated counts for the specified state, or false if all counts are zero.
2287          */
getCountsLocked(long[] counts, int procState)2288         public boolean getCountsLocked(long[] counts, int procState) {
2289             if (counts.length != mCounter.getArrayLength()) {
2290                 return false;
2291             }
2292 
2293             mCounter.getCounts(counts, procState);
2294 
2295             // Return counts only if at least one of the elements is non-zero.
2296             for (int i = counts.length - 1; i >= 0; --i) {
2297                 if (counts[i] != 0) {
2298                     return true;
2299                 }
2300             }
2301             return false;
2302         }
2303 
logState(Printer pw, String prefix)2304         public void logState(Printer pw, String prefix) {
2305             pw.println(prefix + "mCounter=" + mCounter);
2306         }
2307 
2308         /**
2309          * Clears state of this counter.
2310          */
2311         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2312         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2313             mCounter.reset();
2314             if (detachIfReset) {
2315                 detach();
2316             }
2317             return true;
2318         }
2319 
2320         @Override
detach()2321         public void detach() {
2322             mTimeBase.remove(this);
2323         }
2324     }
2325 
2326     @VisibleForTesting
2327     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
2328         final TimeBase mTimeBase;
2329         private long mCount;
2330 
LongSamplingCounter(TimeBase timeBase, Parcel in)2331         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
2332             mTimeBase = timeBase;
2333             mCount = in.readLong();
2334             timeBase.add(this);
2335         }
2336 
LongSamplingCounter(TimeBase timeBase)2337         public LongSamplingCounter(TimeBase timeBase) {
2338             mTimeBase = timeBase;
2339             timeBase.add(this);
2340         }
2341 
writeToParcel(Parcel out)2342         public void writeToParcel(Parcel out) {
2343             out.writeLong(mCount);
2344         }
2345 
2346         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2347         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2348         }
2349 
2350         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2351         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2352         }
2353 
getCountLocked(int which)2354         public long getCountLocked(int which) {
2355             return mCount;
2356         }
2357 
2358         @Override
getCountForProcessState(int procState)2359         public long getCountForProcessState(int procState) {
2360             if (procState == BatteryConsumer.PROCESS_STATE_ANY) {
2361                 return getCountLocked(STATS_SINCE_CHARGED);
2362             }
2363             return 0;
2364         }
2365 
2366         @Override
logState(Printer pw, String prefix)2367         public void logState(Printer pw, String prefix) {
2368             pw.println(prefix + "mCount=" + mCount);
2369         }
2370 
addCountLocked(long count)2371         public void addCountLocked(long count) {
2372             addCountLocked(count, mTimeBase.isRunning());
2373         }
2374 
addCountLocked(long count, boolean isRunning)2375         public void addCountLocked(long count, boolean isRunning) {
2376             if (isRunning) {
2377                 mCount += count;
2378             }
2379         }
2380 
2381         /**
2382          * Clear state of this counter.
2383          */
2384         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2385         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2386             mCount = 0;
2387             if (detachIfReset) {
2388                 detach();
2389             }
2390             return true;
2391         }
2392 
2393         @Override
detach()2394         public void detach() {
2395             mTimeBase.remove(this);
2396         }
2397 
writeSummaryFromParcelLocked(Parcel out)2398         public void writeSummaryFromParcelLocked(Parcel out) {
2399             out.writeLong(mCount);
2400         }
2401 
readSummaryFromParcelLocked(Parcel in)2402         public void readSummaryFromParcelLocked(Parcel in) {
2403             mCount = in.readLong();
2404         }
2405     }
2406 
2407     /**
2408      * State for keeping track of timing information.
2409      */
2410     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
2411         protected final Clock mClock;
2412         protected final int mType;
2413         protected final TimeBase mTimeBase;
2414 
2415         protected int mCount;
2416 
2417         // Times are in microseconds for better accuracy when dividing by the
2418         // lock count, and are in "battery realtime" units.
2419 
2420         /**
2421          * The total time we have accumulated since the start of the original
2422          * boot, to the last time something interesting happened in the
2423          * current run.
2424          */
2425         protected long mTotalTimeUs;
2426 
2427         /**
2428          * The total time this timer has been running until the latest mark has been set.
2429          * Subtract this from mTotalTimeUs to get the time spent running since the mark was set.
2430          */
2431         protected long mTimeBeforeMarkUs;
2432 
2433         /**
2434          * Constructs from a parcel.
2435          * @param type
2436          * @param timeBase
2437          * @param in
2438          */
Timer(Clock clock, int type, TimeBase timeBase, Parcel in)2439         public Timer(Clock clock, int type, TimeBase timeBase, Parcel in) {
2440             mClock = clock;
2441             mType = type;
2442             mTimeBase = timeBase;
2443 
2444             mCount = in.readInt();
2445             mTotalTimeUs = in.readLong();
2446             mTimeBeforeMarkUs = in.readLong();
2447             timeBase.add(this);
2448             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTimeUs);
2449         }
2450 
Timer(Clock clock, int type, TimeBase timeBase)2451         public Timer(Clock clock, int type, TimeBase timeBase) {
2452             mClock = clock;
2453             mType = type;
2454             mTimeBase = timeBase;
2455             timeBase.add(this);
2456         }
2457 
writeToParcel(Parcel out, long elapsedRealtimeUs)2458         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2459             if (DEBUG) {
2460                 Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
2461                         + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2462                                 elapsedRealtimeUs));
2463             }
2464             out.writeInt(computeCurrentCountLocked());
2465             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2466                         elapsedRealtimeUs));
2467             out.writeLong(mTimeBeforeMarkUs);
2468         }
2469 
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)2470         protected abstract long computeRunTimeLocked(long curBatteryRealtime,
2471                 long elapsedRealtimeUs);
2472 
computeCurrentCountLocked()2473         protected abstract int computeCurrentCountLocked();
2474 
2475         /**
2476          * Clear state of this timer.  Returns true if the timer is inactive
2477          * so can be completely dropped.
2478          */
2479         @Override
reset(boolean detachIfReset)2480         public boolean reset(boolean detachIfReset) {
2481             return reset(detachIfReset, mClock.elapsedRealtime() * 1000);
2482         }
2483 
2484         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2485         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2486             mTotalTimeUs = mTimeBeforeMarkUs = 0;
2487             mCount = 0;
2488             if (detachIfReset) {
2489                 detach();
2490             }
2491             return true;
2492         }
2493 
2494         @Override
detach()2495         public void detach() {
2496             mTimeBase.remove(this);
2497         }
2498 
2499         @Override
onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs, long baseRealtimeUs)2500         public void onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs,
2501                 long baseRealtimeUs) {
2502         }
2503 
2504         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2505         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2506             if (DEBUG && mType < 0) {
2507                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtimeUs
2508                         + " old mTotalTime=" + mTotalTimeUs);
2509             }
2510             mTotalTimeUs = computeRunTimeLocked(baseRealtimeUs, elapsedRealtimeUs);
2511             mCount = computeCurrentCountLocked();
2512             if (DEBUG && mType < 0) {
2513                 Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTimeUs);
2514             }
2515         }
2516 
2517         /**
2518          * Writes a possibly null Timer to a Parcel.
2519          *
2520          * @param out the Parcel to be written to.
2521          * @param timer a Timer, or null.
2522          */
2523         @UnsupportedAppUsage
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)2524         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
2525             if (timer == null) {
2526                 out.writeInt(0); // indicates null
2527                 return;
2528             }
2529             out.writeInt(1); // indicates non-null
2530             timer.writeToParcel(out, elapsedRealtimeUs);
2531         }
2532 
2533         @Override
2534         @UnsupportedAppUsage
getTotalTimeLocked(long elapsedRealtimeUs, int which)2535         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
2536             return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2537                     elapsedRealtimeUs);
2538         }
2539 
2540         @Override
2541         @UnsupportedAppUsage
getCountLocked(int which)2542         public int getCountLocked(int which) {
2543             return computeCurrentCountLocked();
2544         }
2545 
2546         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)2547         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
2548             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2549                     elapsedRealtimeUs);
2550             return val - mTimeBeforeMarkUs;
2551         }
2552 
2553         @Override
logState(Printer pw, String prefix)2554         public void logState(Printer pw, String prefix) {
2555             pw.println(prefix + "mCount=" + mCount);
2556             pw.println(prefix + "mTotalTime=" + mTotalTimeUs);
2557         }
2558 
2559 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2560         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2561             long runTimeUs = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2562                     elapsedRealtimeUs);
2563             out.writeLong(runTimeUs);
2564             out.writeInt(computeCurrentCountLocked());
2565         }
2566 
readSummaryFromParcelLocked(Parcel in)2567         public void readSummaryFromParcelLocked(Parcel in) {
2568             // Multiply by 1000 for backwards compatibility
2569             mTotalTimeUs = in.readLong();
2570             mCount = in.readInt();
2571             // When reading the summary, we set the mark to be the latest information.
2572             mTimeBeforeMarkUs = mTotalTimeUs;
2573         }
2574     }
2575 
2576     /**
2577      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
2578      * method. The state of the timer according to its {@link TimeBase} will determine how much
2579      * of the value is recorded.
2580      *
2581      * If the value being recorded resets, {@link #endSample()} can be called in order to
2582      * account for the change. If the value passed in to {@link #update(long, int)} decreased
2583      * between calls, the {@link #endSample()} is automatically called and the new value is
2584      * expected to increase monotonically from that point on.
2585      */
2586     public static class SamplingTimer extends Timer {
2587 
2588         /**
2589          * The most recent reported count from /proc/wakelocks.
2590          */
2591         int mCurrentReportedCount;
2592 
2593         /**
2594          * The reported count from /proc/wakelocks when unplug() was last
2595          * called.
2596          */
2597         int mUnpluggedReportedCount;
2598 
2599         /**
2600          * The most recent reported total_time from /proc/wakelocks.
2601          */
2602         long mCurrentReportedTotalTimeUs;
2603 
2604 
2605         /**
2606          * The reported total_time from /proc/wakelocks when unplug() was last
2607          * called.
2608          */
2609         long mUnpluggedReportedTotalTimeUs;
2610 
2611         /**
2612          * Whether we are currently in a discharge cycle.
2613          */
2614         boolean mTimeBaseRunning;
2615 
2616         /**
2617          * Whether we are currently recording reported values.
2618          */
2619         boolean mTrackingReportedValues;
2620 
2621         /*
2622          * A sequence counter, incremented once for each update of the stats.
2623          */
2624         int mUpdateVersion;
2625 
2626         @VisibleForTesting
SamplingTimer(Clock clock, TimeBase timeBase, Parcel in)2627         public SamplingTimer(Clock clock, TimeBase timeBase, Parcel in) {
2628             super(clock, 0, timeBase, in);
2629             mCurrentReportedCount = in.readInt();
2630             mUnpluggedReportedCount = in.readInt();
2631             mCurrentReportedTotalTimeUs = in.readLong();
2632             mUnpluggedReportedTotalTimeUs = in.readLong();
2633             mTrackingReportedValues = in.readInt() == 1;
2634             mTimeBaseRunning = timeBase.isRunning();
2635         }
2636 
2637         @VisibleForTesting
SamplingTimer(Clock clock, TimeBase timeBase)2638         public SamplingTimer(Clock clock, TimeBase timeBase) {
2639             super(clock, 0, timeBase);
2640             mTrackingReportedValues = false;
2641             mTimeBaseRunning = timeBase.isRunning();
2642         }
2643 
2644         /**
2645          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
2646          * be less than the values used for a previous invocation.
2647          */
endSample()2648         public void endSample() {
2649             endSample(mClock.elapsedRealtime() * 1000);
2650         }
2651 
2652         /**
2653          * @see #endSample()
2654          */
endSample(long elapsedRealtimeUs)2655         public void endSample(long elapsedRealtimeUs) {
2656             mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs);
2657             mCount = computeCurrentCountLocked();
2658             mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0;
2659             mUnpluggedReportedCount = mCurrentReportedCount = 0;
2660             mTrackingReportedValues = false;
2661         }
2662 
setUpdateVersion(int version)2663         public void setUpdateVersion(int version) {
2664             mUpdateVersion = version;
2665         }
2666 
getUpdateVersion()2667         public int getUpdateVersion() {
2668             return mUpdateVersion;
2669         }
2670 
2671         /**
2672          * Updates the current recorded values. These are meant to be monotonically increasing
2673          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
2674          *
2675          * If the values being recorded have been reset, the monotonically increasing requirement
2676          * will be broken. In this case, {@link #endSample()} is automatically called and
2677          * the total value of totalTimeUs and count are recorded, starting a new monotonically
2678          * increasing sample.
2679          *
2680          * @param totalTimeUs total time of sample in microseconds.
2681          * @param count total number of times the event being sampled occurred.
2682          */
updated(long totalTimeUs, int count)2683         public void updated(long totalTimeUs, int count) {
2684             update(totalTimeUs, count, mClock.elapsedRealtime() * 1000);
2685         }
2686 
2687         /**
2688          * @see #update(long, int)
2689          */
update(long totalTimeUs, int count, long elapsedRealtimeUs)2690         public void update(long totalTimeUs, int count, long elapsedRealtimeUs) {
2691             if (mTimeBaseRunning && !mTrackingReportedValues) {
2692                 // Updating the reported value for the first time.
2693                 mUnpluggedReportedTotalTimeUs = totalTimeUs;
2694                 mUnpluggedReportedCount = count;
2695             }
2696 
2697             mTrackingReportedValues = true;
2698 
2699             if (totalTimeUs < mCurrentReportedTotalTimeUs || count < mCurrentReportedCount) {
2700                 endSample(elapsedRealtimeUs);
2701             }
2702 
2703             mCurrentReportedTotalTimeUs = totalTimeUs;
2704             mCurrentReportedCount = count;
2705         }
2706 
2707         /**
2708          * Adds deltaTime and deltaCount to the current sample.
2709          *
2710          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
2711          * @param deltaCount additional number of times the event being sampled occurred.
2712          */
add(long deltaTimeUs, int deltaCount)2713         public void add(long deltaTimeUs, int deltaCount) {
2714             add(deltaTimeUs, deltaCount, mClock.elapsedRealtime() * 1000);
2715         }
2716 
2717         /**
2718          * @see #add(long, int)
2719          */
add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs)2720         public void add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs) {
2721             update(mCurrentReportedTotalTimeUs + deltaTimeUs, mCurrentReportedCount + deltaCount,
2722                     elapsedRealtimeUs);
2723         }
2724 
2725         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2726         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2727             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2728             if (mTrackingReportedValues) {
2729                 mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs;
2730                 mUnpluggedReportedCount = mCurrentReportedCount;
2731             }
2732             mTimeBaseRunning = true;
2733         }
2734 
2735         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2736         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2737             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2738             mTimeBaseRunning = false;
2739         }
2740 
2741         @Override
logState(Printer pw, String prefix)2742         public void logState(Printer pw, String prefix) {
2743             super.logState(pw, prefix);
2744             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
2745                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
2746                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs
2747                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTimeUs);
2748         }
2749 
2750         @Override
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)2751         protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) {
2752             return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues
2753                     ? mCurrentReportedTotalTimeUs - mUnpluggedReportedTotalTimeUs : 0);
2754         }
2755 
2756         @Override
computeCurrentCountLocked()2757         protected int computeCurrentCountLocked() {
2758             return mCount + (mTimeBaseRunning && mTrackingReportedValues
2759                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
2760         }
2761 
2762         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2763         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2764             super.writeToParcel(out, elapsedRealtimeUs);
2765             out.writeInt(mCurrentReportedCount);
2766             out.writeInt(mUnpluggedReportedCount);
2767             out.writeLong(mCurrentReportedTotalTimeUs);
2768             out.writeLong(mUnpluggedReportedTotalTimeUs);
2769             out.writeInt(mTrackingReportedValues ? 1 : 0);
2770         }
2771 
2772         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2773         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2774             super.reset(detachIfReset, elapsedRealtimeUs);
2775             mTrackingReportedValues = false;
2776             mUnpluggedReportedTotalTimeUs = 0;
2777             mUnpluggedReportedCount = 0;
2778             return true;
2779         }
2780     }
2781 
2782     /**
2783      * A timer that increments in batches.  It does not run for durations, but just jumps
2784      * for a pre-determined amount.
2785      */
2786     public static class BatchTimer extends Timer {
2787         final Uid mUid;
2788 
2789         /**
2790          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
2791          */
2792         long mLastAddedTimeUs;
2793 
2794         /**
2795          * The last duration that we added to the timer.  This is in microseconds.
2796          */
2797         long mLastAddedDurationUs;
2798 
2799         /**
2800          * Whether we are currently in a discharge cycle.
2801          */
2802         boolean mInDischarge;
2803 
BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase, Parcel in)2804         BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase, Parcel in) {
2805             super(clock, type, timeBase, in);
2806             mUid = uid;
2807             mLastAddedTimeUs = in.readLong();
2808             mLastAddedDurationUs = in.readLong();
2809             mInDischarge = timeBase.isRunning();
2810         }
2811 
BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase)2812         BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase) {
2813             super(clock, type, timeBase);
2814             mUid = uid;
2815             mInDischarge = timeBase.isRunning();
2816         }
2817 
2818         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2819         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2820             super.writeToParcel(out, elapsedRealtimeUs);
2821             out.writeLong(mLastAddedTimeUs);
2822             out.writeLong(mLastAddedDurationUs);
2823         }
2824 
2825         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2826         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2827             recomputeLastDuration(elapsedRealtimeUs, false);
2828             mInDischarge = false;
2829             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2830         }
2831 
2832         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2833         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2834             recomputeLastDuration(elapsedRealtimeUs, false);
2835             mInDischarge = true;
2836             // If we are still within the last added duration, then re-added whatever remains.
2837             if (mLastAddedTimeUs == elapsedRealtimeUs) {
2838                 mTotalTimeUs += mLastAddedDurationUs;
2839             }
2840             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2841         }
2842 
2843         @Override
logState(Printer pw, String prefix)2844         public void logState(Printer pw, String prefix) {
2845             super.logState(pw, prefix);
2846             pw.println(prefix + "mLastAddedTime=" + mLastAddedTimeUs
2847                     + " mLastAddedDuration=" + mLastAddedDurationUs);
2848         }
2849 
computeOverage(long curTimeUs)2850         private long computeOverage(long curTimeUs) {
2851             if (mLastAddedTimeUs > 0) {
2852                 return mLastAddedDurationUs - curTimeUs;
2853             }
2854             return 0;
2855         }
2856 
recomputeLastDuration(long curTimeUs, boolean abort)2857         private void recomputeLastDuration(long curTimeUs, boolean abort) {
2858             final long overage = computeOverage(curTimeUs);
2859             if (overage > 0) {
2860                 // Aborting before the duration ran out -- roll back the remaining
2861                 // duration.  Only do this if currently discharging; otherwise we didn't
2862                 // actually add the time.
2863                 if (mInDischarge) {
2864                     mTotalTimeUs -= overage;
2865                 }
2866                 if (abort) {
2867                     mLastAddedTimeUs = 0;
2868                 } else {
2869                     mLastAddedTimeUs = curTimeUs;
2870                     mLastAddedDurationUs -= overage;
2871                 }
2872             }
2873         }
2874 
addDuration(BatteryStatsImpl stats, long durationMs)2875         public void addDuration(BatteryStatsImpl stats, long durationMs) {
2876             addDuration(stats, durationMs, mClock.elapsedRealtime());
2877         }
2878 
addDuration(BatteryStatsImpl stats, long durationMs, long elapsedRealtimeMs)2879         public void addDuration(BatteryStatsImpl stats, long durationMs, long elapsedRealtimeMs) {
2880             final long nowUs = elapsedRealtimeMs * 1000;
2881             recomputeLastDuration(nowUs, true);
2882             mLastAddedTimeUs = nowUs;
2883             mLastAddedDurationUs = durationMs * 1000;
2884             if (mInDischarge) {
2885                 mTotalTimeUs += mLastAddedDurationUs;
2886                 mCount++;
2887             }
2888         }
2889 
abortLastDuration(BatteryStatsImpl stats)2890         public void abortLastDuration(BatteryStatsImpl stats) {
2891             abortLastDuration(stats, mClock.elapsedRealtime());
2892         }
2893 
abortLastDuration(BatteryStatsImpl stats, long elapsedRealtimeMs)2894         public void abortLastDuration(BatteryStatsImpl stats, long elapsedRealtimeMs) {
2895             final long nowUs = elapsedRealtimeMs * 1000;
2896             recomputeLastDuration(nowUs, true);
2897         }
2898 
2899         @Override
computeCurrentCountLocked()2900         protected int computeCurrentCountLocked() {
2901             return mCount;
2902         }
2903 
2904         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)2905         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
2906             final long overage = computeOverage(elapsedRealtimeUs);
2907             if (overage > 0) {
2908                 return mTotalTimeUs = overage;
2909             }
2910             return mTotalTimeUs;
2911         }
2912 
2913         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2914         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2915             recomputeLastDuration(elapsedRealtimeUs, true);
2916             boolean stillActive = mLastAddedTimeUs == elapsedRealtimeUs;
2917             super.reset(!stillActive && detachIfReset, elapsedRealtimeUs);
2918             return !stillActive;
2919         }
2920     }
2921 
2922 
2923     /**
2924      * A StopwatchTimer that also tracks the total and max individual
2925      * time spent active according to the given timebase.  Whereas
2926      * StopwatchTimer apportions the time amongst all in the pool,
2927      * the total and max durations are not apportioned.
2928      */
2929     public static class DurationTimer extends StopwatchTimer {
2930         /**
2931          * The time (in ms) that the timer was last acquired or the time base
2932          * last (re-)started. Increasing the nesting depth does not reset this time.
2933          *
2934          * -1 if the timer is currently not running or the time base is not running.
2935          *
2936          * If written to a parcel, the start time is reset, as is mNesting in the base class
2937          * StopwatchTimer.
2938          */
2939         long mStartTimeMs = -1;
2940 
2941         /**
2942          * The longest time period (in ms) that the timer has been active. Not pooled.
2943          */
2944         long mMaxDurationMs;
2945 
2946         /**
2947          * The time (in ms) that that the timer has been active since most recent
2948          * stopRunningLocked() or reset(). Not pooled.
2949          */
2950         long mCurrentDurationMs;
2951 
2952         /**
2953          * The total time (in ms) that that the timer has been active since most recent reset()
2954          * prior to the current startRunningLocked. This is the sum of all past currentDurations
2955          * (but not including the present currentDuration) since reset. Not pooled.
2956          */
2957         long mTotalDurationMs;
2958 
DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2959         public DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2960                 TimeBase timeBase, Parcel in) {
2961             super(clock, uid, type, timerPool, timeBase, in);
2962             mMaxDurationMs = in.readLong();
2963             mTotalDurationMs = in.readLong();
2964             mCurrentDurationMs = in.readLong();
2965         }
2966 
DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2967         public DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2968                 TimeBase timeBase) {
2969             super(clock, uid, type, timerPool, timeBase);
2970         }
2971 
2972         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2973         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2974             super.writeToParcel(out, elapsedRealtimeUs);
2975             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2976             out.writeLong(mTotalDurationMs);
2977             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
2978         }
2979 
2980         /**
2981          * Write the summary to the parcel.
2982          *
2983          * Since the time base is probably meaningless after we come back, reading
2984          * from this will have the effect of stopping the timer. So here all we write
2985          * is the max and total durations.
2986          */
2987         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2988         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2989             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2990             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2991             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
2992         }
2993 
2994         /**
2995          * Read the summary parcel.
2996          *
2997          * Has the side effect of stopping the timer.
2998          */
2999         @Override
readSummaryFromParcelLocked(Parcel in)3000         public void readSummaryFromParcelLocked(Parcel in) {
3001             super.readSummaryFromParcelLocked(in);
3002             mMaxDurationMs = in.readLong();
3003             mTotalDurationMs = in.readLong();
3004             mStartTimeMs = -1;
3005             mCurrentDurationMs = 0;
3006         }
3007 
3008         /**
3009          * The TimeBase time started (again).
3010          *
3011          * If the timer is also running, store the start time.
3012          */
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3013         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3014             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3015             if (mNesting > 0) {
3016                 mStartTimeMs = baseRealtimeUs / 1000;
3017             }
3018         }
3019 
3020         /**
3021          * The TimeBase stopped running.
3022          *
3023          * If the timer is running, add the duration into mCurrentDurationMs.
3024          */
3025         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3026         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3027             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3028             if (mNesting > 0) {
3029                 // baseRealtimeUs has already been converted to the timebase's realtime.
3030                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
3031             }
3032             mStartTimeMs = -1;
3033         }
3034 
3035         @Override
logState(Printer pw, String prefix)3036         public void logState(Printer pw, String prefix) {
3037             super.logState(pw, prefix);
3038         }
3039 
3040         @Override
startRunningLocked(long elapsedRealtimeMs)3041         public void startRunningLocked(long elapsedRealtimeMs) {
3042             super.startRunningLocked(elapsedRealtimeMs);
3043             if (mNesting == 1 && mTimeBase.isRunning()) {
3044                 // Just started
3045                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
3046             }
3047         }
3048 
3049         /**
3050          * Decrements the mNesting ref-count on this timer.
3051          *
3052          * If it actually stopped (mNesting went to 0), then possibly update
3053          * mMaxDuration if the current duration was the longest ever.
3054          */
3055         @Override
stopRunningLocked(long elapsedRealtimeMs)3056         public void stopRunningLocked(long elapsedRealtimeMs) {
3057             if (mNesting == 1) {
3058                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
3059                 mTotalDurationMs += durationMs;
3060                 if (durationMs > mMaxDurationMs) {
3061                     mMaxDurationMs = durationMs;
3062                 }
3063                 mStartTimeMs = -1;
3064                 mCurrentDurationMs = 0;
3065             }
3066             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
3067             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
3068             super.stopRunningLocked(elapsedRealtimeMs);
3069         }
3070 
3071         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3072         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3073             boolean result = super.reset(detachIfReset, elapsedRealtimeUs);
3074             mMaxDurationMs = 0;
3075             mTotalDurationMs = 0;
3076             mCurrentDurationMs = 0;
3077             if (mNesting > 0) {
3078                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeUs) / 1000;
3079             } else {
3080                 mStartTimeMs = -1;
3081             }
3082             return result;
3083         }
3084 
3085         /**
3086          * Returns the max duration that this timer has ever seen.
3087          *
3088          * Note that this time is NOT split between the timers in the timer group that
3089          * this timer is attached to.  It is the TOTAL time.
3090          */
3091         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)3092         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
3093             if (mNesting > 0) {
3094                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
3095                 if (durationMs > mMaxDurationMs) {
3096                     return durationMs;
3097                 }
3098             }
3099             return mMaxDurationMs;
3100         }
3101 
3102         /**
3103          * Returns the time since the timer was started.
3104          * Returns 0 if the timer is not currently running.
3105          *
3106          * Note that this time is NOT split between the timers in the timer group that
3107          * this timer is attached to.  It is the TOTAL time.
3108          *
3109          * Note that if running timer is parceled and unparceled, this method will return
3110          * current duration value at the time of parceling even though timer may not be
3111          * currently running.
3112          */
3113         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)3114         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
3115             long durationMs = mCurrentDurationMs;
3116             if (mNesting > 0 && mTimeBase.isRunning()) {
3117                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
3118                         - mStartTimeMs;
3119             }
3120             return durationMs;
3121         }
3122 
3123         /**
3124          * Returns the total cumulative duration that this timer has been on since reset().
3125          * If mTimerPool == null, this should be the same
3126          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
3127          *
3128          * Note that this time is NOT split between the timers in the timer group that
3129          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
3130          * the result will not be equivalent to getTotalTimeLocked.
3131          */
3132         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)3133         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
3134             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
3135         }
3136     }
3137 
3138     /**
3139      * State for keeping track of timing information.
3140      */
3141     public static class StopwatchTimer extends Timer {
3142         final Uid mUid;
3143         final ArrayList<StopwatchTimer> mTimerPool;
3144 
3145         int mNesting;
3146 
3147         /**
3148          * The last time at which we updated the timer.  If mNesting is > 0,
3149          * subtract this from the current battery time to find the amount of
3150          * time we have been running since we last computed an update.
3151          */
3152         long mUpdateTimeUs;
3153 
3154         /**
3155          * The total time at which the timer was acquired, to determine if it
3156          * was actually held for an interesting duration. If time base was not running when timer
3157          * was acquired, will be -1.
3158          */
3159         long mAcquireTimeUs = -1;
3160 
3161         long mTimeoutUs;
3162 
3163         /**
3164          * For partial wake locks, keep track of whether we are in the list
3165          * to consume CPU cycles.
3166          */
3167         @VisibleForTesting
3168         public boolean mInList;
3169 
StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)3170         public StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3171                 TimeBase timeBase, Parcel in) {
3172             super(clock, type, timeBase, in);
3173             mUid = uid;
3174             mTimerPool = timerPool;
3175             mUpdateTimeUs = in.readLong();
3176         }
3177 
StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)3178         public StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3179                 TimeBase timeBase) {
3180             super(clock, type, timeBase);
3181             mUid = uid;
3182             mTimerPool = timerPool;
3183         }
3184 
setTimeout(long timeoutUs)3185         public void setTimeout(long timeoutUs) {
3186             mTimeoutUs = timeoutUs;
3187         }
3188 
writeToParcel(Parcel out, long elapsedRealtimeUs)3189         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3190             super.writeToParcel(out, elapsedRealtimeUs);
3191             out.writeLong(mUpdateTimeUs);
3192         }
3193 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3194         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3195             if (mNesting > 0) {
3196                 if (DEBUG && mType < 0) {
3197                     Log.v(TAG, "old mUpdateTime=" + mUpdateTimeUs);
3198                 }
3199                 super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3200                 mUpdateTimeUs = baseRealtimeUs;
3201                 if (DEBUG && mType < 0) {
3202                     Log.v(TAG, "new mUpdateTime=" + mUpdateTimeUs);
3203                 }
3204             }
3205         }
3206 
logState(Printer pw, String prefix)3207         public void logState(Printer pw, String prefix) {
3208             super.logState(pw, prefix);
3209             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTimeUs
3210                     + " mAcquireTime=" + mAcquireTimeUs);
3211         }
3212 
startRunningLocked(long elapsedRealtimeMs)3213         public void startRunningLocked(long elapsedRealtimeMs) {
3214             if (mNesting++ == 0) {
3215                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3216                 mUpdateTimeUs = batteryRealtimeUs;
3217                 if (mTimerPool != null) {
3218                     // Accumulate time to all currently active timers before adding
3219                     // this new one to the pool.
3220                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
3221                     // Add this timer to the active pool
3222                     mTimerPool.add(this);
3223                 }
3224                 if (mTimeBase.isRunning()) {
3225                     // Increment the count
3226                     mCount++;
3227                     mAcquireTimeUs = mTotalTimeUs;
3228                 } else {
3229                     mAcquireTimeUs = -1;
3230                 }
3231                 if (DEBUG && mType < 0) {
3232                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTimeUs
3233                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
3234                             + " mAcquireTime=" + mAcquireTimeUs);
3235                 }
3236             }
3237         }
3238 
isRunningLocked()3239         public boolean isRunningLocked() {
3240             return mNesting > 0;
3241         }
3242 
stopRunningLocked(long elapsedRealtimeMs)3243         public void stopRunningLocked(long elapsedRealtimeMs) {
3244             // Ignore attempt to stop a timer that isn't running
3245             if (mNesting == 0) {
3246                 return;
3247             }
3248             if (--mNesting == 0) {
3249                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3250                 if (mTimerPool != null) {
3251                     // Accumulate time to all active counters, scaled by the total
3252                     // active in the pool, before taking this one out of the pool.
3253                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
3254                     // Remove this timer from the active pool
3255                     mTimerPool.remove(this);
3256                 } else {
3257                     mNesting = 1;
3258                     mTotalTimeUs = computeRunTimeLocked(batteryRealtimeUs,
3259                             elapsedRealtimeMs * 1000);
3260                     mNesting = 0;
3261                 }
3262 
3263                 if (DEBUG && mType < 0) {
3264                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTimeUs
3265                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
3266                             + " mAcquireTime=" + mAcquireTimeUs);
3267                 }
3268 
3269                 if (mAcquireTimeUs >= 0 && mTotalTimeUs == mAcquireTimeUs) {
3270                     // If there was no change in the time, then discard this
3271                     // count.  A somewhat cheezy strategy, but hey.
3272                     mCount--;
3273                 }
3274             }
3275         }
3276 
stopAllRunningLocked(long elapsedRealtimeMs)3277         public void stopAllRunningLocked(long elapsedRealtimeMs) {
3278             if (mNesting > 0) {
3279                 mNesting = 1;
3280                 stopRunningLocked(elapsedRealtimeMs);
3281             }
3282         }
3283 
3284         // Update the total time for all other running Timers with the same type as this Timer
3285         // due to a change in timer count
refreshTimersLocked(long batteryRealtimeUs, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)3286         private static long refreshTimersLocked(long batteryRealtimeUs,
3287                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
3288             long selfTimeUs = 0;
3289             final int N = pool.size();
3290             for (int i=N-1; i>= 0; i--) {
3291                 final StopwatchTimer t = pool.get(i);
3292                 long heldTimeUs = batteryRealtimeUs - t.mUpdateTimeUs;
3293                 if (heldTimeUs > 0) {
3294                     final long myTimeUs = heldTimeUs / N;
3295                     if (t == self) {
3296                         selfTimeUs = myTimeUs;
3297                     }
3298                     t.mTotalTimeUs += myTimeUs;
3299                 }
3300                 t.mUpdateTimeUs = batteryRealtimeUs;
3301             }
3302             return selfTimeUs;
3303         }
3304 
3305         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)3306         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
3307             if (mTimeoutUs > 0 && curBatteryRealtimeUs > mUpdateTimeUs + mTimeoutUs) {
3308                 curBatteryRealtimeUs = mUpdateTimeUs + mTimeoutUs;
3309             }
3310             return mTotalTimeUs + (mNesting > 0
3311                     ? (curBatteryRealtimeUs - mUpdateTimeUs)
3312                             / (mTimerPool != null ? mTimerPool.size() : 1)
3313                     : 0);
3314         }
3315 
3316         @Override
computeCurrentCountLocked()3317         protected int computeCurrentCountLocked() {
3318             return mCount;
3319         }
3320 
3321         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3322         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3323             boolean canDetach = mNesting <= 0;
3324             super.reset(canDetach && detachIfReset, elapsedRealtimeUs);
3325             if (mNesting > 0) {
3326                 mUpdateTimeUs = mTimeBase.getRealtime(elapsedRealtimeUs);
3327             }
3328             // To ensure mCount isn't decreased to -1 if timer is stopped later.
3329             mAcquireTimeUs = -1;
3330             return canDetach;
3331         }
3332 
3333         @Override
3334         @UnsupportedAppUsage
detach()3335         public void detach() {
3336             super.detach();
3337             if (mTimerPool != null) {
3338                 mTimerPool.remove(this);
3339             }
3340         }
3341 
3342         @Override
readSummaryFromParcelLocked(Parcel in)3343         public void readSummaryFromParcelLocked(Parcel in) {
3344             super.readSummaryFromParcelLocked(in);
3345             mNesting = 0;
3346         }
3347 
3348         /**
3349          * Set the mark so that we can query later for the total time the timer has
3350          * accumulated since this point. The timer can be running or not.
3351          *
3352          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
3353          */
setMark(long elapsedRealtimeMs)3354         public void setMark(long elapsedRealtimeMs) {
3355             final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3356             if (mNesting > 0) {
3357                 // We are running.
3358                 if (mTimerPool != null) {
3359                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, this);
3360                 } else {
3361                     mTotalTimeUs += batteryRealtimeUs - mUpdateTimeUs;
3362                     mUpdateTimeUs = batteryRealtimeUs;
3363                 }
3364             }
3365             mTimeBeforeMarkUs = mTotalTimeUs;
3366         }
3367     }
3368 
3369     /**
3370      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
3371      * TimeBase is effectively a subset of the other.
3372      */
3373     public static class DualTimer extends DurationTimer {
3374         // This class both is a DurationTimer and also holds a second DurationTimer.
3375         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
3376         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
3377         // STATS_SINCE_CHARGED).
3378         // mSubTimer typically tracks only part of the total time, such as background time, as
3379         // determined by a subTimeBase. It is NOT pooled.
3380         private final DurationTimer mSubTimer;
3381 
3382         /**
3383          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
3384          * The main timer (this) is based on the given timeBase and timerPool.
3385          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
3386          * the main timer is.
3387          */
DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)3388         public DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3389                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
3390             super(clock, uid, type, timerPool, timeBase, in);
3391             mSubTimer = new DurationTimer(clock, uid, type, null, subTimeBase, in);
3392         }
3393 
3394         /**
3395          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
3396          * The main timer (this) is based on the given timeBase and timerPool.
3397          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
3398          * the main timer is.
3399          */
DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)3400         public DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3401                 TimeBase timeBase, TimeBase subTimeBase) {
3402             super(clock, uid, type, timerPool, timeBase);
3403             mSubTimer = new DurationTimer(clock, uid, type, null, subTimeBase);
3404         }
3405 
3406         /** Get the secondary timer. */
3407         @Override
getSubTimer()3408         public DurationTimer getSubTimer() {
3409             return mSubTimer;
3410         }
3411 
3412         @Override
startRunningLocked(long elapsedRealtimeMs)3413         public void startRunningLocked(long elapsedRealtimeMs) {
3414             super.startRunningLocked(elapsedRealtimeMs);
3415             mSubTimer.startRunningLocked(elapsedRealtimeMs);
3416         }
3417 
3418         @Override
stopRunningLocked(long elapsedRealtimeMs)3419         public void stopRunningLocked(long elapsedRealtimeMs) {
3420             super.stopRunningLocked(elapsedRealtimeMs);
3421             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
3422         }
3423 
3424         @Override
stopAllRunningLocked(long elapsedRealtimeMs)3425         public void stopAllRunningLocked(long elapsedRealtimeMs) {
3426             super.stopAllRunningLocked(elapsedRealtimeMs);
3427             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
3428         }
3429 
3430         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3431         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3432             boolean active = false;
3433             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
3434             active |= !mSubTimer.reset(false, elapsedRealtimeUs);
3435             active |= !super.reset(detachIfReset, elapsedRealtimeUs);
3436             return !active;
3437         }
3438 
3439         @Override
detach()3440         public void detach() {
3441             mSubTimer.detach();
3442             super.detach();
3443         }
3444 
3445         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3446         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3447             super.writeToParcel(out, elapsedRealtimeUs);
3448             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
3449         }
3450 
3451         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)3452         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
3453             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3454             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3455         }
3456 
3457         @Override
readSummaryFromParcelLocked(Parcel in)3458         public void readSummaryFromParcelLocked(Parcel in) {
3459             super.readSummaryFromParcelLocked(in);
3460             mSubTimer.readSummaryFromParcelLocked(in);
3461         }
3462     }
3463 
3464 
3465     public abstract class OverflowArrayMap<T> {
3466         private static final String OVERFLOW_NAME = "*overflow*";
3467 
3468         final int mUid;
3469         final ArrayMap<String, T> mMap = new ArrayMap<>();
3470         T mCurOverflow;
3471         ArrayMap<String, MutableInt> mActiveOverflow;
3472         long mLastOverflowTimeMs;
3473         long mLastOverflowFinishTimeMs;
3474         long mLastClearTimeMs;
3475         long mLastCleanupTimeMs;
3476 
OverflowArrayMap(int uid)3477         public OverflowArrayMap(int uid) {
3478             mUid = uid;
3479         }
3480 
getMap()3481         public ArrayMap<String, T> getMap() {
3482             return mMap;
3483         }
3484 
clear()3485         public void clear() {
3486             mLastClearTimeMs = SystemClock.elapsedRealtime();
3487             mMap.clear();
3488             mCurOverflow = null;
3489             mActiveOverflow = null;
3490         }
3491 
add(String name, T obj)3492         public void add(String name, T obj) {
3493             if (name == null) {
3494                 name = "";
3495             }
3496             mMap.put(name, obj);
3497             if (OVERFLOW_NAME.equals(name)) {
3498                 mCurOverflow = obj;
3499             }
3500         }
3501 
cleanup(long elapsedRealtimeMs)3502         public void cleanup(long elapsedRealtimeMs) {
3503             mLastCleanupTimeMs = elapsedRealtimeMs;
3504             if (mActiveOverflow != null) {
3505                 if (mActiveOverflow.size() == 0) {
3506                     mActiveOverflow = null;
3507                 }
3508             }
3509             if (mActiveOverflow == null) {
3510                 // There is no currently active overflow, so we should no longer have
3511                 // an overflow entry.
3512                 if (mMap.containsKey(OVERFLOW_NAME)) {
3513                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
3514                             + mMap.get(OVERFLOW_NAME));
3515                     mMap.remove(OVERFLOW_NAME);
3516                 }
3517                 mCurOverflow = null;
3518             } else {
3519                 // There is currently active overflow, so we should still have an overflow entry.
3520                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
3521                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
3522                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
3523                 }
3524             }
3525         }
3526 
startObject(String name, long elapsedRealtimeMs)3527         public T startObject(String name, long elapsedRealtimeMs) {
3528             if (name == null) {
3529                 name = "";
3530             }
3531             T obj = mMap.get(name);
3532             if (obj != null) {
3533                 return obj;
3534             }
3535 
3536             // No object exists for the given name, but do we currently have it
3537             // running as part of the overflow?
3538             if (mActiveOverflow != null) {
3539                 MutableInt over = mActiveOverflow.get(name);
3540                 if (over != null) {
3541                     // We are already actively counting this name in the overflow object.
3542                     obj = mCurOverflow;
3543                     if (obj == null) {
3544                         // Shouldn't be here, but we'll try to recover.
3545                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
3546                         obj = mCurOverflow = instantiateObject();
3547                         mMap.put(OVERFLOW_NAME, obj);
3548                     }
3549                     over.value++;
3550                     return obj;
3551                 }
3552             }
3553 
3554             // No object exists for given name nor in the overflow; we need to make
3555             // a new one.
3556             final int N = mMap.size();
3557             if (N >= MAX_WAKELOCKS_PER_UID) {
3558                 // Went over the limit on number of objects to track; this one goes
3559                 // in to the overflow.
3560                 obj = mCurOverflow;
3561                 if (obj == null) {
3562                     // Need to start overflow now...
3563                     obj = mCurOverflow = instantiateObject();
3564                     mMap.put(OVERFLOW_NAME, obj);
3565                 }
3566                 if (mActiveOverflow == null) {
3567                     mActiveOverflow = new ArrayMap<>();
3568                 }
3569                 mActiveOverflow.put(name, new MutableInt(1));
3570                 mLastOverflowTimeMs = elapsedRealtimeMs;
3571                 return obj;
3572             }
3573 
3574             // Normal case where we just need to make a new object.
3575             obj = instantiateObject();
3576             mMap.put(name, obj);
3577             return obj;
3578         }
3579 
stopObject(String name, long elapsedRealtimeMs)3580         public T stopObject(String name, long elapsedRealtimeMs) {
3581             if (name == null) {
3582                 name = "";
3583             }
3584             T obj = mMap.get(name);
3585             if (obj != null) {
3586                 return obj;
3587             }
3588 
3589             // No object exists for the given name, but do we currently have it
3590             // running as part of the overflow?
3591             if (mActiveOverflow != null) {
3592                 MutableInt over = mActiveOverflow.get(name);
3593                 if (over != null) {
3594                     // We are already actively counting this name in the overflow object.
3595                     obj = mCurOverflow;
3596                     if (obj != null) {
3597                         over.value--;
3598                         if (over.value <= 0) {
3599                             mActiveOverflow.remove(name);
3600                             mLastOverflowFinishTimeMs = elapsedRealtimeMs;
3601                         }
3602                         return obj;
3603                     }
3604                 }
3605             }
3606 
3607             // Huh, they are stopping an active operation but we can't find one!
3608             // That's not good.
3609             StringBuilder sb = new StringBuilder();
3610             sb.append("Unable to find object for ");
3611             sb.append(name);
3612             sb.append(" in uid ");
3613             sb.append(mUid);
3614             sb.append(" mapsize=");
3615             sb.append(mMap.size());
3616             sb.append(" activeoverflow=");
3617             sb.append(mActiveOverflow);
3618             sb.append(" curoverflow=");
3619             sb.append(mCurOverflow);
3620             long now = elapsedRealtimeMs;
3621             if (mLastOverflowTimeMs != 0) {
3622                 sb.append(" lastOverflowTime=");
3623                 TimeUtils.formatDuration(mLastOverflowTimeMs - now, sb);
3624             }
3625             if (mLastOverflowFinishTimeMs != 0) {
3626                 sb.append(" lastOverflowFinishTime=");
3627                 TimeUtils.formatDuration(mLastOverflowFinishTimeMs - now, sb);
3628             }
3629             if (mLastClearTimeMs != 0) {
3630                 sb.append(" lastClearTime=");
3631                 TimeUtils.formatDuration(mLastClearTimeMs - now, sb);
3632             }
3633             if (mLastCleanupTimeMs != 0) {
3634                 sb.append(" lastCleanupTime=");
3635                 TimeUtils.formatDuration(mLastCleanupTimeMs - now, sb);
3636             }
3637             Slog.wtf(TAG, sb.toString());
3638             return null;
3639         }
3640 
instantiateObject()3641         public abstract T instantiateObject();
3642     }
3643 
3644     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
3645             implements Parcelable {
3646         private final Clock mClock;
3647         private final TimeBase mTimeBase;
3648         private int mNumTxStates;
3649         private int mProcessState;
3650         private TimeMultiStateCounter mIdleTimeMillis;
3651         private final LongSamplingCounter mScanTimeMillis;
3652         private final LongSamplingCounter mSleepTimeMillis;
3653         private TimeMultiStateCounter mRxTimeMillis;
3654         private TimeMultiStateCounter[] mTxTimeMillis;
3655         private final LongSamplingCounter mPowerDrainMaMs;
3656         private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs;
3657 
ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates)3658         public ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates) {
3659             mClock = clock;
3660             mTimeBase = timeBase;
3661             mNumTxStates = numTxStates;
3662             mScanTimeMillis = new LongSamplingCounter(timeBase);
3663             mSleepTimeMillis = new LongSamplingCounter(timeBase);
3664             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
3665             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase);
3666         }
3667 
ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates, Parcel in)3668         public ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates,
3669                 Parcel in) {
3670             mClock = clock;
3671             mTimeBase = timeBase;
3672             mNumTxStates = numTxStates;
3673             mIdleTimeMillis = readTimeMultiStateCounter(in, timeBase);
3674             mScanTimeMillis = new LongSamplingCounter(timeBase, in);
3675             mSleepTimeMillis = new LongSamplingCounter(timeBase, in);
3676             mRxTimeMillis = readTimeMultiStateCounter(in, timeBase);
3677             mTxTimeMillis = readTimeMultiStateCounters(in, timeBase, numTxStates);
3678 
3679             mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
3680             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase, in);
3681         }
3682 
readSummaryFromParcel(Parcel in)3683         public void readSummaryFromParcel(Parcel in) {
3684             mIdleTimeMillis = readTimeMultiStateCounter(in, mTimeBase);
3685             mScanTimeMillis.readSummaryFromParcelLocked(in);
3686             mSleepTimeMillis.readSummaryFromParcelLocked(in);
3687             mRxTimeMillis = readTimeMultiStateCounter(in, mTimeBase);
3688             mTxTimeMillis = readTimeMultiStateCounters(in, mTimeBase, mNumTxStates);
3689 
3690             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
3691             mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in);
3692         }
3693 
3694         @Override
describeContents()3695         public int describeContents() {
3696             return 0;
3697         }
3698 
writeSummaryToParcel(Parcel dest)3699         public void writeSummaryToParcel(Parcel dest) {
3700             writeTimeMultiStateCounter(dest, mIdleTimeMillis);
3701             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
3702             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
3703             writeTimeMultiStateCounter(dest, mRxTimeMillis);
3704             writeTimeMultiStateCounters(dest, mTxTimeMillis);
3705             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
3706             mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest);
3707         }
3708 
3709         @Override
writeToParcel(Parcel dest, int flags)3710         public void writeToParcel(Parcel dest, int flags) {
3711             writeTimeMultiStateCounter(dest, mIdleTimeMillis);
3712             mScanTimeMillis.writeToParcel(dest);
3713             mSleepTimeMillis.writeToParcel(dest);
3714             writeTimeMultiStateCounter(dest, mRxTimeMillis);
3715             writeTimeMultiStateCounters(dest, mTxTimeMillis);
3716             mPowerDrainMaMs.writeToParcel(dest);
3717             mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
3718         }
3719 
readTimeMultiStateCounter(Parcel in, TimeBase timeBase)3720         private TimeMultiStateCounter readTimeMultiStateCounter(Parcel in, TimeBase timeBase) {
3721             if (in.readBoolean()) {
3722                 return TimeMultiStateCounter.readFromParcel(in, timeBase,
3723                         BatteryConsumer.PROCESS_STATE_COUNT, mClock.elapsedRealtime());
3724             }
3725             return null;
3726         }
3727 
writeTimeMultiStateCounter(Parcel dest, TimeMultiStateCounter counter)3728         private void writeTimeMultiStateCounter(Parcel dest, TimeMultiStateCounter counter) {
3729             if (counter != null) {
3730                 dest.writeBoolean(true);
3731                 counter.writeToParcel(dest);
3732             } else {
3733                 dest.writeBoolean(false);
3734             }
3735         }
3736 
readTimeMultiStateCounters(Parcel in, TimeBase timeBase, int expectedNumCounters)3737         private TimeMultiStateCounter[] readTimeMultiStateCounters(Parcel in, TimeBase timeBase,
3738                 int expectedNumCounters) {
3739             if (in.readBoolean()) {
3740                 final int numCounters = in.readInt();
3741                 boolean valid = (numCounters == expectedNumCounters);
3742                 // Need to read counters out of the Parcel, even if all or some of them are
3743                 // invalid.
3744                 TimeMultiStateCounter[] counters = new TimeMultiStateCounter[numCounters];
3745                 for (int i = 0; i < numCounters; i++) {
3746                     final TimeMultiStateCounter counter = TimeMultiStateCounter.readFromParcel(in,
3747                             timeBase, BatteryConsumer.PROCESS_STATE_COUNT,
3748                             mClock.elapsedRealtime());
3749                     if (counter != null) {
3750                         counters[i] = counter;
3751                     } else {
3752                         valid = false;
3753                     }
3754                 }
3755                 if (valid) {
3756                     return counters;
3757                 }
3758             }
3759             return null;
3760         }
3761 
writeTimeMultiStateCounters(Parcel dest, TimeMultiStateCounter[] counters)3762         private void writeTimeMultiStateCounters(Parcel dest, TimeMultiStateCounter[] counters) {
3763             if (counters != null) {
3764                 dest.writeBoolean(true);
3765                 dest.writeInt(counters.length);
3766                 for (TimeMultiStateCounter counter : counters) {
3767                     counter.writeToParcel(dest);
3768                 }
3769             } else {
3770                 dest.writeBoolean(false);
3771             }
3772         }
3773 
reset(boolean detachIfReset, long elapsedRealtimeUs)3774         public void reset(boolean detachIfReset, long elapsedRealtimeUs) {
3775             resetIfNotNull(mIdleTimeMillis, detachIfReset, elapsedRealtimeUs);
3776             mScanTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3777             mSleepTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3778             resetIfNotNull(mRxTimeMillis, detachIfReset, elapsedRealtimeUs);
3779             resetIfNotNull(mTxTimeMillis, detachIfReset, elapsedRealtimeUs);
3780             mPowerDrainMaMs.reset(detachIfReset, elapsedRealtimeUs);
3781             mMonitoredRailChargeConsumedMaMs.reset(detachIfReset, elapsedRealtimeUs);
3782         }
3783 
detach()3784         public void detach() {
3785             detachIfNotNull(mIdleTimeMillis);
3786             mScanTimeMillis.detach();
3787             mSleepTimeMillis.detach();
3788             detachIfNotNull(mRxTimeMillis);
3789             detachIfNotNull(mTxTimeMillis);
3790             mPowerDrainMaMs.detach();
3791             mMonitoredRailChargeConsumedMaMs.detach();
3792         }
3793 
3794         /**
3795          * @return a LongSamplingCounter, measuring time spent in the idle state in
3796          * milliseconds.
3797          */
3798         @Override
getIdleTimeCounter()3799         public LongCounter getIdleTimeCounter() {
3800             if (mIdleTimeMillis == null) {
3801                 return ZERO_LONG_COUNTER;
3802             }
3803             return mIdleTimeMillis;
3804         }
3805 
getOrCreateIdleTimeCounter()3806         private TimeMultiStateCounter getOrCreateIdleTimeCounter() {
3807             if (mIdleTimeMillis == null) {
3808                 mIdleTimeMillis = createTimeMultiStateCounter();
3809             }
3810             return mIdleTimeMillis;
3811         }
3812 
3813         /**
3814          * @return a LongSamplingCounter, measuring time spent in the scan state in
3815          * milliseconds.
3816          */
3817         @Override
getScanTimeCounter()3818         public LongSamplingCounter getScanTimeCounter() {
3819             return mScanTimeMillis;
3820         }
3821 
3822         /**
3823          * @return a LongSamplingCounter, measuring time spent in the sleep state in
3824          * milliseconds.
3825          */
3826         @Override
getSleepTimeCounter()3827         public LongSamplingCounter getSleepTimeCounter() {
3828             return mSleepTimeMillis;
3829         }
3830 
3831         /**
3832          * @return a LongSamplingCounter, measuring time spent in the receive state in
3833          * milliseconds.
3834          */
3835         @Override
getRxTimeCounter()3836         public LongCounter getRxTimeCounter() {
3837             if (mRxTimeMillis == null) {
3838                 return ZERO_LONG_COUNTER;
3839             }
3840             return mRxTimeMillis;
3841         }
3842 
getOrCreateRxTimeCounter()3843         private TimeMultiStateCounter getOrCreateRxTimeCounter() {
3844             if (mRxTimeMillis == null) {
3845                 mRxTimeMillis = createTimeMultiStateCounter();
3846             }
3847             return mRxTimeMillis;
3848         }
3849 
3850         /**
3851          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
3852          * milliseconds.
3853          */
3854         @Override
getTxTimeCounters()3855         public LongCounter[] getTxTimeCounters() {
3856             if (mTxTimeMillis == null) {
3857                 return ZERO_LONG_COUNTER_ARRAY;
3858             }
3859             return mTxTimeMillis;
3860         }
3861 
getOrCreateTxTimeCounters()3862         private TimeMultiStateCounter[] getOrCreateTxTimeCounters() {
3863             if (mTxTimeMillis == null) {
3864                 mTxTimeMillis = new TimeMultiStateCounter[mNumTxStates];
3865                 for (int i = 0; i < mNumTxStates; i++) {
3866                     mTxTimeMillis[i] = createTimeMultiStateCounter();
3867                 }
3868             }
3869             return mTxTimeMillis;
3870         }
3871 
createTimeMultiStateCounter()3872         private TimeMultiStateCounter createTimeMultiStateCounter() {
3873             final long timestampMs = mClock.elapsedRealtime();
3874             TimeMultiStateCounter counter = new TimeMultiStateCounter(mTimeBase,
3875                     BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
3876             counter.setState(mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
3877                     timestampMs);
3878             counter.update(0, timestampMs);
3879             return counter;
3880         }
3881 
3882         /**
3883          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
3884          */
3885         @Override
getPowerCounter()3886         public LongSamplingCounter getPowerCounter() {
3887             return mPowerDrainMaMs;
3888         }
3889 
3890         /**
3891          * @return a LongSamplingCounter, measuring actual monitored rail energy consumed
3892          * milli-ampere milli-seconds (mAmS).
3893          */
3894         @Override
getMonitoredRailChargeConsumedMaMs()3895         public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() {
3896             return mMonitoredRailChargeConsumedMaMs;
3897         }
3898 
setState(int processState, long elapsedTimeMs)3899         private void setState(int processState, long elapsedTimeMs) {
3900             mProcessState = processState;
3901             if (mIdleTimeMillis != null) {
3902                 mIdleTimeMillis.setState(processState, elapsedTimeMs);
3903             }
3904             if (mRxTimeMillis != null) {
3905                 mRxTimeMillis.setState(processState, elapsedTimeMs);
3906             }
3907             if (mTxTimeMillis != null) {
3908                 for (int i = 0; i < mTxTimeMillis.length; i++) {
3909                     mTxTimeMillis[i].setState(processState, elapsedTimeMs);
3910                 }
3911             }
3912         }
3913     }
3914 
3915     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)3916     public SamplingTimer getRpmTimerLocked(String name) {
3917         SamplingTimer rpmt = mRpmStats.get(name);
3918         if (rpmt == null) {
3919             rpmt = new SamplingTimer(mClock, mOnBatteryTimeBase);
3920             mRpmStats.put(name, rpmt);
3921         }
3922         return rpmt;
3923     }
3924 
3925     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)3926     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
3927         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
3928         if (rpmt == null) {
3929             rpmt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
3930             mScreenOffRpmStats.put(name, rpmt);
3931         }
3932         return rpmt;
3933     }
3934 
3935     /*
3936      * Get the wakeup reason counter, and create a new one if one
3937      * doesn't already exist.
3938      */
getWakeupReasonTimerLocked(String name)3939     public SamplingTimer getWakeupReasonTimerLocked(String name) {
3940         SamplingTimer timer = mWakeupReasonStats.get(name);
3941         if (timer == null) {
3942             timer = new SamplingTimer(mClock, mOnBatteryTimeBase);
3943             mWakeupReasonStats.put(name, timer);
3944         }
3945         return timer;
3946     }
3947 
3948     /*
3949      * Get the KernelWakelockTimer associated with name, and create a new one if one
3950      * doesn't already exist.
3951      */
getKernelWakelockTimerLocked(String name)3952     public SamplingTimer getKernelWakelockTimerLocked(String name) {
3953         SamplingTimer kwlt = mKernelWakelockStats.get(name);
3954         if (kwlt == null) {
3955             kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
3956             mKernelWakelockStats.put(name, kwlt);
3957         }
3958         return kwlt;
3959     }
3960 
getKernelMemoryTimerLocked(long bucket)3961     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
3962         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
3963         if (kmt == null) {
3964             kmt = new SamplingTimer(mClock, mOnBatteryTimeBase);
3965             mKernelMemoryStats.put(bucket, kmt);
3966         }
3967         return kmt;
3968     }
3969 
3970     /**
3971      * Returns the index for the specified tag. If this is the first time the tag is encountered
3972      * while writing the current history buffer, the method returns
3973      * <code>(index | TAG_FIRST_OCCURRENCE_FLAG)</code>
3974      */
writeHistoryTag(HistoryTag tag)3975     private int writeHistoryTag(HistoryTag tag) {
3976         if (tag.string == null) {
3977             Slog.wtfStack(TAG, "writeHistoryTag called with null name");
3978         }
3979 
3980         final int stringLength = tag.string.length();
3981         if (stringLength > MAX_HISTORY_TAG_STRING_LENGTH) {
3982             Slog.e(TAG, "Long battery history tag: " + tag.string);
3983             tag.string = tag.string.substring(0, MAX_HISTORY_TAG_STRING_LENGTH);
3984         }
3985 
3986         Integer idxObj = mHistoryTagPool.get(tag);
3987         int idx;
3988         if (idxObj != null) {
3989             idx = idxObj;
3990             if ((idx & TAG_FIRST_OCCURRENCE_FLAG) != 0) {
3991                 mHistoryTagPool.put(tag, idx & ~TAG_FIRST_OCCURRENCE_FLAG);
3992             }
3993             return idx;
3994         } else if (mNextHistoryTagIdx < HISTORY_TAG_INDEX_LIMIT) {
3995             idx = mNextHistoryTagIdx;
3996             HistoryTag key = new HistoryTag();
3997             key.setTo(tag);
3998             tag.poolIdx = idx;
3999             mHistoryTagPool.put(key, idx);
4000             mNextHistoryTagIdx++;
4001 
4002             mNumHistoryTagChars += stringLength + 1;
4003             if (mHistoryTags != null) {
4004                 mHistoryTags.put(idx, key);
4005             }
4006             return idx | TAG_FIRST_OCCURRENCE_FLAG;
4007         } else {
4008             // Tag pool overflow: include the tag itself in the parcel
4009             return HISTORY_TAG_INDEX_LIMIT | TAG_FIRST_OCCURRENCE_FLAG;
4010         }
4011     }
4012 
4013     /*
4014         The history delta format uses flags to denote further data in subsequent ints in the parcel.
4015 
4016         There is always the first token, which may contain the delta time, or an indicator of
4017         the length of the time (int or long) following this token.
4018 
4019         First token: always present,
4020         31              23              15               7             0
4021         █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█
4022 
4023         T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
4024            follows containing the time, and 0x7ffff indicates a long immediately follows with the
4025            delta time.
4026         A: battery level changed and an int follows with battery data.
4027         B: state changed and an int follows with state change data.
4028         C: state2 has changed and an int follows with state2 change data.
4029         D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
4030         E: event data has changed and an event struct follows.
4031         F: battery charge in coulombs has changed and an int with the charge follows.
4032         G: state flag denoting that the mobile radio was active.
4033         H: state flag denoting that the wifi radio was active.
4034         I: state flag denoting that a wifi scan occurred.
4035         J: state flag denoting that a wifi full lock was held.
4036         K: state flag denoting that the gps was on.
4037         L: state flag denoting that a wakelock was held.
4038         M: state flag denoting that the cpu was running.
4039 
4040         Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
4041         with the time delta.
4042 
4043         Battery level int: if A in the first token is set,
4044         31              23              15               7             0
4045         █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█
4046 
4047         D: indicates that extra history details follow.
4048         V: the battery voltage.
4049         T: the battery temperature.
4050         L: the battery level (out of 100).
4051 
4052         State change int: if B in the first token is set,
4053         31              23              15               7             0
4054         █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
4055 
4056         A: wifi multicast was on.
4057         B: battery was plugged in.
4058         C: screen was on.
4059         D: phone was scanning for signal.
4060         E: audio was on.
4061         F: a sensor was active.
4062 
4063         State2 change int: if C in the first token is set,
4064         31              23              15               7             0
4065         █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
4066 
4067         A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
4068         B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
4069         C: a bluetooth scan was active.
4070         D: the camera was active.
4071         E: bluetooth was on.
4072         F: a phone call was active.
4073         G: the device was charging.
4074         H: 2 bits indicating the device-idle (doze) state: off, light, full
4075         I: the flashlight was on.
4076         J: wifi was on.
4077         K: wifi was running.
4078         L: video was playing.
4079         M: power save mode was on.
4080 
4081         Wakelock/wakereason struct: if D in the first token is set,
4082         TODO(adamlesinski): describe wakelock/wakereason struct.
4083 
4084         Event struct: if E in the first token is set,
4085         TODO(adamlesinski): describe the event struct.
4086 
4087         History step details struct: if D in the battery level int is set,
4088         TODO(adamlesinski): describe the history step details struct.
4089 
4090         Battery charge int: if F in the first token is set, an int representing the battery charge
4091         in coulombs follows.
4092      */
4093 
4094     // Part of initial delta int that specifies the time delta.
4095     static final int DELTA_TIME_MASK = 0x7ffff;
4096     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
4097     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
4098     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
4099     // Flag in delta int: a new battery level int follows.
4100     static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
4101     // Flag in delta int: a new full state and battery status int follows.
4102     static final int DELTA_STATE_FLAG                       = 0x00100000;
4103     // Flag in delta int: a new full state2 int follows.
4104     static final int DELTA_STATE2_FLAG                      = 0x00200000;
4105     // Flag in delta int: contains a wakelock or wakeReason tag.
4106     static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
4107     // Flag in delta int: contains an event description.
4108     static final int DELTA_EVENT_FLAG                       = 0x00800000;
4109     // Flag in delta int: contains the battery charge count in uAh.
4110     static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
4111     // These upper bits are the frequently changing state bits.
4112     static final int DELTA_STATE_MASK                       = 0xfe000000;
4113 
4114     // Flag in history tag index: indicates that this is the first occurrence of this tag,
4115     // therefore the tag value is written in the parcel
4116     static final int TAG_FIRST_OCCURRENCE_FLAG = 0x8000;
4117 
4118     // These are the pieces of battery state that are packed in to the upper bits of
4119     // the state int that have been packed in to the first delta int.  They must fit
4120     // in STATE_BATTERY_MASK.
4121     static final int STATE_BATTERY_MASK         = 0xff000000;
4122     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
4123     static final int STATE_BATTERY_STATUS_SHIFT = 29;
4124     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
4125     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
4126     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
4127     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
4128 
4129     // We use the low bit of the battery state int to indicate that we have full details
4130     // from a battery level change.
4131     static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
4132 
4133     @GuardedBy("this")
writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last)4134     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
4135         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
4136             dest.writeInt(DELTA_TIME_ABS);
4137             cur.writeToParcel(dest, 0);
4138             return;
4139         }
4140 
4141         final long deltaTime = cur.time - last.time;
4142         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
4143         final int lastStateInt = buildStateInt(last);
4144 
4145         int deltaTimeToken;
4146         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
4147             deltaTimeToken = DELTA_TIME_LONG;
4148         } else if (deltaTime >= DELTA_TIME_ABS) {
4149             deltaTimeToken = DELTA_TIME_INT;
4150         } else {
4151             deltaTimeToken = (int)deltaTime;
4152         }
4153         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
4154         final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
4155                 ? BATTERY_DELTA_LEVEL_FLAG : 0;
4156         final boolean computeStepDetails = includeStepDetails != 0
4157                 || mLastHistoryStepDetails == null;
4158         final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
4159         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
4160         if (batteryLevelIntChanged) {
4161             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
4162         }
4163         final int stateInt = buildStateInt(cur);
4164         final boolean stateIntChanged = stateInt != lastStateInt;
4165         if (stateIntChanged) {
4166             firstToken |= DELTA_STATE_FLAG;
4167         }
4168         final boolean state2IntChanged = cur.states2 != last.states2;
4169         if (state2IntChanged) {
4170             firstToken |= DELTA_STATE2_FLAG;
4171         }
4172         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
4173             firstToken |= DELTA_WAKELOCK_FLAG;
4174         }
4175         if (cur.eventCode != HistoryItem.EVENT_NONE) {
4176             firstToken |= DELTA_EVENT_FLAG;
4177         }
4178 
4179         final boolean batteryChargeChanged = cur.batteryChargeUah != last.batteryChargeUah;
4180         if (batteryChargeChanged) {
4181             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
4182         }
4183         dest.writeInt(firstToken);
4184         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
4185                 + " deltaTime=" + deltaTime);
4186 
4187         if (deltaTimeToken >= DELTA_TIME_INT) {
4188             if (deltaTimeToken == DELTA_TIME_INT) {
4189                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
4190                 dest.writeInt((int)deltaTime);
4191             } else {
4192                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
4193                 dest.writeLong(deltaTime);
4194             }
4195         }
4196         if (batteryLevelIntChanged) {
4197             dest.writeInt(batteryLevelInt);
4198             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
4199                     + Integer.toHexString(batteryLevelInt)
4200                     + " batteryLevel=" + cur.batteryLevel
4201                     + " batteryTemp=" + cur.batteryTemperature
4202                     + " batteryVolt=" + (int)cur.batteryVoltage);
4203         }
4204         if (stateIntChanged) {
4205             dest.writeInt(stateInt);
4206             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
4207                     + Integer.toHexString(stateInt)
4208                     + " batteryStatus=" + cur.batteryStatus
4209                     + " batteryHealth=" + cur.batteryHealth
4210                     + " batteryPlugType=" + cur.batteryPlugType
4211                     + " states=0x" + Integer.toHexString(cur.states));
4212         }
4213         if (state2IntChanged) {
4214             dest.writeInt(cur.states2);
4215             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
4216                     + Integer.toHexString(cur.states2));
4217         }
4218         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
4219             int wakeLockIndex;
4220             int wakeReasonIndex;
4221             if (cur.wakelockTag != null) {
4222                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
4223                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
4224                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
4225             } else {
4226                 wakeLockIndex = 0xffff;
4227             }
4228             if (cur.wakeReasonTag != null) {
4229                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
4230                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
4231                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
4232             } else {
4233                 wakeReasonIndex = 0xffff;
4234             }
4235             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
4236             if (cur.wakelockTag != null && (wakeLockIndex & TAG_FIRST_OCCURRENCE_FLAG) != 0) {
4237                 cur.wakelockTag.writeToParcel(dest, 0);
4238                 cur.tagsFirstOccurrence = true;
4239             }
4240             if (cur.wakeReasonTag != null && (wakeReasonIndex & TAG_FIRST_OCCURRENCE_FLAG) != 0) {
4241                 cur.wakeReasonTag.writeToParcel(dest, 0);
4242                 cur.tagsFirstOccurrence = true;
4243             }
4244         }
4245         if (cur.eventCode != HistoryItem.EVENT_NONE) {
4246             final int index = writeHistoryTag(cur.eventTag);
4247             final int codeAndIndex = (cur.eventCode & 0xffff) | (index << 16);
4248             dest.writeInt(codeAndIndex);
4249             if ((index & TAG_FIRST_OCCURRENCE_FLAG) != 0) {
4250                 cur.eventTag.writeToParcel(dest, 0);
4251                 cur.tagsFirstOccurrence = true;
4252             }
4253             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
4254                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
4255                     + cur.eventTag.string);
4256         }
4257         if (computeStepDetails) {
4258             if (mPlatformIdleStateCallback != null) {
4259                 mCurHistoryStepDetails.statSubsystemPowerState =
4260                         mPlatformIdleStateCallback.getSubsystemLowPowerStats();
4261                 if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
4262                         mCurHistoryStepDetails.statSubsystemPowerState);
4263 
4264             }
4265             computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
4266             if (includeStepDetails != 0) {
4267                 mCurHistoryStepDetails.writeToParcel(dest);
4268             }
4269             cur.stepDetails = mCurHistoryStepDetails;
4270             mLastHistoryStepDetails = mCurHistoryStepDetails;
4271         } else {
4272             cur.stepDetails = null;
4273         }
4274         if (mLastHistoryStepLevel < cur.batteryLevel) {
4275             mLastHistoryStepDetails = null;
4276         }
4277         mLastHistoryStepLevel = cur.batteryLevel;
4278 
4279         if (batteryChargeChanged) {
4280             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUah=" + cur.batteryChargeUah);
4281             dest.writeInt(cur.batteryChargeUah);
4282         }
4283         dest.writeDouble(cur.modemRailChargeMah);
4284         dest.writeDouble(cur.wifiRailChargeMah);
4285     }
4286 
buildBatteryLevelInt(HistoryItem h)4287     private int buildBatteryLevelInt(HistoryItem h) {
4288         return ((((int)h.batteryLevel)<<25)&0xfe000000)
4289                 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
4290                 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
4291     }
4292 
readBatteryLevelInt(int batteryLevelInt, HistoryItem out)4293     private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
4294         out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
4295         out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
4296         out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
4297     }
4298 
buildStateInt(HistoryItem h)4299     private int buildStateInt(HistoryItem h) {
4300         int plugType = 0;
4301         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
4302             plugType = 1;
4303         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
4304             plugType = 2;
4305         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
4306             plugType = 3;
4307         }
4308         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
4309                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
4310                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
4311                 | (h.states&(~STATE_BATTERY_MASK));
4312     }
4313 
computeHistoryStepDetails(final HistoryStepDetails out, final HistoryStepDetails last)4314     private void computeHistoryStepDetails(final HistoryStepDetails out,
4315             final HistoryStepDetails last) {
4316         final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
4317 
4318         // Perform a CPU update right after we do this collection, so we have started
4319         // collecting good data for the next step.
4320         requestImmediateCpuUpdate();
4321 
4322         if (last == null) {
4323             // We are not generating a delta, so all we need to do is reset the stats
4324             // we will later be doing a delta from.
4325             final int NU = mUidStats.size();
4326             for (int i=0; i<NU; i++) {
4327                 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4328                 uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
4329                 uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
4330             }
4331             mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
4332             mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
4333             mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
4334             mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
4335             mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
4336             mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
4337             mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
4338             mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
4339             tmp.clear();
4340             return;
4341         }
4342         if (DEBUG) {
4343             Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
4344                     + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
4345                     + " irq=" + mLastStepStatIrqTimeMs + " sirq="
4346                     + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
4347             Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
4348                     + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
4349                     + " irq=" + mCurStepStatIrqTimeMs + " sirq="
4350                     + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
4351         }
4352         out.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
4353         out.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
4354         out.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
4355         out.statSystemTime = (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
4356         out.statIOWaitTime = (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
4357         out.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
4358         out.statSoftIrqTime = (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
4359         out.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
4360         out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
4361         out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
4362         out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
4363         final int NU = mUidStats.size();
4364         for (int i=0; i<NU; i++) {
4365             final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4366             final int totalUTimeMs = (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
4367             final int totalSTimeMs = (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
4368             final int totalTimeMs = totalUTimeMs + totalSTimeMs;
4369             uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
4370             uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
4371             if (totalTimeMs <= (out.appCpuUTime3 + out.appCpuSTime3)) {
4372                 continue;
4373             }
4374             if (totalTimeMs <= (out.appCpuUTime2 + out.appCpuSTime2)) {
4375                 out.appCpuUid3 = uid.mUid;
4376                 out.appCpuUTime3 = totalUTimeMs;
4377                 out.appCpuSTime3 = totalSTimeMs;
4378             } else {
4379                 out.appCpuUid3 = out.appCpuUid2;
4380                 out.appCpuUTime3 = out.appCpuUTime2;
4381                 out.appCpuSTime3 = out.appCpuSTime2;
4382                 if (totalTimeMs <= (out.appCpuUTime1 + out.appCpuSTime1)) {
4383                     out.appCpuUid2 = uid.mUid;
4384                     out.appCpuUTime2 = totalUTimeMs;
4385                     out.appCpuSTime2 = totalSTimeMs;
4386                 } else {
4387                     out.appCpuUid2 = out.appCpuUid1;
4388                     out.appCpuUTime2 = out.appCpuUTime1;
4389                     out.appCpuSTime2 = out.appCpuSTime1;
4390                     out.appCpuUid1 = uid.mUid;
4391                     out.appCpuUTime1 = totalUTimeMs;
4392                     out.appCpuSTime1 = totalSTimeMs;
4393                 }
4394             }
4395         }
4396         mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
4397         mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
4398         mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
4399         mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
4400         mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
4401         mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
4402         mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
4403         mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
4404     }
4405 
4406     @GuardedBy("this")
4407     @Override
commitCurrentHistoryBatchLocked()4408     public void commitCurrentHistoryBatchLocked() {
4409         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
4410     }
4411 
4412     @GuardedBy("this")
createFakeHistoryEvents(long numEvents)4413     public void createFakeHistoryEvents(long numEvents) {
4414         final long elapsedRealtimeMs = mClock.elapsedRealtime();
4415         final long uptimeMs = mClock.uptimeMillis();
4416         for(long i = 0; i < numEvents; i++) {
4417             noteLongPartialWakelockStart("name1", "historyName1", 1000,
4418                     elapsedRealtimeMs, uptimeMs);
4419             noteLongPartialWakelockFinish("name1", "historyName1", 1000,
4420                     elapsedRealtimeMs, uptimeMs);
4421         }
4422     }
4423 
4424     @GuardedBy("this")
addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur)4425     void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
4426         if (!mHaveBatteryLevel || !mRecordingHistory) {
4427             return;
4428         }
4429 
4430         final long timeDiffMs = (mHistoryBaseTimeMs + elapsedRealtimeMs) - mHistoryLastWritten.time;
4431         final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
4432         final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
4433         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
4434         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
4435         if (DEBUG) {
4436             Slog.i(TAG, "ADD: tdelta=" + timeDiffMs + " diff="
4437                     + Integer.toHexString(diffStates) + " lastDiff="
4438                     + Integer.toHexString(lastDiffStates) + " diff2="
4439                     + Integer.toHexString(diffStates2) + " lastDiff2="
4440                     + Integer.toHexString(lastDiffStates2));
4441         }
4442 
4443         mBatteryStatsHistory.recordTraceEvents(cur.eventCode, cur.eventTag);
4444         mBatteryStatsHistory.recordTraceCounters(mHistoryLastWritten.states,
4445                 cur.states & mActiveHistoryStates, BatteryStats.HISTORY_STATE_DESCRIPTIONS);
4446         mBatteryStatsHistory.recordTraceCounters(mHistoryLastWritten.states2,
4447                 cur.states2 & mActiveHistoryStates2, BatteryStats.HISTORY_STATE2_DESCRIPTIONS);
4448         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
4449                 && timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0
4450                 && (diffStates2&lastDiffStates2) == 0
4451                 && (!mHistoryLastWritten.tagsFirstOccurrence && !cur.tagsFirstOccurrence)
4452                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
4453                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
4454                 && mHistoryLastWritten.stepDetails == null
4455                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
4456                         || cur.eventCode == HistoryItem.EVENT_NONE)
4457                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
4458                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
4459                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
4460                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
4461                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
4462                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
4463             // We can merge this new change in with the last one.  Merging is
4464             // allowed as long as only the states have changed, and within those states
4465             // as long as no bit has changed both between now and the last entry, as
4466             // well as the last entry and the one before it (so we capture any toggles).
4467             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
4468             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
4469             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
4470             mHistoryBufferLastPos = -1;
4471             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTimeMs;
4472             // If the last written history had a wakelock tag, we need to retain it.
4473             // Note that the condition above made sure that we aren't in a case where
4474             // both it and the current history item have a wakelock tag.
4475             if (mHistoryLastWritten.wakelockTag != null) {
4476                 cur.wakelockTag = cur.localWakelockTag;
4477                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
4478             }
4479             // If the last written history had a wake reason tag, we need to retain it.
4480             // Note that the condition above made sure that we aren't in a case where
4481             // both it and the current history item have a wakelock tag.
4482             if (mHistoryLastWritten.wakeReasonTag != null) {
4483                 cur.wakeReasonTag = cur.localWakeReasonTag;
4484                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
4485             }
4486             // If the last written history had an event, we need to retain it.
4487             // Note that the condition above made sure that we aren't in a case where
4488             // both it and the current history item have an event.
4489             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
4490                 cur.eventCode = mHistoryLastWritten.eventCode;
4491                 cur.eventTag = cur.localEventTag;
4492                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
4493             }
4494             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
4495         }
4496         final int dataSize = mHistoryBuffer.dataSize();
4497 
4498         if (dataSize >= mConstants.MAX_HISTORY_BUFFER) {
4499             //open a new history file.
4500             final long start = SystemClock.uptimeMillis();
4501             writeHistoryLocked(true);
4502             if (DEBUG) {
4503                 Slog.d(TAG, "addHistoryBufferLocked writeHistoryLocked takes ms:"
4504                         + (SystemClock.uptimeMillis() - start));
4505             }
4506             mBatteryStatsHistory.startNextFile();
4507             mHistoryBuffer.setDataSize(0);
4508             mHistoryBuffer.setDataPosition(0);
4509             mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
4510             mHistoryBufferLastPos = -1;
4511             mHistoryLastWritten.clear();
4512             mHistoryLastLastWritten.clear();
4513 
4514             // Mark every entry in the pool with a flag indicating that the tag
4515             // has not yet been encountered while writing the current history buffer.
4516             for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
4517                 entry.setValue(entry.getValue() | TAG_FIRST_OCCURRENCE_FLAG);
4518             }
4519             // Make a copy of mHistoryCur.
4520             HistoryItem copy = new HistoryItem();
4521             copy.setTo(cur);
4522             // startRecordingHistory will reset mHistoryCur.
4523             startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
4524             // Add the copy into history buffer.
4525             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, copy);
4526             return;
4527         }
4528 
4529         if (dataSize == 0) {
4530             // The history is currently empty; we need it to start with a time stamp.
4531             cur.currentTime = mClock.currentTimeMillis();
4532             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
4533         }
4534         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
4535     }
4536 
4537     @GuardedBy("this")
addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur)4538     private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
4539         if (mBatteryStatsHistoryIterator != null) {
4540             throw new IllegalStateException("Can't do this while iterating history!");
4541         }
4542         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
4543         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
4544         final boolean hasTags = mHistoryLastWritten.tagsFirstOccurrence || cur.tagsFirstOccurrence;
4545         mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
4546         mHistoryLastWritten.tagsFirstOccurrence = hasTags;
4547         mHistoryLastWritten.states &= mActiveHistoryStates;
4548         mHistoryLastWritten.states2 &= mActiveHistoryStates2;
4549         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
4550         mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
4551         cur.wakelockTag = null;
4552         cur.wakeReasonTag = null;
4553         cur.eventCode = HistoryItem.EVENT_NONE;
4554         cur.eventTag = null;
4555         cur.tagsFirstOccurrence = false;
4556         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
4557                 + " now " + mHistoryBuffer.dataPosition()
4558                 + " size is now " + mHistoryBuffer.dataSize());
4559     }
4560 
4561     int mChangedStates = 0;
4562     int mChangedStates2 = 0;
4563 
4564     @GuardedBy("this")
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs)4565     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
4566         if (mTrackRunningHistoryElapsedRealtimeMs != 0) {
4567             final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
4568             final long diffUptimeMs = uptimeMs - mTrackRunningHistoryUptimeMs;
4569             if (diffUptimeMs < (diffElapsedMs - 20)) {
4570                 final long wakeElapsedTimeMs = elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs);
4571                 mHistoryAddTmp.setTo(mHistoryLastWritten);
4572                 mHistoryAddTmp.wakelockTag = null;
4573                 mHistoryAddTmp.wakeReasonTag = null;
4574                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
4575                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
4576                 addHistoryRecordInnerLocked(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp);
4577             }
4578         }
4579         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
4580         mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs;
4581         mTrackRunningHistoryUptimeMs = uptimeMs;
4582         addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
4583     }
4584 
4585     @GuardedBy("this")
addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur)4586     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
4587         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
4588     }
4589 
4590     @GuardedBy("this")
addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)4591     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
4592             String name, int uid) {
4593         mHistoryCur.eventCode = code;
4594         mHistoryCur.eventTag = mHistoryCur.localEventTag;
4595         mHistoryCur.eventTag.string = name;
4596         mHistoryCur.eventTag.uid = uid;
4597         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4598     }
4599 
4600     @GuardedBy("this")
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur)4601     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
4602         HistoryItem rec = mHistoryCache;
4603         if (rec != null) {
4604             mHistoryCache = rec.next;
4605         } else {
4606             rec = new HistoryItem();
4607         }
4608         rec.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
4609 
4610         addHistoryRecordLocked(rec);
4611     }
4612 
4613     @GuardedBy("this")
addHistoryRecordLocked(HistoryItem rec)4614     void addHistoryRecordLocked(HistoryItem rec) {
4615         mNumHistoryItems++;
4616         rec.next = null;
4617         mHistoryLastEnd = mHistoryEnd;
4618         if (mHistoryEnd != null) {
4619             mHistoryEnd.next = rec;
4620             mHistoryEnd = rec;
4621         } else {
4622             mHistory = mHistoryEnd = rec;
4623         }
4624     }
4625 
4626     @GuardedBy("this")
clearHistoryLocked()4627     void clearHistoryLocked() {
4628         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
4629         mHistoryBaseTimeMs = 0;
4630         mLastHistoryElapsedRealtimeMs = 0;
4631         mTrackRunningHistoryElapsedRealtimeMs = 0;
4632         mTrackRunningHistoryUptimeMs = 0;
4633 
4634         mHistoryBuffer.setDataSize(0);
4635         mHistoryBuffer.setDataPosition(0);
4636         mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
4637         mHistoryLastLastWritten.clear();
4638         mHistoryLastWritten.clear();
4639         mHistoryTagPool.clear();
4640         mNextHistoryTagIdx = 0;
4641         mNumHistoryTagChars = 0;
4642         mHistoryBufferLastPos = -1;
4643         mActiveHistoryStates = 0xffffffff;
4644         mActiveHistoryStates2 = 0xffffffff;
4645     }
4646 
4647     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs, long realtimeUs)4648     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs,
4649             long realtimeUs) {
4650         final boolean screenOff = !Display.isOnState(screenState);
4651         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
4652         final boolean updateOnBatteryScreenOffTimeBase =
4653                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
4654 
4655         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
4656             if (updateOnBatteryScreenOffTimeBase) {
4657                 updateKernelWakelocksLocked(realtimeUs);
4658                 updateBatteryPropertiesLocked();
4659             }
4660             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
4661             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
4662             // improved, remove the surrounding if{}.
4663             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
4664                 // if either OnBattery or OnBatteryScreenOfftimebase changes.
4665                 updateRpmStatsLocked(realtimeUs);
4666             }
4667             if (DEBUG_ENERGY_CPU) {
4668                 Slog.d(TAG, "Updating cpu time because screen is now "
4669                         + Display.stateToString(screenState)
4670                         + " and battery is " + (unplugged ? "on" : "off"));
4671             }
4672 
4673             mOnBatteryTimeBase.setRunning(unplugged, uptimeUs, realtimeUs);
4674             if (updateOnBatteryTimeBase) {
4675                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4676                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptimeUs, realtimeUs);
4677                 }
4678             }
4679             if (updateOnBatteryScreenOffTimeBase) {
4680                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff,
4681                         uptimeUs, realtimeUs);
4682                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4683                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptimeUs, realtimeUs);
4684                 }
4685             }
4686         }
4687     }
4688 
4689     @GuardedBy("this")
updateBatteryPropertiesLocked()4690     private void updateBatteryPropertiesLocked() {
4691         try {
4692             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
4693                     ServiceManager.getService("batteryproperties"));
4694             if (registrar != null) {
4695                 registrar.scheduleUpdate();
4696             }
4697         } catch (RemoteException e) {
4698             // Ignore.
4699         }
4700     }
4701 
4702     @GuardedBy("this")
addIsolatedUidLocked(int isolatedUid, int appUid)4703     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
4704         addIsolatedUidLocked(isolatedUid, appUid,
4705                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4706     }
4707 
4708     @GuardedBy("this")
4709     @SuppressWarnings("GuardedBy")   // errorprone false positive on u.addIsolatedUid
addIsolatedUidLocked(int isolatedUid, int appUid, long elapsedRealtimeMs, long uptimeMs)4710     public void addIsolatedUidLocked(int isolatedUid, int appUid,
4711             long elapsedRealtimeMs, long uptimeMs) {
4712         mIsolatedUids.put(isolatedUid, appUid);
4713         mIsolatedUidRefCounts.put(isolatedUid, 1);
4714         final Uid u = getUidStatsLocked(appUid, elapsedRealtimeMs, uptimeMs);
4715         u.addIsolatedUid(isolatedUid);
4716     }
4717 
4718     /**
4719      * Schedules a read of the latest cpu times before removing the isolated UID.
4720      * @see #removeIsolatedUidLocked(int, int, int)
4721      */
scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid)4722     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
4723         int curUid = mIsolatedUids.get(isolatedUid, -1);
4724         if (curUid == appUid) {
4725             if (mExternalSync != null) {
4726                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
4727             }
4728         }
4729     }
4730 
4731     /**
4732      * Isolated uid should only be removed after all wakelocks associated with the uid are stopped
4733      * and the cpu time-in-state has been read one last time for the uid.
4734      *
4735      * @see #scheduleRemoveIsolatedUidLocked(int, int)
4736      *
4737      * @return true if the isolated uid is actually removed.
4738      */
4739     @GuardedBy("this")
maybeRemoveIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs)4740     public boolean maybeRemoveIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs,
4741             long uptimeMs) {
4742         final int refCount = mIsolatedUidRefCounts.get(isolatedUid, 0) - 1;
4743         if (refCount > 0) {
4744             // Isolated uid is still being tracked
4745             mIsolatedUidRefCounts.put(isolatedUid, refCount);
4746             return false;
4747         }
4748 
4749         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
4750         if (idx >= 0) {
4751             final int ownerUid = mIsolatedUids.valueAt(idx);
4752             final Uid u = getUidStatsLocked(ownerUid, elapsedRealtimeMs, uptimeMs);
4753             u.removeIsolatedUid(isolatedUid);
4754             mIsolatedUids.removeAt(idx);
4755             mIsolatedUidRefCounts.delete(isolatedUid);
4756         } else {
4757             Slog.w(TAG, "Attempted to remove untracked isolated uid (" + isolatedUid + ")");
4758         }
4759         mPendingRemovedUids.add(new UidToRemove(isolatedUid, elapsedRealtimeMs));
4760 
4761         return true;
4762     }
4763 
4764     /**
4765      * Increment the ref count for an isolated uid.
4766      * call #maybeRemoveIsolatedUidLocked to decrement.
4767      */
incrementIsolatedUidRefCount(int uid)4768     public void incrementIsolatedUidRefCount(int uid) {
4769         final int refCount = mIsolatedUidRefCounts.get(uid, 0);
4770         if (refCount <= 0) {
4771             // Uid is not mapped or referenced
4772             Slog.w(TAG,
4773                     "Attempted to increment ref counted of untracked isolated uid (" + uid + ")");
4774             return;
4775         }
4776         mIsolatedUidRefCounts.put(uid, refCount + 1);
4777     }
4778 
mapUid(int uid)4779     private int mapUid(int uid) {
4780         if (Process.isSdkSandboxUid(uid)) {
4781             return Process.getAppUidForSdkSandboxUid(uid);
4782         }
4783         return mapIsolatedUid(uid);
4784     }
4785 
mapIsolatedUid(int uid)4786     private int mapIsolatedUid(int uid) {
4787         return mIsolatedUids.get(/*key=*/uid, /*valueIfKeyNotFound=*/uid);
4788     }
4789 
4790     @GuardedBy("this")
noteEventLocked(int code, String name, int uid)4791     public void noteEventLocked(int code, String name, int uid) {
4792         noteEventLocked(code, name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4793     }
4794 
4795     @GuardedBy("this")
noteEventLocked(int code, String name, int uid, long elapsedRealtimeMs, long uptimeMs)4796     public void noteEventLocked(int code, String name, int uid,
4797             long elapsedRealtimeMs, long uptimeMs) {
4798         uid = mapUid(uid);
4799         if (!mActiveEvents.updateState(code, name, uid, 0)) {
4800             return;
4801         }
4802         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid);
4803     }
4804 
4805     @GuardedBy("this")
noteCurrentTimeChangedLocked()4806     public void noteCurrentTimeChangedLocked() {
4807         final long currentTime = mClock.currentTimeMillis();
4808         final long elapsedRealtime = mClock.elapsedRealtime();
4809         final long uptime = mClock.uptimeMillis();
4810         noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime);
4811     }
4812 
4813     @GuardedBy("this")
noteCurrentTimeChangedLocked(long currentTimeMs, long elapsedRealtimeMs, long uptimeMs)4814     public void noteCurrentTimeChangedLocked(long currentTimeMs,
4815             long elapsedRealtimeMs, long uptimeMs) {
4816         recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs);
4817     }
4818 
4819     @GuardedBy("this")
noteProcessStartLocked(String name, int uid)4820     public void noteProcessStartLocked(String name, int uid) {
4821         noteProcessStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4822     }
4823 
4824     @GuardedBy("this")
noteProcessStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4825     public void noteProcessStartLocked(String name, int uid,
4826             long elapsedRealtimeMs, long uptimeMs) {
4827         uid = mapUid(uid);
4828         if (isOnBattery()) {
4829             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4830             u.getProcessStatsLocked(name).incStartsLocked();
4831         }
4832         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
4833             return;
4834         }
4835         if (!mRecordAllHistory) {
4836             return;
4837         }
4838         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
4839     }
4840 
4841     @GuardedBy("this")
noteProcessCrashLocked(String name, int uid)4842     public void noteProcessCrashLocked(String name, int uid) {
4843         noteProcessCrashLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4844     }
4845 
4846     @GuardedBy("this")
noteProcessCrashLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4847     public void noteProcessCrashLocked(String name, int uid,
4848             long elapsedRealtimeMs, long uptimeMs) {
4849         uid = mapUid(uid);
4850         if (isOnBattery()) {
4851             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4852             u.getProcessStatsLocked(name).incNumCrashesLocked();
4853         }
4854     }
4855 
4856     @GuardedBy("this")
noteProcessAnrLocked(String name, int uid)4857     public void noteProcessAnrLocked(String name, int uid) {
4858         noteProcessAnrLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4859     }
4860 
4861     @GuardedBy("this")
noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4862     public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4863         uid = mapUid(uid);
4864         if (isOnBattery()) {
4865             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4866             u.getProcessStatsLocked(name).incNumAnrsLocked();
4867         }
4868     }
4869 
4870     @GuardedBy("this")
noteUidProcessStateLocked(int uid, int state)4871     public void noteUidProcessStateLocked(int uid, int state) {
4872         noteUidProcessStateLocked(uid, state, mClock.elapsedRealtime(), mClock.uptimeMillis());
4873     }
4874 
4875     @GuardedBy("this")
4876     @SuppressWarnings("GuardedBy")   // errorprone false positive on u.updateUidProcessStateLocked
noteUidProcessStateLocked(int uid, int state, long elapsedRealtimeMs, long uptimeMs)4877     public void noteUidProcessStateLocked(int uid, int state,
4878             long elapsedRealtimeMs, long uptimeMs) {
4879         int parentUid = mapUid(uid);
4880         if (uid != parentUid) {
4881             if (Process.isIsolated(uid)) {
4882                 // Isolated UIDs process state is already rolled up into parent, so no need to track
4883                 // Otherwise the parent's process state will get downgraded incorrectly
4884                 return;
4885             }
4886         }
4887         // TODO(b/155216561): It is possible for isolated uids to be in a higher
4888         // state than its parent uid. We should track the highest state within the union of host
4889         // and isolated uids rather than only the parent uid.
4890         FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
4891                 ActivityManager.processStateAmToProto(state));
4892         getUidStatsLocked(parentUid, elapsedRealtimeMs, uptimeMs)
4893                 .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs);
4894     }
4895 
4896     @GuardedBy("this")
noteProcessFinishLocked(String name, int uid)4897     public void noteProcessFinishLocked(String name, int uid) {
4898         noteProcessFinishLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4899     }
4900 
4901     @GuardedBy("this")
noteProcessFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4902     public void noteProcessFinishLocked(String name, int uid,
4903             long elapsedRealtimeMs, long uptimeMs) {
4904         uid = mapUid(uid);
4905         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4906             return;
4907         }
4908         if (!mRecordAllHistory) {
4909             return;
4910         }
4911         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH,
4912                 name, uid);
4913     }
4914 
4915     @GuardedBy("this")
noteSyncStartLocked(String name, int uid)4916     public void noteSyncStartLocked(String name, int uid) {
4917         noteSyncStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4918     }
4919 
4920     @GuardedBy("this")
noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4921     public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4922         uid = mapUid(uid);
4923         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4924                 .noteStartSyncLocked(name, elapsedRealtimeMs);
4925         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4926             return;
4927         }
4928         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
4929     }
4930 
4931     @GuardedBy("this")
noteSyncFinishLocked(String name, int uid)4932     public void noteSyncFinishLocked(String name, int uid) {
4933         noteSyncFinishLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4934     }
4935 
4936     @GuardedBy("this")
noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4937     public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4938         uid = mapUid(uid);
4939         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4940                 .noteStopSyncLocked(name, elapsedRealtimeMs);
4941         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4942             return;
4943         }
4944         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH,
4945                 name, uid);
4946     }
4947 
4948     @GuardedBy("this")
noteJobStartLocked(String name, int uid)4949     public void noteJobStartLocked(String name, int uid) {
4950         noteJobStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4951     }
4952 
4953     @GuardedBy("this")
noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4954     public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4955         uid = mapUid(uid);
4956         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4957                 .noteStartJobLocked(name, elapsedRealtimeMs);
4958         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4959             return;
4960         }
4961         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
4962     }
4963 
4964     @GuardedBy("this")
noteJobFinishLocked(String name, int uid, int stopReason)4965     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4966         noteJobFinishLocked(name, uid, stopReason,
4967                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4968     }
4969 
4970     @GuardedBy("this")
noteJobFinishLocked(String name, int uid, int stopReason, long elapsedRealtimeMs, long uptimeMs)4971     public void noteJobFinishLocked(String name, int uid, int stopReason,
4972             long elapsedRealtimeMs, long uptimeMs) {
4973         uid = mapUid(uid);
4974         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4975                 .noteStopJobLocked(name, elapsedRealtimeMs, stopReason);
4976         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4977             return;
4978         }
4979         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
4980     }
4981 
4982     @GuardedBy("this")
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast)4983     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
4984         noteJobsDeferredLocked(uid, numDeferred, sinceLast,
4985                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4986     }
4987 
4988     @GuardedBy("this")
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast, long elapsedRealtimeMs, long uptimeMs)4989     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast,
4990             long elapsedRealtimeMs, long uptimeMs) {
4991         uid = mapUid(uid);
4992         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4993                 .noteJobsDeferredLocked(numDeferred, sinceLast);
4994     }
4995 
4996     @GuardedBy("this")
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4997     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4998         noteAlarmStartLocked(name, workSource, uid,
4999                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5000     }
5001 
5002     @GuardedBy("this")
noteAlarmStartLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)5003     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid,
5004             long elapsedRealtimeMs, long uptimeMs) {
5005         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid,
5006                 elapsedRealtimeMs, uptimeMs);
5007     }
5008 
5009     @GuardedBy("this")
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)5010     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
5011         noteAlarmFinishLocked(name, workSource, uid,
5012                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5013     }
5014 
5015     @GuardedBy("this")
noteAlarmFinishLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)5016     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid,
5017             long elapsedRealtimeMs, long uptimeMs) {
5018         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid,
5019                 elapsedRealtimeMs, uptimeMs);
5020     }
5021 
5022     @GuardedBy("this")
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)5023     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
5024             int uid, long elapsedRealtimeMs, long uptimeMs) {
5025         if (!mRecordAllHistory) {
5026             return;
5027         }
5028 
5029         if (workSource != null) {
5030             for (int i = 0; i < workSource.size(); ++i) {
5031                 uid = mapUid(workSource.getUid(i));
5032                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
5033                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
5034                 }
5035             }
5036 
5037             List<WorkChain> workChains = workSource.getWorkChains();
5038             if (workChains != null) {
5039                 for (int i = 0; i < workChains.size(); ++i) {
5040                     uid = mapUid(workChains.get(i).getAttributionUid());
5041                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
5042                         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
5043                     }
5044                 }
5045             }
5046         } else {
5047             uid = mapUid(uid);
5048 
5049             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
5050                 addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
5051             }
5052         }
5053     }
5054 
5055     @GuardedBy("this")
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)5056     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
5057             String tag) {
5058         noteWakupAlarmLocked(packageName, uid, workSource, tag,
5059                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5060     }
5061 
5062     @GuardedBy("this")
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag, long elapsedRealtimeMs, long uptimeMs)5063     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
5064             String tag, long elapsedRealtimeMs, long uptimeMs) {
5065         if (workSource != null) {
5066             for (int i = 0; i < workSource.size(); ++i) {
5067                 uid = workSource.getUid(i);
5068                 final String workSourceName = workSource.getPackageName(i);
5069 
5070                 if (isOnBattery()) {
5071                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
5072                             workSourceName != null ? workSourceName : packageName,
5073                             elapsedRealtimeMs, uptimeMs);
5074                     pkg.noteWakeupAlarmLocked(tag);
5075                 }
5076             }
5077 
5078             List<WorkChain> workChains = workSource.getWorkChains();
5079             if (workChains != null) {
5080                 for (int i = 0; i < workChains.size(); ++i) {
5081                     final WorkChain wc = workChains.get(i);
5082                     uid = wc.getAttributionUid();
5083 
5084                     if (isOnBattery()) {
5085                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
5086                                 elapsedRealtimeMs, uptimeMs);
5087                         pkg.noteWakeupAlarmLocked(tag);
5088                     }
5089                 }
5090             }
5091         } else {
5092             if (isOnBattery()) {
5093                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
5094                         elapsedRealtimeMs, uptimeMs);
5095                 pkg.noteWakeupAlarmLocked(tag);
5096             }
5097         }
5098     }
5099 
requestWakelockCpuUpdate()5100     private void requestWakelockCpuUpdate() {
5101         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
5102     }
5103 
requestImmediateCpuUpdate()5104     private void requestImmediateCpuUpdate() {
5105         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
5106     }
5107 
5108     @GuardedBy("this")
setRecordAllHistoryLocked(boolean enabled)5109     public void setRecordAllHistoryLocked(boolean enabled) {
5110         mRecordAllHistory = enabled;
5111         if (!enabled) {
5112             // Clear out any existing state.
5113             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
5114             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
5115             // Record the currently running processes as stopping, now that we are no
5116             // longer tracking them.
5117             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
5118                     HistoryItem.EVENT_PROC);
5119             if (active != null) {
5120                 long mSecRealtime = mClock.elapsedRealtime();
5121                 final long mSecUptime = mClock.uptimeMillis();
5122                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
5123                     SparseIntArray uids = ent.getValue();
5124                     for (int j=0; j<uids.size(); j++) {
5125                         addHistoryEventLocked(mSecRealtime, mSecUptime,
5126                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
5127                     }
5128                 }
5129             }
5130         } else {
5131             // Record the currently running processes as starting, now that we are tracking them.
5132             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
5133                     HistoryItem.EVENT_PROC);
5134             if (active != null) {
5135                 long mSecRealtime = mClock.elapsedRealtime();
5136                 final long mSecUptime = mClock.uptimeMillis();
5137                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
5138                     SparseIntArray uids = ent.getValue();
5139                     for (int j=0; j<uids.size(); j++) {
5140                         addHistoryEventLocked(mSecRealtime, mSecUptime,
5141                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
5142                     }
5143                 }
5144             }
5145         }
5146     }
5147 
setNoAutoReset(boolean enabled)5148     public void setNoAutoReset(boolean enabled) {
5149         mNoAutoReset = enabled;
5150     }
5151 
5152     @GuardedBy("this")
setPretendScreenOff(boolean pretendScreenOff)5153     public void setPretendScreenOff(boolean pretendScreenOff) {
5154         if (mPretendScreenOff != pretendScreenOff) {
5155             mPretendScreenOff = pretendScreenOff;
5156             final int primaryScreenState = mPerDisplayBatteryStats[0].screenState;
5157             noteScreenStateLocked(0, primaryScreenState,
5158                     mClock.elapsedRealtime(), mClock.uptimeMillis(),
5159                     mClock.currentTimeMillis());
5160         }
5161     }
5162 
5163     private String mInitialAcquireWakeName;
5164     private int mInitialAcquireWakeUid = -1;
5165 
5166     @GuardedBy("this")
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging)5167     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5168             int type, boolean unimportantForLogging) {
5169         noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging,
5170                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5171     }
5172 
5173     @GuardedBy("this")
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)5174     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5175             int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) {
5176         final int mappedUid = mapUid(uid);
5177         if (type == WAKE_TYPE_PARTIAL) {
5178             // Only care about partial wake locks, since full wake locks
5179             // will be canceled when the user puts the screen to sleep.
5180             aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
5181             if (historyName == null) {
5182                 historyName = name;
5183             }
5184             if (mRecordAllHistory) {
5185                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
5186                         mappedUid, 0)) {
5187                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
5188                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, mappedUid);
5189                 }
5190             }
5191             if (mWakeLockNesting == 0) {
5192                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
5193                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
5194                         + Integer.toHexString(mHistoryCur.states));
5195                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
5196                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
5197                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = mappedUid;
5198                 mWakeLockImportant = !unimportantForLogging;
5199                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5200             } else if (!mWakeLockImportant && !unimportantForLogging
5201                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
5202                 if (mHistoryLastWritten.wakelockTag != null) {
5203                     // We'll try to update the last tag.
5204                     mHistoryLastWritten.wakelockTag = null;
5205                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
5206                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
5207                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = mappedUid;
5208                     addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5209                 }
5210                 mWakeLockImportant = true;
5211             }
5212             mWakeLockNesting++;
5213         }
5214         if (mappedUid >= 0) {
5215             if (mappedUid != uid) {
5216                 // Prevent the isolated uid mapping from being removed while the wakelock is
5217                 // being held.
5218                 incrementIsolatedUidRefCount(uid);
5219             }
5220             if (mOnBatteryScreenOffTimeBase.isRunning()) {
5221                 // We only update the cpu time when a wake lock is acquired if the screen is off.
5222                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
5223                 if (DEBUG_ENERGY_CPU) {
5224                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
5225                 }
5226                 requestWakelockCpuUpdate();
5227             }
5228 
5229             getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs)
5230                     .noteStartWakeLocked(pid, name, type, elapsedRealtimeMs);
5231 
5232             if (wc != null) {
5233                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
5234                         wc.getTags(), getPowerManagerWakeLockLevel(type), name,
5235                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
5236             } else {
5237                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED,
5238                         mapIsolatedUid(uid), null, getPowerManagerWakeLockLevel(type), name,
5239                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
5240             }
5241         }
5242     }
5243 
5244     @GuardedBy("this")
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type)5245     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5246             int type) {
5247         noteStopWakeLocked(uid, pid, wc, name, historyName, type,
5248                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5249     }
5250 
5251     @GuardedBy("this")
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)5252     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5253             int type, long elapsedRealtimeMs, long uptimeMs) {
5254         final int mappedUid = mapUid(uid);
5255         if (type == WAKE_TYPE_PARTIAL) {
5256             mWakeLockNesting--;
5257             if (mRecordAllHistory) {
5258                 if (historyName == null) {
5259                     historyName = name;
5260                 }
5261                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
5262                         mappedUid, 0)) {
5263                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
5264                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid);
5265                 }
5266             }
5267             if (mWakeLockNesting == 0) {
5268                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
5269                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
5270                         + Integer.toHexString(mHistoryCur.states));
5271                 mInitialAcquireWakeName = null;
5272                 mInitialAcquireWakeUid = -1;
5273                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5274             }
5275         }
5276         if (mappedUid >= 0) {
5277             if (mOnBatteryScreenOffTimeBase.isRunning()) {
5278                 if (DEBUG_ENERGY_CPU) {
5279                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
5280                 }
5281                 requestWakelockCpuUpdate();
5282             }
5283 
5284             getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs)
5285                     .noteStopWakeLocked(pid, name, type, elapsedRealtimeMs);
5286             if (wc != null) {
5287                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
5288                         wc.getTags(), getPowerManagerWakeLockLevel(type), name,
5289                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
5290             } else {
5291                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED,
5292                         mapIsolatedUid(uid), null, getPowerManagerWakeLockLevel(type), name,
5293                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
5294             }
5295 
5296             if (mappedUid != uid) {
5297                 // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
5298                 maybeRemoveIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
5299             }
5300         }
5301     }
5302 
5303     /**
5304      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
5305      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
5306      * These are estimations, since batterystats loses some of the original data.
5307      * TODO: Delete this. Instead, FrameworkStatsLog.write should be called from
5308      * PowerManager's Notifier.
5309      */
getPowerManagerWakeLockLevel(int battertStatsWakelockType)5310     private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
5311         switch (battertStatsWakelockType) {
5312             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
5313             case BatteryStats.WAKE_TYPE_PARTIAL:
5314                 return PowerManager.PARTIAL_WAKE_LOCK;
5315 
5316             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
5317             case BatteryStats.WAKE_TYPE_FULL:
5318                 return PowerManager.FULL_WAKE_LOCK;
5319 
5320             case BatteryStats.WAKE_TYPE_DRAW:
5321                 return PowerManager.DRAW_WAKE_LOCK;
5322 
5323             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
5324             case BatteryStats.WAKE_TYPE_WINDOW:
5325                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
5326                 return -1;
5327 
5328             default:
5329                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
5330                 return -1;
5331         }
5332     }
5333 
5334     @GuardedBy("this")
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging)5335     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
5336             String historyName, int type, boolean unimportantForLogging) {
5337         noteStartWakeFromSourceLocked(ws, pid, name, historyName, type, unimportantForLogging,
5338                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5339     }
5340 
5341     @GuardedBy("this")
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)5342     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
5343             String historyName, int type, boolean unimportantForLogging,
5344             long elapsedRealtimeMs, long uptimeMs) {
5345         final int N = ws.size();
5346         for (int i=0; i<N; i++) {
5347             noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
5348                     unimportantForLogging, elapsedRealtimeMs, uptimeMs);
5349         }
5350 
5351         List<WorkChain> wcs = ws.getWorkChains();
5352         if (wcs != null) {
5353             for (int i = 0; i < wcs.size(); ++i) {
5354                 final WorkChain wc = wcs.get(i);
5355                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
5356                         unimportantForLogging, elapsedRealtimeMs, uptimeMs);
5357             }
5358         }
5359     }
5360 
5361     @GuardedBy("this")
noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging)5362     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
5363             String historyName, int type, WorkSource newWs, int newPid, String newName,
5364             String newHistoryName, int newType, boolean newUnimportantForLogging) {
5365         noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type, newWs, newPid,
5366                 newName, newHistoryName, newType, newUnimportantForLogging,
5367                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5368     }
5369 
5370     @GuardedBy("this")
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)5371     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
5372             String historyName, int type, WorkSource newWs, int newPid, String newName,
5373             String newHistoryName, int newType, boolean newUnimportantForLogging,
5374             long elapsedRealtimeMs, long uptimeMs) {
5375         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
5376 
5377         // For correct semantics, we start the need worksources first, so that we won't
5378         // make inappropriate history items as if all wake locks went away and new ones
5379         // appeared.  This is okay because tracking of wake locks allows nesting.
5380         //
5381         // First the starts :
5382         final int NN = newWs.size();
5383         for (int i=0; i<NN; i++) {
5384             noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
5385                     newUnimportantForLogging, elapsedRealtimeMs, uptimeMs);
5386         }
5387         if (wcs != null) {
5388             List<WorkChain> newChains = wcs[0];
5389             if (newChains != null) {
5390                 for (int i = 0; i < newChains.size(); ++i) {
5391                     final WorkChain newChain = newChains.get(i);
5392                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
5393                             newHistoryName, newType, newUnimportantForLogging, elapsedRealtimeMs,
5394                             uptimeMs);
5395                 }
5396             }
5397         }
5398 
5399         // Then the stops :
5400         final int NO = ws.size();
5401         for (int i=0; i<NO; i++) {
5402             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
5403                     uptimeMs);
5404         }
5405         if (wcs != null) {
5406             List<WorkChain> goneChains = wcs[1];
5407             if (goneChains != null) {
5408                 for (int i = 0; i < goneChains.size(); ++i) {
5409                     final WorkChain goneChain = goneChains.get(i);
5410                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
5411                             historyName, type, elapsedRealtimeMs, uptimeMs);
5412                 }
5413             }
5414         }
5415     }
5416 
5417     @GuardedBy("this")
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type)5418     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
5419             String historyName, int type) {
5420         noteStopWakeFromSourceLocked(ws, pid, name, historyName, type,
5421                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5422     }
5423 
5424     @GuardedBy("this")
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)5425     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
5426             String historyName, int type, long elapsedRealtimeMs, long uptimeMs) {
5427         final int N = ws.size();
5428         for (int i=0; i<N; i++) {
5429             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
5430                     uptimeMs);
5431         }
5432 
5433         List<WorkChain> wcs = ws.getWorkChains();
5434         if (wcs != null) {
5435             for (int i = 0; i < wcs.size(); ++i) {
5436                 final WorkChain wc = wcs.get(i);
5437                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
5438                         elapsedRealtimeMs, uptimeMs);
5439             }
5440         }
5441     }
5442 
5443     @GuardedBy("this")
noteLongPartialWakelockStart(String name, String historyName, int uid)5444     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
5445         noteLongPartialWakelockStart(name, historyName, uid,
5446                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5447     }
5448 
5449     @GuardedBy("this")
noteLongPartialWakelockStart(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5450     public void noteLongPartialWakelockStart(String name, String historyName, int uid,
5451             long elapsedRealtimeMs, long uptimeMs) {
5452         noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
5453     }
5454 
5455     @GuardedBy("this")
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource)5456     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
5457             WorkSource workSource) {
5458         noteLongPartialWakelockStartFromSource(name, historyName, workSource,
5459                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5460     }
5461 
5462     @GuardedBy("this")
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)5463     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
5464             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
5465         final int N = workSource.size();
5466         for (int i = 0; i < N; ++i) {
5467             final int uid = mapUid(workSource.getUid(i));
5468             noteLongPartialWakeLockStartInternal(name, historyName, uid,
5469                     elapsedRealtimeMs, uptimeMs);
5470         }
5471 
5472         final List<WorkChain> workChains = workSource.getWorkChains();
5473         if (workChains != null) {
5474             for (int i = 0; i < workChains.size(); ++i) {
5475                 final WorkChain workChain = workChains.get(i);
5476                 final int uid = workChain.getAttributionUid();
5477                 noteLongPartialWakeLockStartInternal(name, historyName, uid,
5478                         elapsedRealtimeMs, uptimeMs);
5479             }
5480         }
5481     }
5482 
5483     @GuardedBy("this")
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5484     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid,
5485             long elapsedRealtimeMs, long uptimeMs) {
5486         final int mappedUid = mapUid(uid);
5487         if (historyName == null) {
5488             historyName = name;
5489         }
5490         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName,
5491                 mappedUid, 0)) {
5492             return;
5493         }
5494         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
5495                 historyName, mappedUid);
5496         if (mappedUid != uid) {
5497             // Prevent the isolated uid mapping from being removed while the wakelock is
5498             // being held.
5499             incrementIsolatedUidRefCount(uid);
5500         }
5501     }
5502 
5503     @GuardedBy("this")
noteLongPartialWakelockFinish(String name, String historyName, int uid)5504     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
5505         noteLongPartialWakelockFinish(name, historyName, uid,
5506                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5507     }
5508 
5509     @GuardedBy("this")
noteLongPartialWakelockFinish(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5510     public void noteLongPartialWakelockFinish(String name, String historyName, int uid,
5511             long elapsedRealtimeMs, long uptimeMs) {
5512         noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
5513     }
5514 
5515     @GuardedBy("this")
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource)5516     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
5517             WorkSource workSource) {
5518         noteLongPartialWakelockFinishFromSource(name, historyName, workSource,
5519                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5520     }
5521 
5522     @GuardedBy("this")
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)5523     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
5524             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
5525         final int N = workSource.size();
5526         for (int i = 0; i < N; ++i) {
5527             final int uid = mapUid(workSource.getUid(i));
5528             noteLongPartialWakeLockFinishInternal(name, historyName, uid,
5529                     elapsedRealtimeMs, uptimeMs);
5530         }
5531 
5532         final List<WorkChain> workChains = workSource.getWorkChains();
5533         if (workChains != null) {
5534             for (int i = 0; i < workChains.size(); ++i) {
5535                 final WorkChain workChain = workChains.get(i);
5536                 final int uid = workChain.getAttributionUid();
5537                 noteLongPartialWakeLockFinishInternal(name, historyName, uid,
5538                         elapsedRealtimeMs, uptimeMs);
5539             }
5540         }
5541     }
5542 
5543     @GuardedBy("this")
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5544     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid,
5545             long elapsedRealtimeMs, long uptimeMs) {
5546         final int mappedUid = mapUid(uid);
5547         if (historyName == null) {
5548             historyName = name;
5549         }
5550         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName,
5551                 mappedUid, 0)) {
5552             return;
5553         }
5554         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
5555                 historyName, mappedUid);
5556         if (mappedUid != uid) {
5557             // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
5558             maybeRemoveIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
5559         }
5560     }
5561 
5562     @GuardedBy("this")
aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs)5563     void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) {
5564         if (mLastWakeupReason != null) {
5565             long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs;
5566             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
5567             timer.add(deltaUptimeMs * 1000, 1, elapsedRealtimeMs); // time in in microseconds
5568             FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
5569                     /* duration_usec */ deltaUptimeMs * 1000);
5570             mLastWakeupReason = null;
5571         }
5572     }
5573 
5574     @GuardedBy("this")
noteWakeupReasonLocked(String reason)5575     public void noteWakeupReasonLocked(String reason) {
5576         noteWakeupReasonLocked(reason, mClock.elapsedRealtime(), mClock.uptimeMillis());
5577     }
5578 
5579     @GuardedBy("this")
noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs)5580     public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
5581         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
5582                 + Integer.toHexString(mHistoryCur.states));
5583         aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
5584         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
5585         mHistoryCur.wakeReasonTag.string = reason;
5586         mHistoryCur.wakeReasonTag.uid = 0;
5587         mLastWakeupReason = reason;
5588         mLastWakeupUptimeMs = uptimeMs;
5589         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5590     }
5591 
5592     @GuardedBy("this")
startAddingCpuLocked()5593     public boolean startAddingCpuLocked() {
5594         mExternalSync.cancelCpuSyncDueToWakelockChange();
5595         return mOnBatteryInternal;
5596     }
5597 
5598     @GuardedBy("this")
finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs)5599     public void finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
5600                                       int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
5601                                       int statSoftIrqTimeMs, int statIdleTimeMs) {
5602         if (DEBUG) {
5603             Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
5604                     + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
5605                     + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
5606                     + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
5607         }
5608         mCurStepCpuUserTimeMs += totalUTimeMs;
5609         mCurStepCpuSystemTimeMs += totalSTimeMs;
5610         mCurStepStatUserTimeMs += statUserTimeMs;
5611         mCurStepStatSystemTimeMs += statSystemTimeMs;
5612         mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
5613         mCurStepStatIrqTimeMs += statIrqTimeMs;
5614         mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
5615         mCurStepStatIdleTimeMs += statIdleTimeMs;
5616     }
5617 
noteProcessDiedLocked(int uid, int pid)5618     public void noteProcessDiedLocked(int uid, int pid) {
5619         uid = mapUid(uid);
5620         Uid u = mUidStats.get(uid);
5621         if (u != null) {
5622             u.mPids.remove(pid);
5623         }
5624     }
5625 
getProcessWakeTime(int uid, int pid, long realtimeMs)5626     public long getProcessWakeTime(int uid, int pid, long realtimeMs) {
5627         uid = mapUid(uid);
5628         Uid u = mUidStats.get(uid);
5629         if (u != null) {
5630             Uid.Pid p = u.mPids.get(pid);
5631             if (p != null) {
5632                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtimeMs - p.mWakeStartMs) : 0);
5633             }
5634         }
5635         return 0;
5636     }
5637 
reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs)5638     public void reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs) {
5639         uid = mapUid(uid);
5640         Uid u = mUidStats.get(uid);
5641         if (u != null) {
5642             u.reportExcessiveCpuLocked(proc, overTimeMs, usedTimeMs);
5643         }
5644     }
5645 
5646     int mSensorNesting;
5647 
5648     @GuardedBy("this")
noteStartSensorLocked(int uid, int sensor)5649     public void noteStartSensorLocked(int uid, int sensor) {
5650         noteStartSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
5651     }
5652 
5653     @GuardedBy("this")
noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)5654     public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
5655         uid = mapUid(uid);
5656         if (mSensorNesting == 0) {
5657             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
5658             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
5659                     + Integer.toHexString(mHistoryCur.states));
5660             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5661         }
5662         mSensorNesting++;
5663         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5664                 .noteStartSensor(sensor, elapsedRealtimeMs);
5665     }
5666 
5667     @GuardedBy("this")
noteStopSensorLocked(int uid, int sensor)5668     public void noteStopSensorLocked(int uid, int sensor) {
5669         noteStopSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
5670     }
5671 
5672     @GuardedBy("this")
noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)5673     public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
5674         uid = mapUid(uid);
5675         mSensorNesting--;
5676         if (mSensorNesting == 0) {
5677             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
5678             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
5679                     + Integer.toHexString(mHistoryCur.states));
5680             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5681         }
5682         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5683                 .noteStopSensor(sensor, elapsedRealtimeMs);
5684     }
5685 
5686     int mGpsNesting;
5687 
5688     @GuardedBy("this")
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)5689     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
5690         noteGpsChangedLocked(oldWs, newWs, mClock.elapsedRealtime(), mClock.uptimeMillis());
5691     }
5692 
5693     @GuardedBy("this")
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)5694     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs,
5695             long elapsedRealtimeMs, long uptimeMs) {
5696         for (int i = 0; i < newWs.size(); ++i) {
5697             noteStartGpsLocked(newWs.getUid(i), null, elapsedRealtimeMs, uptimeMs);
5698         }
5699 
5700         for (int i = 0; i < oldWs.size(); ++i) {
5701             noteStopGpsLocked((oldWs.getUid(i)), null, elapsedRealtimeMs, uptimeMs);
5702         }
5703 
5704         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
5705         if (wcs != null) {
5706             if (wcs[0] != null) {
5707                 final List<WorkChain> newChains = wcs[0];
5708                 for (int i = 0; i < newChains.size(); ++i) {
5709                     noteStartGpsLocked(-1, newChains.get(i), elapsedRealtimeMs, uptimeMs);
5710                 }
5711             }
5712 
5713             if (wcs[1] != null) {
5714                 final List<WorkChain> goneChains = wcs[1];
5715                 for (int i = 0; i < goneChains.size(); ++i) {
5716                     noteStopGpsLocked(-1, goneChains.get(i), elapsedRealtimeMs, uptimeMs);
5717                 }
5718             }
5719         }
5720     }
5721 
5722     @GuardedBy("this")
noteStartGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)5723     private void noteStartGpsLocked(int uid, WorkChain workChain,
5724             long elapsedRealtimeMs, long uptimeMs) {
5725         if (workChain != null) {
5726             uid = workChain.getAttributionUid();
5727         }
5728         final int mappedUid = mapUid(uid);
5729         if (mGpsNesting == 0) {
5730             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
5731             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
5732                     + Integer.toHexString(mHistoryCur.states));
5733             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5734         }
5735         mGpsNesting++;
5736 
5737         if (workChain == null) {
5738             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
5739                     mapIsolatedUid(uid), null, FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
5740         } else {
5741             FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
5742                     workChain.getUids(), workChain.getTags(),
5743                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
5744         }
5745 
5746         getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
5747     }
5748 
5749     @GuardedBy("this")
noteStopGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)5750     private void noteStopGpsLocked(int uid, WorkChain workChain,
5751             long elapsedRealtimeMs, long uptimeMs) {
5752         if (workChain != null) {
5753             uid = workChain.getAttributionUid();
5754         }
5755         final int mappedUid = mapUid(uid);
5756         mGpsNesting--;
5757         if (mGpsNesting == 0) {
5758             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
5759             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
5760                     + Integer.toHexString(mHistoryCur.states));
5761             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5762             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
5763             mGpsSignalQualityBin = -1;
5764         }
5765 
5766         if (workChain == null) {
5767             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
5768                     mapIsolatedUid(uid), null,
5769                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
5770         } else {
5771             FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
5772                     workChain.getTags(), FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
5773         }
5774 
5775         getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
5776     }
5777 
5778     @GuardedBy("this")
noteGpsSignalQualityLocked(int signalLevel)5779     public void noteGpsSignalQualityLocked(int signalLevel) {
5780         noteGpsSignalQualityLocked(signalLevel, mClock.elapsedRealtime(), mClock.uptimeMillis());
5781     }
5782 
5783     @GuardedBy("this")
noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs)5784     public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) {
5785         if (mGpsNesting == 0) {
5786             return;
5787         }
5788         if (signalLevel < 0 || signalLevel >= mGpsSignalQualityTimer.length) {
5789             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
5790             return;
5791         }
5792         if (mGpsSignalQualityBin != signalLevel) {
5793             if (mGpsSignalQualityBin >= 0) {
5794                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtimeMs);
5795             }
5796             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
5797                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
5798             }
5799             mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
5800                     | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
5801             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5802             mGpsSignalQualityBin = signalLevel;
5803         }
5804         return;
5805     }
5806 
5807     @GuardedBy("this")
noteScreenStateLocked(int display, int state)5808     public void noteScreenStateLocked(int display, int state) {
5809         noteScreenStateLocked(display, state, mClock.elapsedRealtime(), mClock.uptimeMillis(),
5810                 mClock.currentTimeMillis());
5811     }
5812 
5813     @GuardedBy("this")
noteScreenStateLocked(int display, int displayState, long elapsedRealtimeMs, long uptimeMs, long currentTimeMs)5814     public void noteScreenStateLocked(int display, int displayState,
5815             long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
5816         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
5817         // original 4 are mapped to one of the originals.
5818         if (displayState > MAX_TRACKED_SCREEN_STATE) {
5819             if (Display.isOnState(displayState)) {
5820                 displayState = Display.STATE_ON;
5821             } else if (Display.isDozeState(displayState)) {
5822                 if (Display.isSuspendedState(displayState)) {
5823                     displayState = Display.STATE_DOZE_SUSPEND;
5824                 } else {
5825                     displayState = Display.STATE_DOZE;
5826                 }
5827             } else if (Display.isOffState(displayState)) {
5828                 displayState = Display.STATE_OFF;
5829             } else {
5830                 Slog.wtf(TAG, "Unknown screen state (not mapped): " + displayState);
5831                 displayState = Display.STATE_UNKNOWN;
5832             }
5833         }
5834         // As of this point, displayState should be mapped to one of:
5835         //  - Display.STATE_ON,
5836         //  - Display.STATE_DOZE
5837         //  - Display.STATE_DOZE_SUSPEND
5838         //  - Display.STATE_OFF
5839         //  - Display.STATE_UNKNOWN
5840 
5841         int state;
5842         int overallBin = mScreenBrightnessBin;
5843         int externalUpdateFlag = 0;
5844         boolean shouldScheduleSync = false;
5845         final int numDisplay = mPerDisplayBatteryStats.length;
5846         if (display < 0 || display >= numDisplay) {
5847             Slog.wtf(TAG, "Unexpected note screen state for display " + display + " (only "
5848                     + mPerDisplayBatteryStats.length + " displays exist...)");
5849             return;
5850         }
5851         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5852         final int oldDisplayState = displayStats.screenState;
5853 
5854         if (oldDisplayState == displayState) {
5855             // Nothing changed
5856             state = mScreenState;
5857         } else {
5858             displayStats.screenState = displayState;
5859 
5860             // Stop timer for previous display state.
5861             switch (oldDisplayState) {
5862                 case Display.STATE_ON:
5863                     displayStats.screenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5864                     final int bin = displayStats.screenBrightnessBin;
5865                     if (bin >= 0) {
5866                         displayStats.screenBrightnessTimers[bin].stopRunningLocked(
5867                                 elapsedRealtimeMs);
5868                     }
5869                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5870                     shouldScheduleSync = true;
5871                     break;
5872                 case Display.STATE_DOZE:
5873                     // Transition from doze to doze suspend can be ignored.
5874                     if (displayState == Display.STATE_DOZE_SUSPEND) break;
5875                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5876                     shouldScheduleSync = true;
5877                     break;
5878                 case Display.STATE_DOZE_SUSPEND:
5879                     // Transition from doze suspend to doze can be ignored.
5880                     if (displayState == Display.STATE_DOZE) break;
5881                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5882                     shouldScheduleSync = true;
5883                     break;
5884                 case Display.STATE_OFF: // fallthrough
5885                 case Display.STATE_UNKNOWN:
5886                     // Not tracked by timers.
5887                     break;
5888                 default:
5889                     Slog.wtf(TAG,
5890                             "Attempted to stop timer for unexpected display state " + display);
5891             }
5892 
5893             // Start timer for new display state.
5894             switch (displayState) {
5895                 case Display.STATE_ON:
5896                     displayStats.screenOnTimer.startRunningLocked(elapsedRealtimeMs);
5897                     final int bin = displayStats.screenBrightnessBin;
5898                     if (bin >= 0) {
5899                         displayStats.screenBrightnessTimers[bin].startRunningLocked(
5900                                 elapsedRealtimeMs);
5901                     }
5902                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5903                     shouldScheduleSync = true;
5904                     break;
5905                 case Display.STATE_DOZE:
5906                     // Transition from doze suspend to doze can be ignored.
5907                     if (oldDisplayState == Display.STATE_DOZE_SUSPEND) break;
5908                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5909                     shouldScheduleSync = true;
5910                     break;
5911                 case Display.STATE_DOZE_SUSPEND:
5912                     // Transition from doze to doze suspend can be ignored.
5913                     if (oldDisplayState == Display.STATE_DOZE) break;
5914                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5915                     shouldScheduleSync = true;
5916                     break;
5917                 case Display.STATE_OFF: // fallthrough
5918                 case Display.STATE_UNKNOWN:
5919                     // Not tracked by timers.
5920                     break;
5921                 default:
5922                     Slog.wtf(TAG,
5923                             "Attempted to start timer for unexpected display state " + displayState
5924                                     + " for display " + display);
5925             }
5926 
5927             if (shouldScheduleSync
5928                     && mGlobalMeasuredEnergyStats != null
5929                     && mGlobalMeasuredEnergyStats.isStandardBucketSupported(
5930                     MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON)) {
5931                 // Display measured energy stats is available. Prepare to schedule an
5932                 // external sync.
5933                 externalUpdateFlag |= ExternalStatsSync.UPDATE_DISPLAY;
5934             }
5935 
5936             // Reevaluate most important display screen state.
5937             state = Display.STATE_UNKNOWN;
5938             for (int i = 0; i < numDisplay; i++) {
5939                 final int tempState = mPerDisplayBatteryStats[i].screenState;
5940                 if (tempState == Display.STATE_ON
5941                         || state == Display.STATE_ON) {
5942                     state = Display.STATE_ON;
5943                 } else if (tempState == Display.STATE_DOZE
5944                         || state == Display.STATE_DOZE) {
5945                     state = Display.STATE_DOZE;
5946                 } else if (tempState == Display.STATE_DOZE_SUSPEND
5947                         || state == Display.STATE_DOZE_SUSPEND) {
5948                     state = Display.STATE_DOZE_SUSPEND;
5949                 } else if (tempState == Display.STATE_OFF
5950                         || state == Display.STATE_OFF) {
5951                     state = Display.STATE_OFF;
5952                 }
5953             }
5954         }
5955 
5956         final boolean batteryRunning = mOnBatteryTimeBase.isRunning();
5957         final boolean batteryScreenOffRunning = mOnBatteryScreenOffTimeBase.isRunning();
5958 
5959         state = mPretendScreenOff ? Display.STATE_OFF : state;
5960         if (mScreenState != state) {
5961             recordDailyStatsIfNeededLocked(true, currentTimeMs);
5962             final int oldState = mScreenState;
5963             mScreenState = state;
5964             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
5965                     + ", newState=" + Display.stateToString(state));
5966 
5967             if (state != Display.STATE_UNKNOWN) {
5968                 int stepState = state-1;
5969                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
5970                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
5971                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
5972                 } else {
5973                     Slog.wtf(TAG, "Unexpected screen state: " + state);
5974                 }
5975             }
5976 
5977             boolean updateHistory = false;
5978             if (Display.isDozeState(state) && !Display.isDozeState(oldState)) {
5979                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
5980                 mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5981                 updateHistory = true;
5982             } else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) {
5983                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
5984                 mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5985                 updateHistory = true;
5986             }
5987             if (Display.isOnState(state)) {
5988                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
5989                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
5990                         + Integer.toHexString(mHistoryCur.states));
5991                 mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
5992                 if (mScreenBrightnessBin >= 0) {
5993                     mScreenBrightnessTimer[mScreenBrightnessBin]
5994                             .startRunningLocked(elapsedRealtimeMs);
5995                 }
5996                 updateHistory = true;
5997             } else if (Display.isOnState(oldState)) {
5998                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
5999                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
6000                         + Integer.toHexString(mHistoryCur.states));
6001                 mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
6002                 if (mScreenBrightnessBin >= 0) {
6003                     mScreenBrightnessTimer[mScreenBrightnessBin]
6004                             .stopRunningLocked(elapsedRealtimeMs);
6005                 }
6006                 updateHistory = true;
6007             }
6008             if (updateHistory) {
6009                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
6010                         + Display.stateToString(state));
6011                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6012             }
6013 
6014             // Per screen state Cpu stats needed. Prepare to schedule an external sync.
6015             externalUpdateFlag |= ExternalStatsSync.UPDATE_CPU;
6016             shouldScheduleSync = true;
6017 
6018             if (Display.isOnState(state)) {
6019                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
6020                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
6021                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
6022                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
6023                         elapsedRealtimeMs, uptimeMs);
6024             } else if (Display.isOnState(oldState)) {
6025                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
6026                         elapsedRealtimeMs, uptimeMs);
6027                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
6028                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
6029             }
6030             // Update discharge amounts.
6031             if (mOnBatteryInternal) {
6032                 updateDischargeScreenLevelsLocked(oldState, state);
6033             }
6034         }
6035 
6036         // Changing display states might have changed the screen used to determine the overall
6037         // brightness.
6038         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
6039 
6040         if (shouldScheduleSync) {
6041             final int numDisplays = mPerDisplayBatteryStats.length;
6042             final int[] displayStates = new int[numDisplays];
6043             for (int i = 0; i < numDisplays; i++) {
6044                 displayStates[i] = mPerDisplayBatteryStats[i].screenState;
6045             }
6046             mExternalSync.scheduleSyncDueToScreenStateChange(externalUpdateFlag,
6047                     batteryRunning, batteryScreenOffRunning, state, displayStates);
6048         }
6049     }
6050 
6051     @UnsupportedAppUsage
6052     @GuardedBy("this")
noteScreenBrightnessLocked(int brightness)6053     public void noteScreenBrightnessLocked(int brightness) {
6054         noteScreenBrightnessLocked(0, brightness);
6055     }
6056 
6057     /**
6058      * Note screen brightness change for a display.
6059      */
6060     @GuardedBy("this")
noteScreenBrightnessLocked(int display, int brightness)6061     public void noteScreenBrightnessLocked(int display, int brightness) {
6062         noteScreenBrightnessLocked(display, brightness, mClock.elapsedRealtime(),
6063                 mClock.uptimeMillis());
6064     }
6065 
6066 
6067     /**
6068      * Note screen brightness change for a display.
6069      */
6070     @GuardedBy("this")
noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs, long uptimeMs)6071     public void noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs,
6072             long uptimeMs) {
6073         // Bin the brightness.
6074         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
6075         if (bin < 0) bin = 0;
6076         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
6077 
6078         final int overallBin;
6079 
6080         final int numDisplays = mPerDisplayBatteryStats.length;
6081         if (display < 0 || display >= numDisplays) {
6082             Slog.wtf(TAG, "Unexpected note screen brightness for display " + display + " (only "
6083                     + mPerDisplayBatteryStats.length + " displays exist...)");
6084             return;
6085         }
6086 
6087         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
6088         final int oldBin = displayStats.screenBrightnessBin;
6089         if (oldBin == bin) {
6090             // Nothing changed
6091             overallBin = mScreenBrightnessBin;
6092         } else {
6093             displayStats.screenBrightnessBin = bin;
6094             if (displayStats.screenState == Display.STATE_ON) {
6095                 if (oldBin >= 0) {
6096                     displayStats.screenBrightnessTimers[oldBin].stopRunningLocked(
6097                             elapsedRealtimeMs);
6098                 }
6099                 displayStats.screenBrightnessTimers[bin].startRunningLocked(
6100                         elapsedRealtimeMs);
6101             }
6102             overallBin = evaluateOverallScreenBrightnessBinLocked();
6103         }
6104 
6105         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
6106     }
6107 
6108     @GuardedBy("this")
evaluateOverallScreenBrightnessBinLocked()6109     private int evaluateOverallScreenBrightnessBinLocked() {
6110         int overallBin = -1;
6111         final int numDisplays = getDisplayCount();
6112         for (int display = 0; display < numDisplays; display++) {
6113             final int displayBrightnessBin;
6114             if (mPerDisplayBatteryStats[display].screenState == Display.STATE_ON) {
6115                 displayBrightnessBin = mPerDisplayBatteryStats[display].screenBrightnessBin;
6116             } else {
6117                 displayBrightnessBin = -1;
6118             }
6119             if (displayBrightnessBin > overallBin) {
6120                 overallBin = displayBrightnessBin;
6121             }
6122         }
6123         return overallBin;
6124     }
6125 
6126     @GuardedBy("this")
maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs, long uptimeMs)6127     private void maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs,
6128             long uptimeMs) {
6129         if (mScreenBrightnessBin != overallBin) {
6130             if (overallBin >= 0) {
6131                 mHistoryCur.states = (mHistoryCur.states & ~HistoryItem.STATE_BRIGHTNESS_MASK)
6132                         | (overallBin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
6133                 if (DEBUG_HISTORY) {
6134                     Slog.v(TAG, "Screen brightness " + overallBin + " to: "
6135                             + Integer.toHexString(mHistoryCur.states));
6136                 }
6137                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6138             }
6139             if (mScreenState == Display.STATE_ON) {
6140                 if (mScreenBrightnessBin >= 0) {
6141                     mScreenBrightnessTimer[mScreenBrightnessBin]
6142                             .stopRunningLocked(elapsedRealtimeMs);
6143                 }
6144                 if (overallBin >= 0) {
6145                     mScreenBrightnessTimer[overallBin]
6146                             .startRunningLocked(elapsedRealtimeMs);
6147                 }
6148             }
6149             mScreenBrightnessBin = overallBin;
6150         }
6151     }
6152 
6153     @UnsupportedAppUsage
6154     @GuardedBy("this")
noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event)6155     public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event) {
6156         noteUserActivityLocked(uid, event, mClock.elapsedRealtime(), mClock.uptimeMillis());
6157     }
6158 
6159     @GuardedBy("this")
noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event, long elapsedRealtimeMs, long uptimeMs)6160     public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event,
6161             long elapsedRealtimeMs, long uptimeMs) {
6162         if (mOnBatteryInternal) {
6163             uid = mapUid(uid);
6164             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event);
6165         }
6166     }
6167 
6168     @GuardedBy("this")
noteWakeUpLocked(String reason, int reasonUid)6169     public void noteWakeUpLocked(String reason, int reasonUid) {
6170         noteWakeUpLocked(reason, reasonUid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6171     }
6172 
6173     @GuardedBy("this")
noteWakeUpLocked(String reason, int reasonUid, long elapsedRealtimeMs, long uptimeMs)6174     public void noteWakeUpLocked(String reason, int reasonUid,
6175             long elapsedRealtimeMs, long uptimeMs) {
6176         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP,
6177                 reason, reasonUid);
6178     }
6179 
6180     @GuardedBy("this")
noteInteractiveLocked(boolean interactive)6181     public void noteInteractiveLocked(boolean interactive) {
6182         noteInteractiveLocked(interactive, mClock.elapsedRealtime());
6183     }
6184 
6185     @GuardedBy("this")
noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs)6186     public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) {
6187         if (mInteractive != interactive) {
6188             mInteractive = interactive;
6189             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
6190             if (interactive) {
6191                 mInteractiveTimer.startRunningLocked(elapsedRealtimeMs);
6192             } else {
6193                 mInteractiveTimer.stopRunningLocked(elapsedRealtimeMs);
6194             }
6195         }
6196     }
6197 
6198     @GuardedBy("this")
noteConnectivityChangedLocked(int type, String extra)6199     public void noteConnectivityChangedLocked(int type, String extra) {
6200         noteConnectivityChangedLocked(type, extra,
6201                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6202     }
6203 
6204     @GuardedBy("this")
noteConnectivityChangedLocked(int type, String extra, long elapsedRealtimeMs, long uptimeMs)6205     public void noteConnectivityChangedLocked(int type, String extra,
6206             long elapsedRealtimeMs, long uptimeMs) {
6207         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
6208                 extra, type);
6209         mNumConnectivityChange++;
6210     }
6211 
6212     @GuardedBy("this")
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)6213     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
6214             final long uptimeMillis, int uid) {
6215         uid = mapUid(uid);
6216         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
6217                 uid);
6218         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
6219     }
6220 
6221     /**
6222      * Updates the radio power state and returns true if an external stats collection should occur.
6223      */
6224     @GuardedBy("this")
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)6225     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
6226         return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
6227                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6228     }
6229 
6230     @GuardedBy("this")
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)6231     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid,
6232             long elapsedRealtimeMs, long uptimeMs) {
6233         if (mMobileRadioPowerState != powerState) {
6234             long realElapsedRealtimeMs;
6235             final boolean active = isActiveRadioPowerState(powerState);
6236             if (active) {
6237                 if (uid > 0) {
6238                     noteMobileRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
6239                 }
6240 
6241                 mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
6242                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
6243             } else {
6244                 realElapsedRealtimeMs = timestampNs / (1000*1000);
6245                 long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
6246                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
6247                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
6248                             + " is before start time " + lastUpdateTimeMs);
6249                     realElapsedRealtimeMs = elapsedRealtimeMs;
6250                 } else if (realElapsedRealtimeMs < elapsedRealtimeMs) {
6251                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
6252                             - realElapsedRealtimeMs);
6253                 }
6254                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
6255             }
6256             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
6257                     + Integer.toHexString(mHistoryCur.states));
6258             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6259             mMobileRadioPowerState = powerState;
6260 
6261             // Inform current RatBatteryStats that the modem active state might have changed.
6262             getRatBatteryStatsLocked(mActiveRat).noteActive(active, elapsedRealtimeMs);
6263 
6264             if (active) {
6265                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs);
6266                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs);
6267             } else {
6268                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
6269                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
6270 
6271                 if (mLastModemActivityInfo != null) {
6272                     if (elapsedRealtimeMs < mLastModemActivityInfo.getTimestampMillis()
6273                             + MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS) {
6274                         // Modem Activity info has been collected recently, don't bother
6275                         // triggering another update.
6276                         return false;
6277                     }
6278                 }
6279                 // Tell the caller to collect radio network/power stats.
6280                 return true;
6281             }
6282         }
6283         return false;
6284     }
6285 
isActiveRadioPowerState(int powerState)6286     private static boolean isActiveRadioPowerState(int powerState) {
6287         return powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
6288                 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
6289     }
6290 
6291     @GuardedBy("this")
notePowerSaveModeLocked(boolean enabled)6292     public void notePowerSaveModeLocked(boolean enabled) {
6293         notePowerSaveModeLocked(enabled, mClock.elapsedRealtime(), mClock.uptimeMillis());
6294     }
6295 
6296     /**
6297      * Toggles the power save mode state.
6298      */
6299     @GuardedBy("this")
notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs, long uptimeMs)6300     public void notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs,
6301             long uptimeMs) {
6302         if (mPowerSaveModeEnabled != enabled) {
6303             notePowerSaveModeLocked(enabled, elapsedRealtimeMs, uptimeMs);
6304         } else {
6305             // Log an initial value for BATTERY_SAVER_MODE_STATE_CHANGED in order to
6306             // allow the atom to read all future state changes.
6307             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
6308                     enabled
6309                         ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
6310                         : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
6311         }
6312     }
6313 
6314     @GuardedBy("this")
notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs)6315     public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs) {
6316         if (mPowerSaveModeEnabled != enabled) {
6317             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
6318             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
6319             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
6320             mPowerSaveModeEnabled = enabled;
6321             if (enabled) {
6322                 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
6323                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
6324                         + Integer.toHexString(mHistoryCur.states2));
6325                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
6326             } else {
6327                 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
6328                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
6329                         + Integer.toHexString(mHistoryCur.states2));
6330                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
6331             }
6332             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6333             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
6334                     enabled
6335                         ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
6336                         : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
6337         }
6338     }
6339 
6340     @GuardedBy("this")
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid)6341     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
6342         noteDeviceIdleModeLocked(mode, activeReason, activeUid,
6343                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6344     }
6345 
6346     @GuardedBy("this")
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid, long elapsedRealtimeMs, long uptimeMs)6347     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid,
6348             long elapsedRealtimeMs, long uptimeMs) {
6349         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
6350         if (mDeviceIdling && !nowIdling && activeReason == null) {
6351             // We don't go out of general idling mode until explicitly taken out of
6352             // device idle through going active or significant motion.
6353             nowIdling = true;
6354         }
6355         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
6356         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
6357             // We don't go out of general light idling mode until explicitly taken out of
6358             // device idle through going active or significant motion.
6359             nowLightIdling = true;
6360         }
6361         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
6362             addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
6363                     activeReason, activeUid);
6364         }
6365         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
6366             int statsmode;
6367             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
6368             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
6369             else                     statsmode = DEVICE_IDLE_MODE_OFF;
6370             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
6371         }
6372         if (mDeviceIdling != nowIdling) {
6373             mDeviceIdling = nowIdling;
6374             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
6375             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
6376             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
6377             if (nowIdling) {
6378                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtimeMs);
6379             } else {
6380                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
6381             }
6382         }
6383         if (mDeviceLightIdling != nowLightIdling) {
6384             mDeviceLightIdling = nowLightIdling;
6385             if (nowLightIdling) {
6386                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtimeMs);
6387             } else {
6388                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
6389             }
6390         }
6391         if (mDeviceIdleMode != mode) {
6392             mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
6393                     | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
6394             if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
6395                     + Integer.toHexString(mHistoryCur.states2));
6396             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6397             long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
6398             mLastIdleTimeStartMs = elapsedRealtimeMs;
6399             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
6400                 if (lastDuration > mLongestLightIdleTimeMs) {
6401                     mLongestLightIdleTimeMs = lastDuration;
6402                 }
6403                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtimeMs);
6404             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
6405                 if (lastDuration > mLongestFullIdleTimeMs) {
6406                     mLongestFullIdleTimeMs = lastDuration;
6407                 }
6408                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtimeMs);
6409             }
6410             if (mode == DEVICE_IDLE_MODE_LIGHT) {
6411                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtimeMs);
6412             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
6413                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtimeMs);
6414             }
6415             mDeviceIdleMode = mode;
6416             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
6417         }
6418     }
6419 
6420     @GuardedBy("this")
notePackageInstalledLocked(String pkgName, long versionCode)6421     public void notePackageInstalledLocked(String pkgName, long versionCode) {
6422         notePackageInstalledLocked(pkgName, versionCode,
6423                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6424     }
6425 
6426     @GuardedBy("this")
notePackageInstalledLocked(String pkgName, long versionCode, long elapsedRealtimeMs, long uptimeMs)6427     public void notePackageInstalledLocked(String pkgName, long versionCode,
6428             long elapsedRealtimeMs, long uptimeMs) {
6429         // XXX need to figure out what to do with long version codes.
6430         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
6431                 pkgName, (int)versionCode);
6432         PackageChange pc = new PackageChange();
6433         pc.mPackageName = pkgName;
6434         pc.mUpdate = true;
6435         pc.mVersionCode = versionCode;
6436         addPackageChange(pc);
6437     }
6438 
6439     @GuardedBy("this")
notePackageUninstalledLocked(String pkgName)6440     public void notePackageUninstalledLocked(String pkgName) {
6441         notePackageUninstalledLocked(pkgName, mClock.elapsedRealtime(), mClock.uptimeMillis());
6442     }
6443 
6444     @GuardedBy("this")
notePackageUninstalledLocked(String pkgName, long elapsedRealtimeMs, long uptimeMs)6445     public void notePackageUninstalledLocked(String pkgName,
6446             long elapsedRealtimeMs, long uptimeMs) {
6447         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
6448                 HistoryItem.EVENT_PACKAGE_UNINSTALLED, pkgName, 0);
6449         PackageChange pc = new PackageChange();
6450         pc.mPackageName = pkgName;
6451         pc.mUpdate = true;
6452         addPackageChange(pc);
6453     }
6454 
addPackageChange(PackageChange pc)6455     private void addPackageChange(PackageChange pc) {
6456         if (mDailyPackageChanges == null) {
6457             mDailyPackageChanges = new ArrayList<>();
6458         }
6459         mDailyPackageChanges.add(pc);
6460     }
6461 
6462     @GuardedBy("this")
stopAllGpsSignalQualityTimersLocked(int except)6463     void stopAllGpsSignalQualityTimersLocked(int except) {
6464         stopAllGpsSignalQualityTimersLocked(except, mClock.elapsedRealtime());
6465     }
6466 
6467     @GuardedBy("this")
stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs)6468     void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
6469         for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
6470             if (i == except) {
6471                 continue;
6472             }
6473             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
6474                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtimeMs);
6475             }
6476         }
6477     }
6478 
6479     @UnsupportedAppUsage
6480     @GuardedBy("this")
notePhoneOnLocked()6481     public void notePhoneOnLocked() {
6482         notePhoneOnLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
6483     }
6484 
6485     @GuardedBy("this")
notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs)6486     public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
6487         if (!mPhoneOn) {
6488             mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
6489             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
6490                     + Integer.toHexString(mHistoryCur.states));
6491             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6492             mPhoneOn = true;
6493             mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
6494             if (mConstants.PHONE_ON_EXTERNAL_STATS_COLLECTION) {
6495                 scheduleSyncExternalStatsLocked("phone-on", ExternalStatsSync.UPDATE_RADIO);
6496             }
6497         }
6498     }
6499 
6500     @UnsupportedAppUsage
6501     @GuardedBy("this")
notePhoneOffLocked()6502     public void notePhoneOffLocked() {
6503         notePhoneOffLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
6504     }
6505 
6506     @GuardedBy("this")
notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs)6507     public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
6508         if (mPhoneOn) {
6509             mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
6510             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
6511                     + Integer.toHexString(mHistoryCur.states));
6512             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6513             mPhoneOn = false;
6514             mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
6515             scheduleSyncExternalStatsLocked("phone-off", ExternalStatsSync.UPDATE_RADIO);
6516         }
6517     }
6518 
6519     @GuardedBy("this")
registerUsbStateReceiver(Context context)6520     private void registerUsbStateReceiver(Context context) {
6521         final IntentFilter usbStateFilter = new IntentFilter();
6522         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
6523         context.registerReceiver(new BroadcastReceiver() {
6524             @Override
6525             public void onReceive(Context context, Intent intent) {
6526                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
6527                 synchronized (BatteryStatsImpl.this) {
6528                     noteUsbConnectionStateLocked(state, mClock.elapsedRealtime(),
6529                             mClock.uptimeMillis());
6530                 }
6531             }
6532         }, usbStateFilter);
6533         synchronized (this) {
6534             if (mUsbDataState == USB_DATA_UNKNOWN) {
6535                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
6536                 final boolean initState = usbState != null && usbState.getBooleanExtra(
6537                         UsbManager.USB_CONNECTED, false);
6538                 noteUsbConnectionStateLocked(initState, mClock.elapsedRealtime(),
6539                         mClock.uptimeMillis());
6540             }
6541         }
6542     }
6543 
6544     @GuardedBy("this")
noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs, long uptimeMs)6545     private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs,
6546             long uptimeMs) {
6547         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
6548         if (mUsbDataState != newState) {
6549             mUsbDataState = newState;
6550             if (connected) {
6551                 mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
6552             } else {
6553                 mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
6554             }
6555             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6556         }
6557     }
6558 
6559     @GuardedBy("this")
stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)6560     void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
6561         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
6562             if (i == except) {
6563                 continue;
6564             }
6565             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
6566                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
6567             }
6568         }
6569     }
6570 
fixPhoneServiceState(int state, int signalBin)6571     private int fixPhoneServiceState(int state, int signalBin) {
6572         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
6573             // In this case we will always be STATE_OUT_OF_SERVICE, so need
6574             // to infer that we are scanning from other data.
6575             if (state == ServiceState.STATE_OUT_OF_SERVICE
6576                     && signalBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
6577                 state = ServiceState.STATE_IN_SERVICE;
6578             }
6579         }
6580 
6581         return state;
6582     }
6583 
6584     @GuardedBy("this")
updateAllPhoneStateLocked(int state, int simState, int strengthBin, long elapsedRealtimeMs, long uptimeMs)6585     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin,
6586             long elapsedRealtimeMs, long uptimeMs) {
6587         boolean scanning = false;
6588         boolean newHistory = false;
6589 
6590         mPhoneServiceStateRaw = state;
6591         mPhoneSimStateRaw = simState;
6592         mPhoneSignalStrengthBinRaw = strengthBin;
6593 
6594         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
6595             // In this case we will always be STATE_OUT_OF_SERVICE, so need
6596             // to infer that we are scanning from other data.
6597             if (state == ServiceState.STATE_OUT_OF_SERVICE
6598                     && strengthBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
6599                 state = ServiceState.STATE_IN_SERVICE;
6600             }
6601         }
6602 
6603         // If the phone is powered off, stop all timers.
6604         if (state == ServiceState.STATE_POWER_OFF) {
6605             strengthBin = -1;
6606 
6607         // If we are in service, make sure the correct signal string timer is running.
6608         } else if (state == ServiceState.STATE_IN_SERVICE) {
6609             // Bin will be changed below.
6610 
6611         // If we're out of service, we are in the lowest signal strength
6612         // bin and have the scanning bit set.
6613         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
6614             scanning = true;
6615             strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
6616             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
6617                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
6618                 newHistory = true;
6619                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
6620                         + Integer.toHexString(mHistoryCur.states));
6621                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs);
6622                 FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
6623                         simState, strengthBin);
6624             }
6625         }
6626 
6627         if (!scanning) {
6628             // If we are no longer scanning, then stop the scanning timer.
6629             if (mPhoneSignalScanningTimer.isRunningLocked()) {
6630                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
6631                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
6632                         + Integer.toHexString(mHistoryCur.states));
6633                 newHistory = true;
6634                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
6635                 FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
6636                         simState, strengthBin);
6637             }
6638         }
6639 
6640         if (mPhoneServiceState != state) {
6641             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
6642                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
6643             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
6644                     + Integer.toHexString(mHistoryCur.states));
6645             newHistory = true;
6646             mPhoneServiceState = state;
6647         }
6648 
6649         if (mPhoneSignalStrengthBin != strengthBin) {
6650             if (mPhoneSignalStrengthBin >= 0) {
6651                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
6652                         elapsedRealtimeMs);
6653             }
6654             if (strengthBin >= 0) {
6655                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
6656                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
6657                 }
6658                 mHistoryCur.states =
6659                         (mHistoryCur.states & ~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
6660                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
6661                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
6662                         + Integer.toHexString(mHistoryCur.states));
6663                 newHistory = true;
6664                 FrameworkStatsLog.write(
6665                         FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
6666             } else {
6667                 stopAllPhoneSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
6668             }
6669             mPhoneSignalStrengthBin = strengthBin;
6670         }
6671 
6672         if (newHistory) {
6673             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6674         }
6675     }
6676 
6677     /**
6678      * Telephony stack updates the phone state.
6679      * @param state phone state from ServiceState.getState()
6680      */
6681     @GuardedBy("this")
notePhoneStateLocked(int state, int simState)6682     public void notePhoneStateLocked(int state, int simState) {
6683         notePhoneStateLocked(state, simState, mClock.elapsedRealtime(), mClock.uptimeMillis());
6684     }
6685 
6686     @GuardedBy("this")
notePhoneStateLocked(int state, int simState, long elapsedRealtimeMs, long uptimeMs)6687     public void notePhoneStateLocked(int state, int simState,
6688             long elapsedRealtimeMs, long uptimeMs) {
6689         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw,
6690                 elapsedRealtimeMs, uptimeMs);
6691     }
6692 
6693     @UnsupportedAppUsage
6694     @GuardedBy("this")
notePhoneSignalStrengthLocked(SignalStrength signalStrength)6695     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
6696         notePhoneSignalStrengthLocked(signalStrength,
6697                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6698     }
6699 
6700     @GuardedBy("this")
notePhoneSignalStrengthLocked(SignalStrength signalStrength, long elapsedRealtimeMs, long uptimeMs)6701     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
6702             long elapsedRealtimeMs, long uptimeMs) {
6703         final int overallSignalStrength = signalStrength.getLevel();
6704         final SparseIntArray perRatSignalStrength = new SparseIntArray(
6705                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT);
6706 
6707         // Extract signal strength level for each RAT.
6708         final List<CellSignalStrength> cellSignalStrengths =
6709                 signalStrength.getCellSignalStrengths();
6710         final int size = cellSignalStrengths.size();
6711         for (int i = 0; i < size; i++) {
6712             CellSignalStrength cellSignalStrength = cellSignalStrengths.get(i);
6713             // Map each CellSignalStrength to a BatteryStats.RadioAccessTechnology
6714             final int ratType;
6715             final int level;
6716             if (cellSignalStrength instanceof CellSignalStrengthNr) {
6717                 ratType = RADIO_ACCESS_TECHNOLOGY_NR;
6718                 level = cellSignalStrength.getLevel();
6719             } else if (cellSignalStrength instanceof CellSignalStrengthLte) {
6720                 ratType = RADIO_ACCESS_TECHNOLOGY_LTE;
6721                 level = cellSignalStrength.getLevel();
6722             } else {
6723                 ratType = RADIO_ACCESS_TECHNOLOGY_OTHER;
6724                 level = cellSignalStrength.getLevel();
6725             }
6726 
6727             // According to SignalStrength#getCellSignalStrengths(), multiple of the same
6728             // cellSignalStrength can be present. Just take the highest level one for each RAT.
6729             if (perRatSignalStrength.get(ratType, -1) < level) {
6730                 perRatSignalStrength.put(ratType, level);
6731             }
6732         }
6733 
6734         notePhoneSignalStrengthLocked(overallSignalStrength, perRatSignalStrength,
6735                 elapsedRealtimeMs, uptimeMs);
6736     }
6737 
6738     /**
6739      * Note phone signal strength change, including per RAT signal strength.
6740      *
6741      * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
6742      * @param perRatSignalStrength signal strength of available RATs
6743      */
6744     @GuardedBy("this")
notePhoneSignalStrengthLocked(int signalStrength, SparseIntArray perRatSignalStrength)6745     public void notePhoneSignalStrengthLocked(int signalStrength,
6746             SparseIntArray perRatSignalStrength) {
6747         notePhoneSignalStrengthLocked(signalStrength, perRatSignalStrength,
6748                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6749     }
6750 
6751     /**
6752      * Note phone signal strength change, including per RAT signal strength.
6753      *
6754      * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
6755      * @param perRatSignalStrength signal strength of available RATs
6756      */
6757     @GuardedBy("this")
notePhoneSignalStrengthLocked(int signalStrength, SparseIntArray perRatSignalStrength, long elapsedRealtimeMs, long uptimeMs)6758     public void notePhoneSignalStrengthLocked(int signalStrength,
6759             SparseIntArray perRatSignalStrength,
6760             long elapsedRealtimeMs, long uptimeMs) {
6761         // Note each RAT's signal strength.
6762         final int size = perRatSignalStrength.size();
6763         for (int i = 0; i < size; i++) {
6764             final int rat = perRatSignalStrength.keyAt(i);
6765             final int ratSignalStrength = perRatSignalStrength.valueAt(i);
6766             getRatBatteryStatsLocked(rat).noteSignalStrength(ratSignalStrength, elapsedRealtimeMs);
6767         }
6768         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, signalStrength,
6769                 elapsedRealtimeMs, uptimeMs);
6770     }
6771 
6772     @UnsupportedAppUsage
6773     @GuardedBy("this")
notePhoneDataConnectionStateLocked(@etworkType int dataType, boolean hasData, @RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency)6774     public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
6775             @RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency) {
6776         notePhoneDataConnectionStateLocked(dataType, hasData, serviceType, nrFrequency,
6777                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6778     }
6779 
6780     @GuardedBy("this")
notePhoneDataConnectionStateLocked(@etworkType int dataType, boolean hasData, @RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency, long elapsedRealtimeMs, long uptimeMs)6781     public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
6782             @RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency,
6783             long elapsedRealtimeMs, long uptimeMs) {
6784         // BatteryStats uses 0 to represent no network type.
6785         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
6786         // Unknown is included in DATA_CONNECTION_OTHER.
6787         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
6788         if (hasData) {
6789             if (dataType > 0 && dataType <= TelephonyManager.getAllNetworkTypes().length) {
6790                 bin = dataType;
6791             } else {
6792                 switch (serviceType) {
6793                     case ServiceState.STATE_OUT_OF_SERVICE:
6794                         bin = DATA_CONNECTION_OUT_OF_SERVICE;
6795                         break;
6796                     case ServiceState.STATE_EMERGENCY_ONLY:
6797                         bin = DATA_CONNECTION_EMERGENCY_SERVICE;
6798                         break;
6799                     default:
6800                         bin = DATA_CONNECTION_OTHER;
6801                         break;
6802                 }
6803             }
6804         }
6805 
6806         final int newRat = mapNetworkTypeToRadioAccessTechnology(bin);
6807         if (newRat == RADIO_ACCESS_TECHNOLOGY_NR) {
6808             // Note possible frequency change for the NR RAT.
6809             getRatBatteryStatsLocked(newRat).noteFrequencyRange(nrFrequency, elapsedRealtimeMs);
6810         }
6811 
6812         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
6813         if (mPhoneDataConnectionType != bin) {
6814             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
6815                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
6816             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
6817                     + Integer.toHexString(mHistoryCur.states));
6818             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6819             if (mPhoneDataConnectionType >= 0) {
6820                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
6821                         elapsedRealtimeMs);
6822             }
6823             mPhoneDataConnectionType = bin;
6824             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs);
6825 
6826             if (mActiveRat != newRat) {
6827                 getRatBatteryStatsLocked(mActiveRat).noteActive(false, elapsedRealtimeMs);
6828                 mActiveRat = newRat;
6829             }
6830             final boolean modemActive = mMobileRadioActiveTimer.isRunningLocked();
6831             getRatBatteryStatsLocked(newRat).noteActive(modemActive, elapsedRealtimeMs);
6832         }
6833     }
6834 
6835     @RadioAccessTechnology
mapNetworkTypeToRadioAccessTechnology(@etworkType int dataType)6836     private static int mapNetworkTypeToRadioAccessTechnology(@NetworkType int dataType) {
6837         switch (dataType) {
6838             case TelephonyManager.NETWORK_TYPE_NR:
6839                 return RADIO_ACCESS_TECHNOLOGY_NR;
6840             case TelephonyManager.NETWORK_TYPE_LTE:
6841                 return RADIO_ACCESS_TECHNOLOGY_LTE;
6842             case TelephonyManager.NETWORK_TYPE_UNKNOWN: //fallthrough
6843             case TelephonyManager.NETWORK_TYPE_GPRS: //fallthrough
6844             case TelephonyManager.NETWORK_TYPE_EDGE: //fallthrough
6845             case TelephonyManager.NETWORK_TYPE_UMTS: //fallthrough
6846             case TelephonyManager.NETWORK_TYPE_CDMA: //fallthrough
6847             case TelephonyManager.NETWORK_TYPE_EVDO_0: //fallthrough
6848             case TelephonyManager.NETWORK_TYPE_EVDO_A: //fallthrough
6849             case TelephonyManager.NETWORK_TYPE_1xRTT: //fallthrough
6850             case TelephonyManager.NETWORK_TYPE_HSDPA: //fallthrough
6851             case TelephonyManager.NETWORK_TYPE_HSUPA: //fallthrough
6852             case TelephonyManager.NETWORK_TYPE_HSPA: //fallthrough
6853             case TelephonyManager.NETWORK_TYPE_IDEN: //fallthrough
6854             case TelephonyManager.NETWORK_TYPE_EVDO_B: //fallthrough
6855             case TelephonyManager.NETWORK_TYPE_EHRPD: //fallthrough
6856             case TelephonyManager.NETWORK_TYPE_HSPAP: //fallthrough
6857             case TelephonyManager.NETWORK_TYPE_GSM: //fallthrough
6858             case TelephonyManager.NETWORK_TYPE_TD_SCDMA: //fallthrough
6859             case TelephonyManager.NETWORK_TYPE_IWLAN: //fallthrough
6860                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6861             default:
6862                 Slog.w(TAG, "Unhandled NetworkType (" + dataType + "), mapping to OTHER");
6863                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6864         }
6865     }
6866 
6867     @RadioAccessTechnology
mapRadioAccessNetworkTypeToRadioAccessTechnology( @ccessNetworkConstants.RadioAccessNetworkType int dataType)6868     private static int mapRadioAccessNetworkTypeToRadioAccessTechnology(
6869             @AccessNetworkConstants.RadioAccessNetworkType int dataType) {
6870         switch (dataType) {
6871             case AccessNetworkConstants.AccessNetworkType.NGRAN:
6872                 return RADIO_ACCESS_TECHNOLOGY_NR;
6873             case AccessNetworkConstants.AccessNetworkType.EUTRAN:
6874                 return RADIO_ACCESS_TECHNOLOGY_LTE;
6875             case AccessNetworkConstants.AccessNetworkType.UNKNOWN: //fallthrough
6876             case AccessNetworkConstants.AccessNetworkType.GERAN: //fallthrough
6877             case AccessNetworkConstants.AccessNetworkType.UTRAN: //fallthrough
6878             case AccessNetworkConstants.AccessNetworkType.CDMA2000: //fallthrough
6879             case AccessNetworkConstants.AccessNetworkType.IWLAN:
6880                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6881             default:
6882                 Slog.w(TAG,
6883                         "Unhandled RadioAccessNetworkType (" + dataType + "), mapping to OTHER");
6884                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6885         }
6886     }
6887 
6888     @GuardedBy("this")
noteWifiOnLocked()6889     public void noteWifiOnLocked() {
6890         noteWifiOnLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
6891     }
6892 
6893     @GuardedBy("this")
noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs)6894     public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
6895         if (!mWifiOn) {
6896             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
6897             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
6898                     + Integer.toHexString(mHistoryCur.states));
6899             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6900             mWifiOn = true;
6901             mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
6902             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
6903         }
6904     }
6905 
6906     @GuardedBy("this")
noteWifiOffLocked()6907     public void noteWifiOffLocked() {
6908         noteWifiOffLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
6909     }
6910 
6911     @GuardedBy("this")
noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs)6912     public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
6913         if (mWifiOn) {
6914             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
6915             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
6916                     + Integer.toHexString(mHistoryCur.states));
6917             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6918             mWifiOn = false;
6919             mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
6920             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
6921         }
6922     }
6923 
6924     @UnsupportedAppUsage
6925     @GuardedBy("this")
noteAudioOnLocked(int uid)6926     public void noteAudioOnLocked(int uid) {
6927         noteAudioOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6928     }
6929 
6930     @GuardedBy("this")
noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6931     public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6932         uid = mapUid(uid);
6933         if (mAudioOnNesting == 0) {
6934             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
6935             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
6936                     + Integer.toHexString(mHistoryCur.states));
6937             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6938             mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
6939         }
6940         mAudioOnNesting++;
6941         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6942                 .noteAudioTurnedOnLocked(elapsedRealtimeMs);
6943     }
6944 
6945     @UnsupportedAppUsage
6946     @GuardedBy("this")
noteAudioOffLocked(int uid)6947     public void noteAudioOffLocked(int uid) {
6948         noteAudioOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6949     }
6950 
6951     @GuardedBy("this")
noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6952     public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6953         if (mAudioOnNesting == 0) {
6954             return;
6955         }
6956         uid = mapUid(uid);
6957         if (--mAudioOnNesting == 0) {
6958             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
6959             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
6960                     + Integer.toHexString(mHistoryCur.states));
6961             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6962             mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
6963         }
6964         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6965                 .noteAudioTurnedOffLocked(elapsedRealtimeMs);
6966     }
6967 
6968     @UnsupportedAppUsage
6969     @GuardedBy("this")
noteVideoOnLocked(int uid)6970     public void noteVideoOnLocked(int uid) {
6971         noteVideoOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6972     }
6973 
6974     @GuardedBy("this")
noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6975     public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6976         uid = mapUid(uid);
6977         if (mVideoOnNesting == 0) {
6978             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
6979             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
6980                     + Integer.toHexString(mHistoryCur.states));
6981             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6982             mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
6983         }
6984         mVideoOnNesting++;
6985         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6986                 .noteVideoTurnedOnLocked(elapsedRealtimeMs);
6987     }
6988 
6989     @UnsupportedAppUsage
6990     @GuardedBy("this")
noteVideoOffLocked(int uid)6991     public void noteVideoOffLocked(int uid) {
6992         noteVideoOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6993     }
6994 
6995     @GuardedBy("this")
noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6996     public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6997         if (mVideoOnNesting == 0) {
6998             return;
6999         }
7000         uid = mapUid(uid);
7001         if (--mVideoOnNesting == 0) {
7002             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
7003             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
7004                     + Integer.toHexString(mHistoryCur.states));
7005             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7006             mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
7007         }
7008         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7009                 .noteVideoTurnedOffLocked(elapsedRealtimeMs);
7010     }
7011 
7012     @GuardedBy("this")
noteResetAudioLocked()7013     public void noteResetAudioLocked() {
7014         noteResetAudioLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
7015     }
7016 
7017     @GuardedBy("this")
noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs)7018     public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
7019         if (mAudioOnNesting > 0) {
7020             mAudioOnNesting = 0;
7021             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
7022             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
7023                     + Integer.toHexString(mHistoryCur.states));
7024             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7025             mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7026             for (int i=0; i<mUidStats.size(); i++) {
7027                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
7028                 uid.noteResetAudioLocked(elapsedRealtimeMs);
7029             }
7030         }
7031     }
7032 
7033     @GuardedBy("this")
noteResetVideoLocked()7034     public void noteResetVideoLocked() {
7035         noteResetVideoLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
7036     }
7037 
7038     @GuardedBy("this")
noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs)7039     public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
7040         if (mVideoOnNesting > 0) {
7041             mVideoOnNesting = 0;
7042             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
7043             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
7044                     + Integer.toHexString(mHistoryCur.states));
7045             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7046             mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7047             for (int i=0; i<mUidStats.size(); i++) {
7048                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
7049                 uid.noteResetVideoLocked(elapsedRealtimeMs);
7050             }
7051         }
7052     }
7053 
7054     @GuardedBy("this")
noteActivityResumedLocked(int uid)7055     public void noteActivityResumedLocked(int uid) {
7056         noteActivityResumedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7057     }
7058 
7059     @GuardedBy("this")
noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7060     public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7061         uid = mapUid(uid);
7062         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7063                 .noteActivityResumedLocked(elapsedRealtimeMs);
7064     }
7065 
7066     @GuardedBy("this")
noteActivityPausedLocked(int uid)7067     public void noteActivityPausedLocked(int uid) {
7068         noteActivityPausedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7069     }
7070 
7071     @GuardedBy("this")
noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7072     public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7073         uid = mapUid(uid);
7074         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7075                 .noteActivityPausedLocked(elapsedRealtimeMs);
7076     }
7077 
7078     @GuardedBy("this")
noteVibratorOnLocked(int uid, long durationMillis)7079     public void noteVibratorOnLocked(int uid, long durationMillis) {
7080         noteVibratorOnLocked(uid, durationMillis,
7081                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7082     }
7083 
7084     @GuardedBy("this")
noteVibratorOnLocked(int uid, long durationMillis, long elapsedRealtimeMs, long uptimeMs)7085     public void noteVibratorOnLocked(int uid, long durationMillis,
7086             long elapsedRealtimeMs, long uptimeMs) {
7087         uid = mapUid(uid);
7088         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7089                 .noteVibratorOnLocked(durationMillis, elapsedRealtimeMs);
7090     }
7091 
7092     @GuardedBy("this")
noteVibratorOffLocked(int uid)7093     public void noteVibratorOffLocked(int uid) {
7094         noteVibratorOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7095     }
7096 
7097     @GuardedBy("this")
noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7098     public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7099         uid = mapUid(uid);
7100         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7101                 .noteVibratorOffLocked(elapsedRealtimeMs);
7102     }
7103 
7104     @GuardedBy("this")
noteFlashlightOnLocked(int uid)7105     public void noteFlashlightOnLocked(int uid) {
7106         noteFlashlightOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7107     }
7108 
7109     @GuardedBy("this")
noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7110     public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7111         uid = mapUid(uid);
7112         if (mFlashlightOnNesting++ == 0) {
7113             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
7114             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
7115                     + Integer.toHexString(mHistoryCur.states2));
7116             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7117             mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
7118         }
7119         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7120                 .noteFlashlightTurnedOnLocked(elapsedRealtimeMs);
7121     }
7122 
7123     @GuardedBy("this")
noteFlashlightOffLocked(int uid)7124     public void noteFlashlightOffLocked(int uid) {
7125         noteFlashlightOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7126     }
7127 
7128     @GuardedBy("this")
noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7129     public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7130         if (mFlashlightOnNesting == 0) {
7131             return;
7132         }
7133         uid = mapUid(uid);
7134         if (--mFlashlightOnNesting == 0) {
7135             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
7136             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
7137                     + Integer.toHexString(mHistoryCur.states2));
7138             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7139             mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
7140         }
7141         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7142                 .noteFlashlightTurnedOffLocked(elapsedRealtimeMs);
7143     }
7144 
7145     @GuardedBy("this")
noteCameraOnLocked(int uid)7146     public void noteCameraOnLocked(int uid) {
7147         noteCameraOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7148     }
7149 
7150     @GuardedBy("this")
noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7151     public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7152         uid = mapUid(uid);
7153         if (mCameraOnNesting++ == 0) {
7154             mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
7155             if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
7156                     + Integer.toHexString(mHistoryCur.states2));
7157             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7158             mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
7159         }
7160         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7161                 .noteCameraTurnedOnLocked(elapsedRealtimeMs);
7162     }
7163 
7164     @GuardedBy("this")
noteCameraOffLocked(int uid)7165     public void noteCameraOffLocked(int uid) {
7166         noteCameraOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7167     }
7168 
7169     @GuardedBy("this")
noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7170     public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7171         if (mCameraOnNesting == 0) {
7172             return;
7173         }
7174         uid = mapUid(uid);
7175         if (--mCameraOnNesting == 0) {
7176             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
7177             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
7178                     + Integer.toHexString(mHistoryCur.states2));
7179             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7180             mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
7181         }
7182         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7183                 .noteCameraTurnedOffLocked(elapsedRealtimeMs);
7184     }
7185 
7186     @GuardedBy("this")
noteResetCameraLocked()7187     public void noteResetCameraLocked() {
7188         noteResetCameraLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
7189     }
7190 
7191     @GuardedBy("this")
noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs)7192     public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
7193         if (mCameraOnNesting > 0) {
7194             mCameraOnNesting = 0;
7195             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
7196             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
7197                     + Integer.toHexString(mHistoryCur.states2));
7198             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7199             mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7200             for (int i=0; i<mUidStats.size(); i++) {
7201                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
7202                 uid.noteResetCameraLocked(elapsedRealtimeMs);
7203             }
7204         }
7205     }
7206 
7207     @GuardedBy("this")
noteResetFlashlightLocked()7208     public void noteResetFlashlightLocked() {
7209         noteResetFlashlightLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
7210     }
7211 
7212     @GuardedBy("this")
noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs)7213     public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
7214         if (mFlashlightOnNesting > 0) {
7215             mFlashlightOnNesting = 0;
7216             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
7217             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
7218                     + Integer.toHexString(mHistoryCur.states2));
7219             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7220             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7221             for (int i=0; i<mUidStats.size(); i++) {
7222                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
7223                 uid.noteResetFlashlightLocked(elapsedRealtimeMs);
7224             }
7225         }
7226     }
7227 
7228     @GuardedBy("this")
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)7229     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
7230             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
7231         if (workChain != null) {
7232             uid = workChain.getAttributionUid();
7233         }
7234         uid = mapUid(uid);
7235         if (mBluetoothScanNesting == 0) {
7236             mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
7237             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
7238                     + Integer.toHexString(mHistoryCur.states2));
7239             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7240             mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
7241         }
7242         mBluetoothScanNesting++;
7243         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7244                 .noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized);
7245     }
7246 
7247     @GuardedBy("this")
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)7248     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
7249         noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
7250                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7251     }
7252 
7253     @GuardedBy("this")
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)7254     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
7255             long elapsedRealtimeMs, long uptimeMs) {
7256         final int N = ws.size();
7257         for (int i = 0; i < N; i++) {
7258             noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized,
7259                     elapsedRealtimeMs, uptimeMs);
7260         }
7261 
7262         final List<WorkChain> workChains = ws.getWorkChains();
7263         if (workChains != null) {
7264             for (int i = 0; i < workChains.size(); ++i) {
7265                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized,
7266                         elapsedRealtimeMs, uptimeMs);
7267             }
7268         }
7269     }
7270 
7271     @GuardedBy("this")
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)7272     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
7273             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
7274         if (workChain != null) {
7275             uid = workChain.getAttributionUid();
7276         }
7277         uid = mapUid(uid);
7278         mBluetoothScanNesting--;
7279         if (mBluetoothScanNesting == 0) {
7280             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
7281             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
7282                     + Integer.toHexString(mHistoryCur.states2));
7283             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7284             mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
7285         }
7286         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7287                 .noteBluetoothScanStoppedLocked(elapsedRealtimeMs, isUnoptimized);
7288     }
7289 
7290     @GuardedBy("this")
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)7291     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
7292         noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
7293                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7294     }
7295 
7296     @GuardedBy("this")
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)7297     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
7298             long elapsedRealtimeMs, long uptimeMs) {
7299         final int N = ws.size();
7300         for (int i = 0; i < N; i++) {
7301             noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized,
7302                     elapsedRealtimeMs, uptimeMs);
7303         }
7304 
7305         final List<WorkChain> workChains = ws.getWorkChains();
7306         if (workChains != null) {
7307             for (int i = 0; i < workChains.size(); ++i) {
7308                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized,
7309                         elapsedRealtimeMs, uptimeMs);
7310             }
7311         }
7312     }
7313 
7314     @GuardedBy("this")
noteResetBluetoothScanLocked()7315     public void noteResetBluetoothScanLocked() {
7316         noteResetBluetoothScanLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
7317     }
7318 
7319     @GuardedBy("this")
noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs)7320     public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
7321         if (mBluetoothScanNesting > 0) {
7322             mBluetoothScanNesting = 0;
7323             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
7324             if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
7325                     + Integer.toHexString(mHistoryCur.states2));
7326             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7327             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7328             for (int i=0; i<mUidStats.size(); i++) {
7329                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
7330                 uid.noteResetBluetoothScanLocked(elapsedRealtimeMs);
7331             }
7332         }
7333     }
7334 
7335     @GuardedBy("this")
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)7336     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
7337         noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
7338                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7339     }
7340 
7341     @GuardedBy("this")
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults, long elapsedRealtimeMs, long uptimeMs)7342     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults,
7343             long elapsedRealtimeMs, long uptimeMs) {
7344         final int N = ws.size();
7345         for (int i = 0; i < N; i++) {
7346             int uid = mapUid(ws.getUid(i));
7347             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7348                     .noteBluetoothScanResultsLocked(numNewResults);
7349         }
7350 
7351         final List<WorkChain> workChains = ws.getWorkChains();
7352         if (workChains != null) {
7353             for (int i = 0; i < workChains.size(); ++i) {
7354                 final WorkChain wc = workChains.get(i);
7355                 int uid = mapUid(wc.getAttributionUid());
7356                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7357                         .noteBluetoothScanResultsLocked(numNewResults);
7358             }
7359         }
7360     }
7361 
7362     @GuardedBy("this")
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)7363     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
7364             final long uptimeMillis, int uid) {
7365         uid = mapUid(uid);
7366         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
7367                 uid);
7368         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
7369     }
7370 
7371     @GuardedBy("this")
noteWifiRadioPowerState(int powerState, long timestampNs, int uid)7372     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
7373         noteWifiRadioPowerState(powerState, timestampNs, uid,
7374                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7375     }
7376 
7377     @GuardedBy("this")
noteWifiRadioPowerState(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)7378     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid,
7379             long elapsedRealtimeMs, long uptimeMs) {
7380         if (mWifiRadioPowerState != powerState) {
7381             final boolean active =
7382                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
7383                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
7384             if (active) {
7385                 if (uid > 0) {
7386                     noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
7387                 }
7388                 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
7389                 mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
7390             } else {
7391                 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
7392                 mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000));
7393             }
7394             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
7395                     + Integer.toHexString(mHistoryCur.states));
7396             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7397             mWifiRadioPowerState = powerState;
7398         }
7399     }
7400 
7401     @GuardedBy("this")
noteWifiRunningLocked(WorkSource ws)7402     public void noteWifiRunningLocked(WorkSource ws) {
7403         noteWifiRunningLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis());
7404     }
7405 
7406     @GuardedBy("this")
noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7407     public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
7408         if (!mGlobalWifiRunning) {
7409             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
7410             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
7411                     + Integer.toHexString(mHistoryCur.states));
7412             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7413             mGlobalWifiRunning = true;
7414             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
7415             int N = ws.size();
7416             for (int i=0; i<N; i++) {
7417                 int uid = mapUid(ws.getUid(i));
7418                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7419                         .noteWifiRunningLocked(elapsedRealtimeMs);
7420             }
7421 
7422             List<WorkChain> workChains = ws.getWorkChains();
7423             if (workChains != null) {
7424                 for (int i = 0; i < workChains.size(); ++i) {
7425                     int uid = mapUid(workChains.get(i).getAttributionUid());
7426                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7427                             .noteWifiRunningLocked(elapsedRealtimeMs);
7428                 }
7429             }
7430 
7431             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
7432         } else {
7433             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
7434         }
7435     }
7436 
7437     @GuardedBy("this")
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs)7438     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
7439         noteWifiRunningChangedLocked(oldWs, newWs,
7440                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7441     }
7442 
7443     @GuardedBy("this")
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)7444     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs,
7445             long elapsedRealtimeMs, long uptimeMs) {
7446         if (mGlobalWifiRunning) {
7447             int N = oldWs.size();
7448             for (int i=0; i<N; i++) {
7449                 int uid = mapUid(oldWs.getUid(i));
7450                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7451                         .noteWifiStoppedLocked(elapsedRealtimeMs);
7452             }
7453 
7454             List<WorkChain> workChains = oldWs.getWorkChains();
7455             if (workChains != null) {
7456                 for (int i = 0; i < workChains.size(); ++i) {
7457                     int uid = mapUid(workChains.get(i).getAttributionUid());
7458                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7459                             .noteWifiStoppedLocked(elapsedRealtimeMs);
7460                 }
7461             }
7462 
7463             N = newWs.size();
7464             for (int i=0; i<N; i++) {
7465                 int uid = mapUid(newWs.getUid(i));
7466                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7467                         .noteWifiRunningLocked(elapsedRealtimeMs);
7468             }
7469 
7470             workChains = newWs.getWorkChains();
7471             if (workChains != null) {
7472                 for (int i = 0; i < workChains.size(); ++i) {
7473                     int uid = mapUid(workChains.get(i).getAttributionUid());
7474                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7475                             .noteWifiRunningLocked(elapsedRealtimeMs);
7476                 }
7477             }
7478         } else {
7479             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
7480         }
7481     }
7482 
7483     @GuardedBy("this")
noteWifiStoppedLocked(WorkSource ws)7484     public void noteWifiStoppedLocked(WorkSource ws) {
7485         noteWifiStoppedLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis());
7486     }
7487 
7488     @GuardedBy("this")
noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7489     public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
7490         if (mGlobalWifiRunning) {
7491             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
7492             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
7493                     + Integer.toHexString(mHistoryCur.states));
7494             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7495             mGlobalWifiRunning = false;
7496             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
7497             int N = ws.size();
7498             for (int i=0; i<N; i++) {
7499                 int uid = mapUid(ws.getUid(i));
7500                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7501                         .noteWifiStoppedLocked(elapsedRealtimeMs);
7502             }
7503 
7504             List<WorkChain> workChains = ws.getWorkChains();
7505             if (workChains != null) {
7506                 for (int i = 0; i < workChains.size(); ++i) {
7507                     int uid = mapUid(workChains.get(i).getAttributionUid());
7508                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7509                             .noteWifiStoppedLocked(elapsedRealtimeMs);
7510                 }
7511             }
7512 
7513             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
7514         } else {
7515             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
7516         }
7517     }
7518 
7519     @GuardedBy("this")
noteWifiStateLocked(int wifiState, String accessPoint)7520     public void noteWifiStateLocked(int wifiState, String accessPoint) {
7521         noteWifiStateLocked(wifiState, accessPoint, mClock.elapsedRealtime());
7522     }
7523 
7524     @GuardedBy("this")
noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs)7525     public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) {
7526         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
7527         if (mWifiState != wifiState) {
7528             if (mWifiState >= 0) {
7529                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtimeMs);
7530             }
7531             mWifiState = wifiState;
7532             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs);
7533             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
7534         }
7535     }
7536 
7537     @GuardedBy("this")
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth)7538     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
7539         noteWifiSupplicantStateChangedLocked(supplState, failedAuth,
7540                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7541     }
7542 
7543     @GuardedBy("this")
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth, long elapsedRealtimeMs, long uptimeMs)7544     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth,
7545             long elapsedRealtimeMs, long uptimeMs) {
7546         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
7547         if (mWifiSupplState != supplState) {
7548             if (mWifiSupplState >= 0) {
7549                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtimeMs);
7550             }
7551             mWifiSupplState = supplState;
7552             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
7553             mHistoryCur.states2 =
7554                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
7555                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
7556             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
7557                     + Integer.toHexString(mHistoryCur.states2));
7558             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7559         }
7560     }
7561 
7562     @GuardedBy("this")
stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)7563     void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
7564         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7565             if (i == except) {
7566                 continue;
7567             }
7568             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
7569                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
7570             }
7571         }
7572     }
7573 
7574     @GuardedBy("this")
noteWifiRssiChangedLocked(int newRssi)7575     public void noteWifiRssiChangedLocked(int newRssi) {
7576         noteWifiRssiChangedLocked(newRssi, mClock.elapsedRealtime(), mClock.uptimeMillis());
7577     }
7578 
7579     @GuardedBy("this")
noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs)7580     public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) {
7581         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
7582         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
7583         if (mWifiSignalStrengthBin != strengthBin) {
7584             if (mWifiSignalStrengthBin >= 0) {
7585                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
7586                         elapsedRealtimeMs);
7587             }
7588             if (strengthBin >= 0) {
7589                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
7590                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
7591                 }
7592                 mHistoryCur.states2 =
7593                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
7594                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
7595                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
7596                         + Integer.toHexString(mHistoryCur.states2));
7597                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7598             } else {
7599                 stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
7600             }
7601             mWifiSignalStrengthBin = strengthBin;
7602         }
7603     }
7604 
7605     int mWifiFullLockNesting = 0;
7606 
7607     @UnsupportedAppUsage
7608     @GuardedBy("this")
noteFullWifiLockAcquiredLocked(int uid)7609     public void noteFullWifiLockAcquiredLocked(int uid) {
7610         noteFullWifiLockAcquiredLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7611     }
7612 
7613     @GuardedBy("this")
noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7614     public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7615         if (mWifiFullLockNesting == 0) {
7616             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
7617             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
7618                     + Integer.toHexString(mHistoryCur.states));
7619             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7620         }
7621         mWifiFullLockNesting++;
7622         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7623                 .noteFullWifiLockAcquiredLocked(elapsedRealtimeMs);
7624     }
7625 
7626     @UnsupportedAppUsage
7627     @GuardedBy("this")
noteFullWifiLockReleasedLocked(int uid)7628     public void noteFullWifiLockReleasedLocked(int uid) {
7629         noteFullWifiLockReleasedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7630     }
7631 
7632     @GuardedBy("this")
noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7633     public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7634         mWifiFullLockNesting--;
7635         if (mWifiFullLockNesting == 0) {
7636             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
7637             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
7638                     + Integer.toHexString(mHistoryCur.states));
7639             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7640         }
7641         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7642                 .noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
7643     }
7644 
7645     int mWifiScanNesting = 0;
7646 
7647     @GuardedBy("this")
noteWifiScanStartedLocked(int uid)7648     public void noteWifiScanStartedLocked(int uid) {
7649         noteWifiScanStartedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7650     }
7651 
7652     @GuardedBy("this")
noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7653     public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7654         if (mWifiScanNesting == 0) {
7655             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
7656             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
7657                     + Integer.toHexString(mHistoryCur.states));
7658             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7659         }
7660         mWifiScanNesting++;
7661         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7662                 .noteWifiScanStartedLocked(elapsedRealtimeMs);
7663     }
7664 
7665     @GuardedBy("this")
noteWifiScanStoppedLocked(int uid)7666     public void noteWifiScanStoppedLocked(int uid) {
7667         noteWifiScanStoppedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7668     }
7669 
7670     @GuardedBy("this")
noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7671     public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7672         mWifiScanNesting--;
7673         if (mWifiScanNesting == 0) {
7674             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
7675             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
7676                     + Integer.toHexString(mHistoryCur.states));
7677             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7678         }
7679         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7680                 .noteWifiScanStoppedLocked(elapsedRealtimeMs);
7681     }
7682 
noteWifiBatchedScanStartedLocked(int uid, int csph)7683     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
7684         noteWifiBatchedScanStartedLocked(uid, csph,
7685                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7686     }
7687 
noteWifiBatchedScanStartedLocked(int uid, int csph, long elapsedRealtimeMs, long uptimeMs)7688     public void noteWifiBatchedScanStartedLocked(int uid, int csph,
7689             long elapsedRealtimeMs, long uptimeMs) {
7690         uid = mapUid(uid);
7691         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7692                 .noteWifiBatchedScanStartedLocked(csph, elapsedRealtimeMs);
7693     }
7694 
noteWifiBatchedScanStoppedLocked(int uid)7695     public void noteWifiBatchedScanStoppedLocked(int uid) {
7696         noteWifiBatchedScanStoppedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7697     }
7698 
noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7699     public void noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7700         uid = mapUid(uid);
7701         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7702                 .noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs);
7703     }
7704 
7705     int mWifiMulticastNesting = 0;
7706 
7707     @GuardedBy("this")
7708     @UnsupportedAppUsage
noteWifiMulticastEnabledLocked(int uid)7709     public void noteWifiMulticastEnabledLocked(int uid) {
7710         noteWifiMulticastEnabledLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7711     }
7712 
7713     @GuardedBy("this")
noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7714     public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7715         uid = mapUid(uid);
7716         if (mWifiMulticastNesting == 0) {
7717             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
7718             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
7719                     + Integer.toHexString(mHistoryCur.states));
7720             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7721 
7722             // Start Wifi Multicast overall timer
7723             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
7724                 if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
7725                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
7726             }
7727         }
7728         mWifiMulticastNesting++;
7729         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7730                 .noteWifiMulticastEnabledLocked(elapsedRealtimeMs);
7731     }
7732 
7733     @UnsupportedAppUsage
7734     @GuardedBy("this")
noteWifiMulticastDisabledLocked(int uid)7735     public void noteWifiMulticastDisabledLocked(int uid) {
7736         noteWifiMulticastDisabledLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7737     }
7738 
7739     @GuardedBy("this")
noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7740     public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7741         uid = mapUid(uid);
7742         mWifiMulticastNesting--;
7743         if (mWifiMulticastNesting == 0) {
7744             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
7745             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
7746                     + Integer.toHexString(mHistoryCur.states));
7747             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
7748 
7749             // Stop Wifi Multicast overall timer
7750             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
7751                 if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
7752                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
7753             }
7754         }
7755         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7756                 .noteWifiMulticastDisabledLocked(elapsedRealtimeMs);
7757     }
7758 
7759     @GuardedBy("this")
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws)7760     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
7761         noteFullWifiLockAcquiredFromSourceLocked(ws,
7762                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7763     }
7764 
7765     @GuardedBy("this")
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7766     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws,
7767             long elapsedRealtimeMs, long uptimeMs) {
7768         int N = ws.size();
7769         for (int i=0; i<N; i++) {
7770             final int uid = mapUid(ws.getUid(i));
7771             noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
7772         }
7773 
7774         final List<WorkChain> workChains = ws.getWorkChains();
7775         if (workChains != null) {
7776             for (int i = 0; i < workChains.size(); ++i) {
7777                 final WorkChain workChain = workChains.get(i);
7778                 final int uid = mapUid(workChain.getAttributionUid());
7779                 noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
7780             }
7781         }
7782     }
7783 
7784     @GuardedBy("this")
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws)7785     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
7786         noteFullWifiLockReleasedFromSourceLocked(ws,
7787                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7788     }
7789 
7790     @GuardedBy("this")
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7791     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws,
7792             long elapsedRealtimeMs, long uptimeMs) {
7793         int N = ws.size();
7794         for (int i=0; i<N; i++) {
7795             final int uid = mapUid(ws.getUid(i));
7796             noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
7797         }
7798 
7799         final List<WorkChain> workChains = ws.getWorkChains();
7800         if (workChains != null) {
7801             for (int i = 0; i < workChains.size(); ++i) {
7802                 final WorkChain workChain = workChains.get(i);
7803                 final int uid = mapUid(workChain.getAttributionUid());
7804                 noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
7805             }
7806         }
7807     }
7808 
7809     @GuardedBy("this")
noteWifiScanStartedFromSourceLocked(WorkSource ws)7810     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
7811         noteWifiScanStartedFromSourceLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis());
7812     }
7813 
7814     @GuardedBy("this")
noteWifiScanStartedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7815     public void noteWifiScanStartedFromSourceLocked(WorkSource ws,
7816             long elapsedRealtimeMs, long uptimeMs) {
7817         int N = ws.size();
7818         for (int i=0; i<N; i++) {
7819             final int uid = mapUid(ws.getUid(i));
7820             noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
7821         }
7822 
7823         final List<WorkChain> workChains = ws.getWorkChains();
7824         if (workChains != null) {
7825             for (int i = 0; i < workChains.size(); ++i) {
7826                 final WorkChain workChain = workChains.get(i);
7827                 final int uid = mapUid(workChain.getAttributionUid());
7828                 noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
7829             }
7830         }
7831     }
7832 
7833     @GuardedBy("this")
noteWifiScanStoppedFromSourceLocked(WorkSource ws)7834     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
7835         noteWifiScanStoppedFromSourceLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis());
7836     }
7837 
7838     @GuardedBy("this")
noteWifiScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7839     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws,
7840             long elapsedRealtimeMs, long uptimeMs) {
7841         int N = ws.size();
7842         for (int i=0; i<N; i++) {
7843             final int uid = mapUid(ws.getUid(i));
7844             noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
7845         }
7846 
7847         final List<WorkChain> workChains = ws.getWorkChains();
7848         if (workChains != null) {
7849             for (int i = 0; i < workChains.size(); ++i) {
7850                 final WorkChain workChain = workChains.get(i);
7851                 final int uid = mapUid(workChain.getAttributionUid());
7852                 noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
7853             }
7854         }
7855     }
7856 
7857     @GuardedBy("this")
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph)7858     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
7859         noteWifiBatchedScanStartedFromSourceLocked(ws, csph,
7860                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7861     }
7862 
7863     @GuardedBy("this")
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph, long elapsedRealtimeMs, long uptimeMs)7864     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph,
7865             long elapsedRealtimeMs, long uptimeMs) {
7866         int N = ws.size();
7867         for (int i=0; i<N; i++) {
7868             noteWifiBatchedScanStartedLocked(ws.getUid(i), csph, elapsedRealtimeMs, uptimeMs);
7869         }
7870 
7871         final List<WorkChain> workChains = ws.getWorkChains();
7872         if (workChains != null) {
7873             for (int i = 0; i < workChains.size(); ++i) {
7874                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph,
7875                         elapsedRealtimeMs, uptimeMs);
7876             }
7877         }
7878     }
7879 
7880     @GuardedBy("this")
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws)7881     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
7882         noteWifiBatchedScanStoppedFromSourceLocked(ws,
7883                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7884     }
7885 
7886     @GuardedBy("this")
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7887     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws,
7888             long elapsedRealtimeMs, long uptimeMs) {
7889         int N = ws.size();
7890         for (int i=0; i<N; i++) {
7891             noteWifiBatchedScanStoppedLocked(ws.getUid(i), elapsedRealtimeMs, uptimeMs);
7892         }
7893 
7894         final List<WorkChain> workChains = ws.getWorkChains();
7895         if (workChains != null) {
7896             for (int i = 0; i < workChains.size(); ++i) {
7897                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid(),
7898                         elapsedRealtimeMs, uptimeMs);
7899             }
7900         }
7901     }
7902 
includeInStringArray(String[] array, String str)7903     private static String[] includeInStringArray(String[] array, String str) {
7904         if (ArrayUtils.indexOf(array, str) >= 0) {
7905             return array;
7906         }
7907         String[] newArray = new String[array.length+1];
7908         System.arraycopy(array, 0, newArray, 0, array.length);
7909         newArray[array.length] = str;
7910         return newArray;
7911     }
7912 
excludeFromStringArray(String[] array, String str)7913     private static String[] excludeFromStringArray(String[] array, String str) {
7914         int index = ArrayUtils.indexOf(array, str);
7915         if (index >= 0) {
7916             String[] newArray = new String[array.length-1];
7917             if (index > 0) {
7918                 System.arraycopy(array, 0, newArray, 0, index);
7919             }
7920             if (index < array.length-1) {
7921                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
7922             }
7923             return newArray;
7924         }
7925         return array;
7926     }
7927 
7928     /** @hide */
noteNetworkInterfaceForTransports(String iface, int[] transportTypes)7929     public void noteNetworkInterfaceForTransports(String iface, int[] transportTypes) {
7930         if (TextUtils.isEmpty(iface)) return;
7931         final int displayTransport = NetworkCapabilitiesUtils.getDisplayTransport(transportTypes);
7932 
7933         synchronized (mModemNetworkLock) {
7934             if (displayTransport == TRANSPORT_CELLULAR) {
7935                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
7936                 if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
7937             } else {
7938                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
7939                 if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
7940             }
7941         }
7942 
7943         synchronized (mWifiNetworkLock) {
7944             if (displayTransport == TRANSPORT_WIFI) {
7945                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
7946                 if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
7947             } else {
7948                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
7949                 if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
7950             }
7951         }
7952     }
7953 
7954     /**
7955      * Records timing data related to an incoming Binder call in order to attribute
7956      * the power consumption to the calling app.
7957      */
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)7958     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
7959             Collection<BinderCallsStats.CallStat> callStats) {
7960         noteBinderCallStats(workSourceUid, incrementalCallCount, callStats,
7961                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7962     }
7963 
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats, long elapsedRealtimeMs, long uptimeMs)7964     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
7965             Collection<BinderCallsStats.CallStat> callStats,
7966             long elapsedRealtimeMs, long uptimeMs) {
7967         synchronized (this) {
7968             getUidStatsLocked(workSourceUid, elapsedRealtimeMs, uptimeMs)
7969                     .noteBinderCallStatsLocked(incrementalCallCount, callStats);
7970         }
7971     }
7972 
7973     /**
7974      * Takes note of native IDs of threads taking incoming binder calls. The CPU time
7975      * of these threads is attributed to the apps making those binder calls.
7976      */
noteBinderThreadNativeIds(int[] binderThreadNativeTids)7977     public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) {
7978         mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids);
7979     }
7980 
7981     /**
7982      * Estimates the proportion of system server CPU activity handling incoming binder calls
7983      * that can be attributed to each app
7984      */
7985     @VisibleForTesting
updateSystemServiceCallStats()7986     public void updateSystemServiceCallStats() {
7987         // Start off by computing the average duration of recorded binder calls,
7988         // regardless of which binder or transaction. We will use this as a fallback
7989         // for calls that were not sampled at all.
7990         int totalRecordedCallCount = 0;
7991         long totalRecordedCallTimeMicros = 0;
7992         for (int i = 0; i < mUidStats.size(); i++) {
7993             Uid uid = mUidStats.valueAt(i);
7994             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
7995             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
7996                 BinderCallStats stats = binderCallStats.valueAt(j);
7997                 totalRecordedCallCount += stats.recordedCallCount;
7998                 totalRecordedCallTimeMicros += stats.recordedCpuTimeMicros;
7999             }
8000         }
8001 
8002         long totalSystemServiceTimeMicros = 0;
8003 
8004         // For every UID, use recorded durations of sampled binder calls to estimate
8005         // the total time the system server spent handling requests from this UID.
8006         for (int i = 0; i < mUidStats.size(); i++) {
8007             Uid uid = mUidStats.valueAt(i);
8008 
8009             long totalTimeForUidUs = 0;
8010             int totalCallCountForUid = 0;
8011             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
8012             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
8013                 BinderCallStats stats = binderCallStats.valueAt(j);
8014                 totalCallCountForUid += stats.callCount;
8015                 if (stats.recordedCallCount > 0) {
8016                     totalTimeForUidUs +=
8017                             stats.callCount * stats.recordedCpuTimeMicros / stats.recordedCallCount;
8018                 } else if (totalRecordedCallCount > 0) {
8019                     totalTimeForUidUs +=
8020                             stats.callCount * totalRecordedCallTimeMicros / totalRecordedCallCount;
8021                 }
8022             }
8023 
8024             if (totalCallCountForUid < uid.mBinderCallCount && totalRecordedCallCount > 0) {
8025                 // Estimate remaining calls, which were not tracked because of binder call
8026                 // stats sampling
8027                 totalTimeForUidUs +=
8028                         (uid.mBinderCallCount - totalCallCountForUid) * totalRecordedCallTimeMicros
8029                                 / totalRecordedCallCount;
8030             }
8031 
8032             uid.mSystemServiceTimeUs = totalTimeForUidUs;
8033             totalSystemServiceTimeMicros += totalTimeForUidUs;
8034         }
8035 
8036         for (int i = 0; i < mUidStats.size(); i++) {
8037             Uid uid = mUidStats.valueAt(i);
8038             if (totalSystemServiceTimeMicros > 0) {
8039                 uid.mProportionalSystemServiceUsage =
8040                         (double) uid.mSystemServiceTimeUs / totalSystemServiceTimeMicros;
8041             } else {
8042                 uid.mProportionalSystemServiceUsage = 0;
8043             }
8044         }
8045     }
8046 
getWifiIfaces()8047     public String[] getWifiIfaces() {
8048         synchronized (mWifiNetworkLock) {
8049             return mWifiIfaces;
8050         }
8051     }
8052 
getMobileIfaces()8053     public String[] getMobileIfaces() {
8054         synchronized (mModemNetworkLock) {
8055             return mModemIfaces;
8056         }
8057     }
8058 
8059     @UnsupportedAppUsage
getScreenOnTime(long elapsedRealtimeUs, int which)8060     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
8061         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8062     }
8063 
getScreenOnCount(int which)8064     @Override public int getScreenOnCount(int which) {
8065         return mScreenOnTimer.getCountLocked(which);
8066     }
8067 
getScreenDozeTime(long elapsedRealtimeUs, int which)8068     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
8069         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8070     }
8071 
getScreenDozeCount(int which)8072     @Override public int getScreenDozeCount(int which) {
8073         return mScreenDozeTimer.getCountLocked(which);
8074     }
8075 
8076     @UnsupportedAppUsage
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)8077     @Override public long getScreenBrightnessTime(int brightnessBin,
8078             long elapsedRealtimeUs, int which) {
8079         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
8080                 elapsedRealtimeUs, which);
8081     }
8082 
getScreenBrightnessTimer(int brightnessBin)8083     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
8084         return mScreenBrightnessTimer[brightnessBin];
8085     }
8086 
8087     @Override
getDisplayCount()8088     public int getDisplayCount() {
8089         return mPerDisplayBatteryStats.length;
8090     }
8091 
8092     @Override
getDisplayScreenOnTime(int display, long elapsedRealtimeUs)8093     public long getDisplayScreenOnTime(int display, long elapsedRealtimeUs) {
8094         return mPerDisplayBatteryStats[display].screenOnTimer.getTotalTimeLocked(elapsedRealtimeUs,
8095                 STATS_SINCE_CHARGED);
8096     }
8097 
8098     @Override
getDisplayScreenDozeTime(int display, long elapsedRealtimeUs)8099     public long getDisplayScreenDozeTime(int display, long elapsedRealtimeUs) {
8100         return mPerDisplayBatteryStats[display].screenDozeTimer.getTotalTimeLocked(
8101                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
8102     }
8103 
8104     @Override
getDisplayScreenBrightnessTime(int display, int brightnessBin, long elapsedRealtimeUs)8105     public long getDisplayScreenBrightnessTime(int display, int brightnessBin,
8106             long elapsedRealtimeUs) {
8107         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
8108         return displayStats.screenBrightnessTimers[brightnessBin].getTotalTimeLocked(
8109                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
8110     }
8111 
getInteractiveTime(long elapsedRealtimeUs, int which)8112     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
8113         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8114     }
8115 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)8116     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
8117         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8118     }
8119 
getPowerSaveModeEnabledCount(int which)8120     @Override public int getPowerSaveModeEnabledCount(int which) {
8121         return mPowerSaveModeEnabledTimer.getCountLocked(which);
8122     }
8123 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)8124     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
8125             int which) {
8126         switch (mode) {
8127             case DEVICE_IDLE_MODE_LIGHT:
8128                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8129             case DEVICE_IDLE_MODE_DEEP:
8130                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8131         }
8132         return 0;
8133     }
8134 
getDeviceIdleModeCount(int mode, int which)8135     @Override public int getDeviceIdleModeCount(int mode, int which) {
8136         switch (mode) {
8137             case DEVICE_IDLE_MODE_LIGHT:
8138                 return mDeviceIdleModeLightTimer.getCountLocked(which);
8139             case DEVICE_IDLE_MODE_DEEP:
8140                 return mDeviceIdleModeFullTimer.getCountLocked(which);
8141         }
8142         return 0;
8143     }
8144 
getLongestDeviceIdleModeTime(int mode)8145     @Override public long getLongestDeviceIdleModeTime(int mode) {
8146         switch (mode) {
8147             case DEVICE_IDLE_MODE_LIGHT:
8148                 return mLongestLightIdleTimeMs;
8149             case DEVICE_IDLE_MODE_DEEP:
8150                 return mLongestFullIdleTimeMs;
8151         }
8152         return 0;
8153     }
8154 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)8155     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
8156         switch (mode) {
8157             case DEVICE_IDLE_MODE_LIGHT:
8158                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8159             case DEVICE_IDLE_MODE_DEEP:
8160                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8161         }
8162         return 0;
8163     }
8164 
getDeviceIdlingCount(int mode, int which)8165     @Override public int getDeviceIdlingCount(int mode, int which) {
8166         switch (mode) {
8167             case DEVICE_IDLE_MODE_LIGHT:
8168                 return mDeviceLightIdlingTimer.getCountLocked(which);
8169             case DEVICE_IDLE_MODE_DEEP:
8170                 return mDeviceIdlingTimer.getCountLocked(which);
8171         }
8172         return 0;
8173     }
8174 
getNumConnectivityChange(int which)8175     @Override public int getNumConnectivityChange(int which) {
8176         return mNumConnectivityChange;
8177     }
8178 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)8179     @Override public long getGpsSignalQualityTime(int strengthBin,
8180             long elapsedRealtimeUs, int which) {
8181         if (strengthBin < 0 || strengthBin >= mGpsSignalQualityTimer.length) {
8182             return 0;
8183         }
8184         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
8185                 elapsedRealtimeUs, which);
8186     }
8187 
getGpsBatteryDrainMaMs()8188     @Override public long getGpsBatteryDrainMaMs() {
8189         final double opVolt = mPowerProfile.getAveragePower(
8190             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
8191         if (opVolt == 0) {
8192             return 0;
8193         }
8194         double energyUsedMaMs = 0.0;
8195         final int which = STATS_SINCE_CHARGED;
8196         final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
8197         for(int i=0; i < mGpsSignalQualityTimer.length; i++) {
8198             energyUsedMaMs
8199                     += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
8200                     * (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000);
8201         }
8202         return (long) energyUsedMaMs;
8203     }
8204 
8205     @UnsupportedAppUsage
getPhoneOnTime(long elapsedRealtimeUs, int which)8206     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
8207         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8208     }
8209 
getPhoneOnCount(int which)8210     @Override public int getPhoneOnCount(int which) {
8211         return mPhoneOnTimer.getCountLocked(which);
8212     }
8213 
8214     @UnsupportedAppUsage
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)8215     @Override public long getPhoneSignalStrengthTime(int strengthBin,
8216             long elapsedRealtimeUs, int which) {
8217         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
8218                 elapsedRealtimeUs, which);
8219     }
8220 
8221     @UnsupportedAppUsage
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)8222     @Override public long getPhoneSignalScanningTime(
8223             long elapsedRealtimeUs, int which) {
8224         return mPhoneSignalScanningTimer.getTotalTimeLocked(
8225                 elapsedRealtimeUs, which);
8226     }
8227 
getPhoneSignalScanningTimer()8228     @Override public Timer getPhoneSignalScanningTimer() {
8229         return mPhoneSignalScanningTimer;
8230     }
8231 
8232     @UnsupportedAppUsage
getPhoneSignalStrengthCount(int strengthBin, int which)8233     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
8234         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
8235     }
8236 
getPhoneSignalStrengthTimer(int strengthBin)8237     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
8238         return mPhoneSignalStrengthsTimer[strengthBin];
8239     }
8240 
8241     @UnsupportedAppUsage
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)8242     @Override public long getPhoneDataConnectionTime(int dataType,
8243             long elapsedRealtimeUs, int which) {
8244         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
8245                 elapsedRealtimeUs, which);
8246     }
8247 
8248     @UnsupportedAppUsage
getPhoneDataConnectionCount(int dataType, int which)8249     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
8250         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
8251     }
8252 
getPhoneDataConnectionTimer(int dataType)8253     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
8254         return mPhoneDataConnectionsTimer[dataType];
8255     }
8256 
getActiveRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)8257     @Override public long getActiveRadioDurationMs(@RadioAccessTechnology int rat,
8258             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
8259             long elapsedRealtimeMs) {
8260         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
8261         if (stats == null) return 0L;
8262 
8263         final int freqCount = stats.perStateTimers.length;
8264         if (frequencyRange < 0 || frequencyRange >= freqCount) return 0L;
8265 
8266         final StopwatchTimer[] strengthTimers = stats.perStateTimers[frequencyRange];
8267         final int strengthCount = strengthTimers.length;
8268         if (signalStrength < 0 || signalStrength >= strengthCount) return 0L;
8269 
8270         return stats.perStateTimers[frequencyRange][signalStrength].getTotalTimeLocked(
8271                 elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
8272     }
8273 
8274     @Override
getActiveTxRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)8275     public long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
8276             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
8277             long elapsedRealtimeMs) {
8278         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
8279         if (stats == null) return DURATION_UNAVAILABLE;
8280 
8281         final LongSamplingCounter counter = stats.getTxDurationCounter(frequencyRange,
8282                 signalStrength, false);
8283         if (counter == null) return DURATION_UNAVAILABLE;
8284 
8285         return counter.getCountLocked(STATS_SINCE_CHARGED);
8286     }
8287 
8288     @Override
getActiveRxRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs)8289     public long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
8290             @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs) {
8291         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
8292         if (stats == null) return DURATION_UNAVAILABLE;
8293 
8294         final LongSamplingCounter counter = stats.getRxDurationCounter(frequencyRange, false);
8295         if (counter == null) return DURATION_UNAVAILABLE;
8296 
8297         return counter.getCountLocked(STATS_SINCE_CHARGED);
8298     }
8299 
8300     @UnsupportedAppUsage
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)8301     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
8302         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8303     }
8304 
getMobileRadioActiveCount(int which)8305     @Override public int getMobileRadioActiveCount(int which) {
8306         return mMobileRadioActiveTimer.getCountLocked(which);
8307     }
8308 
getMobileRadioActiveAdjustedTime(int which)8309     @Override public long getMobileRadioActiveAdjustedTime(int which) {
8310         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
8311     }
8312 
getMobileRadioActiveUnknownTime(int which)8313     @Override public long getMobileRadioActiveUnknownTime(int which) {
8314         return mMobileRadioActiveUnknownTime.getCountLocked(which);
8315     }
8316 
getMobileRadioActiveUnknownCount(int which)8317     @Override public int getMobileRadioActiveUnknownCount(int which) {
8318         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
8319     }
8320 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)8321     @Override public long getWifiMulticastWakelockTime(
8322             long elapsedRealtimeUs, int which) {
8323         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
8324                 elapsedRealtimeUs, which);
8325     }
8326 
getWifiMulticastWakelockCount(int which)8327     @Override public int getWifiMulticastWakelockCount(int which) {
8328         return mWifiMulticastWakelockTimer.getCountLocked(which);
8329     }
8330 
8331     @UnsupportedAppUsage
getWifiOnTime(long elapsedRealtimeUs, int which)8332     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
8333         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8334     }
8335 
getWifiActiveTime(long elapsedRealtimeUs, int which)8336     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
8337         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8338     }
8339 
8340     @UnsupportedAppUsage
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)8341     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
8342         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8343     }
8344 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)8345     @Override public long getWifiStateTime(int wifiState,
8346             long elapsedRealtimeUs, int which) {
8347         return mWifiStateTimer[wifiState].getTotalTimeLocked(
8348                 elapsedRealtimeUs, which);
8349     }
8350 
getWifiStateCount(int wifiState, int which)8351     @Override public int getWifiStateCount(int wifiState, int which) {
8352         return mWifiStateTimer[wifiState].getCountLocked(which);
8353     }
8354 
getWifiStateTimer(int wifiState)8355     @Override public Timer getWifiStateTimer(int wifiState) {
8356         return mWifiStateTimer[wifiState];
8357     }
8358 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)8359     @Override public long getWifiSupplStateTime(int state,
8360             long elapsedRealtimeUs, int which) {
8361         return mWifiSupplStateTimer[state].getTotalTimeLocked(
8362                 elapsedRealtimeUs, which);
8363     }
8364 
getWifiSupplStateCount(int state, int which)8365     @Override public int getWifiSupplStateCount(int state, int which) {
8366         return mWifiSupplStateTimer[state].getCountLocked(which);
8367     }
8368 
getWifiSupplStateTimer(int state)8369     @Override public Timer getWifiSupplStateTimer(int state) {
8370         return mWifiSupplStateTimer[state];
8371     }
8372 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)8373     @Override public long getWifiSignalStrengthTime(int strengthBin,
8374             long elapsedRealtimeUs, int which) {
8375         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
8376                 elapsedRealtimeUs, which);
8377     }
8378 
getWifiSignalStrengthCount(int strengthBin, int which)8379     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
8380         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
8381     }
8382 
getWifiSignalStrengthTimer(int strengthBin)8383     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
8384         return mWifiSignalStrengthsTimer[strengthBin];
8385     }
8386 
8387     @Override
getBluetoothControllerActivity()8388     public ControllerActivityCounter getBluetoothControllerActivity() {
8389         return mBluetoothActivity;
8390     }
8391 
8392     @Override
getWifiControllerActivity()8393     public ControllerActivityCounter getWifiControllerActivity() {
8394         return mWifiActivity;
8395     }
8396 
8397     @Override
getModemControllerActivity()8398     public ControllerActivityCounter getModemControllerActivity() {
8399         return mModemActivity;
8400     }
8401 
8402     @Override
hasBluetoothActivityReporting()8403     public boolean hasBluetoothActivityReporting() {
8404         return mHasBluetoothReporting;
8405     }
8406 
8407     @Override
hasWifiActivityReporting()8408     public boolean hasWifiActivityReporting() {
8409         return mHasWifiReporting;
8410     }
8411 
8412     @Override
hasModemActivityReporting()8413     public boolean hasModemActivityReporting() {
8414         return mHasModemReporting;
8415     }
8416 
8417     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)8418     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
8419         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8420     }
8421 
8422     @Override
getFlashlightOnCount(int which)8423     public long getFlashlightOnCount(int which) {
8424         return mFlashlightOnTimer.getCountLocked(which);
8425     }
8426 
8427     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)8428     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
8429         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8430     }
8431 
8432     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)8433     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
8434         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8435     }
8436 
8437     @Override
8438     @UnsupportedAppUsage
getNetworkActivityBytes(int type, int which)8439     public long getNetworkActivityBytes(int type, int which) {
8440         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
8441             return mNetworkByteActivityCounters[type].getCountLocked(which);
8442         } else {
8443             return 0;
8444         }
8445     }
8446 
8447     @Override
getNetworkActivityPackets(int type, int which)8448     public long getNetworkActivityPackets(int type, int which) {
8449         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
8450             return mNetworkPacketActivityCounters[type].getCountLocked(which);
8451         } else {
8452             return 0;
8453         }
8454     }
8455 
8456     @GuardedBy("this")
8457     @Override
getBluetoothMeasuredBatteryConsumptionUC()8458     public long getBluetoothMeasuredBatteryConsumptionUC() {
8459         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
8460     }
8461 
8462     @GuardedBy("this")
8463     @Override
getCpuMeasuredBatteryConsumptionUC()8464     public long getCpuMeasuredBatteryConsumptionUC() {
8465         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
8466     }
8467 
8468     @GuardedBy("this")
8469     @Override
getGnssMeasuredBatteryConsumptionUC()8470     public long getGnssMeasuredBatteryConsumptionUC() {
8471         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS);
8472     }
8473 
8474     @GuardedBy("this")
8475     @Override
getMobileRadioMeasuredBatteryConsumptionUC()8476     public long getMobileRadioMeasuredBatteryConsumptionUC() {
8477         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO);
8478     }
8479 
8480     @GuardedBy("this")
8481     @Override
getPhoneEnergyConsumptionUC()8482     public long getPhoneEnergyConsumptionUC() {
8483         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_PHONE);
8484     }
8485 
8486     @GuardedBy("this")
8487     @Override
getScreenOnMeasuredBatteryConsumptionUC()8488     public long getScreenOnMeasuredBatteryConsumptionUC() {
8489         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
8490     }
8491 
8492     @GuardedBy("this")
8493     @Override
getScreenDozeMeasuredBatteryConsumptionUC()8494     public long getScreenDozeMeasuredBatteryConsumptionUC() {
8495         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE);
8496     }
8497 
8498     @GuardedBy("this")
8499     @Override
getWifiMeasuredBatteryConsumptionUC()8500     public long getWifiMeasuredBatteryConsumptionUC() {
8501         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
8502     }
8503 
8504     /**
8505      * Returns the consumption (in microcoulombs) that the given standard power bucket consumed.
8506      * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable
8507      *
8508      * @param bucket standard power bucket of interest
8509      * @return charge (in microcoulombs) used for this power bucket
8510      */
8511     @GuardedBy("this")
getPowerBucketConsumptionUC(@tandardPowerBucket int bucket)8512     private long getPowerBucketConsumptionUC(@StandardPowerBucket int bucket) {
8513         if (mGlobalMeasuredEnergyStats == null) {
8514             return POWER_DATA_UNAVAILABLE;
8515         }
8516         return mGlobalMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket);
8517     }
8518 
8519     @GuardedBy("this")
8520     @Override
getCustomConsumerMeasuredBatteryConsumptionUC()8521     public @Nullable long[] getCustomConsumerMeasuredBatteryConsumptionUC() {
8522         if (mGlobalMeasuredEnergyStats == null) {
8523             return null;
8524         }
8525         return mGlobalMeasuredEnergyStats.getAccumulatedCustomBucketCharges();
8526     }
8527 
8528     /**
8529      * Returns the names of custom power components.
8530      */
8531     @GuardedBy("this")
8532     @Override
getCustomEnergyConsumerNames()8533     public @NonNull String[] getCustomEnergyConsumerNames() {
8534         if (mMeasuredEnergyStatsConfig == null) {
8535             return new String[0];
8536         }
8537         final String[] names = mMeasuredEnergyStatsConfig.getCustomBucketNames();
8538         for (int i = 0; i < names.length; i++) {
8539             if (TextUtils.isEmpty(names[i])) {
8540                 names[i] = "CUSTOM_" + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i;
8541             }
8542         }
8543         return names;
8544     }
8545 
8546     @GuardedBy("this")
getStartClockTime()8547     @Override public long getStartClockTime() {
8548         final long currentTimeMs = mClock.currentTimeMillis();
8549         if ((currentTimeMs > MILLISECONDS_IN_YEAR
8550                 && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
8551                 || (mStartClockTimeMs > currentTimeMs)) {
8552             // If the start clock time has changed by more than a year, then presumably
8553             // the previous time was completely bogus.  So we are going to figure out a
8554             // new time based on how much time has elapsed since we started counting.
8555             recordCurrentTimeChangeLocked(currentTimeMs, mClock.elapsedRealtime(),
8556                     mClock.uptimeMillis());
8557             return currentTimeMs - (mClock.elapsedRealtime() - (mRealtimeStartUs / 1000));
8558         }
8559         return mStartClockTimeMs;
8560     }
8561 
getStartPlatformVersion()8562     @Override public String getStartPlatformVersion() {
8563         return mStartPlatformVersion;
8564     }
8565 
getEndPlatformVersion()8566     @Override public String getEndPlatformVersion() {
8567         return mEndPlatformVersion;
8568     }
8569 
getParcelVersion()8570     @Override public int getParcelVersion() {
8571         return VERSION;
8572     }
8573 
getIsOnBattery()8574     @Override public boolean getIsOnBattery() {
8575         return mOnBattery;
8576     }
8577 
getStatsStartRealtime()8578     @Override public long getStatsStartRealtime() {
8579         return mRealtimeStartUs;
8580     }
8581 
8582     @UnsupportedAppUsage
getUidStats()8583     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
8584         return mUidStats;
8585     }
8586 
resetIfNotNull(T t, boolean detachIfReset, long elapsedRealtimeUs)8587     private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset,
8588             long elapsedRealtimeUs) {
8589         if (t != null) {
8590             return t.reset(detachIfReset, elapsedRealtimeUs);
8591         }
8592         return true;
8593     }
8594 
resetIfNotNull(T[] t, boolean detachIfReset, long elapsedRealtimeUs)8595     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset,
8596             long elapsedRealtimeUs) {
8597         if (t != null) {
8598             boolean ret = true;
8599             for (int i = 0; i < t.length; i++) {
8600                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
8601             }
8602             return ret;
8603         }
8604         return true;
8605     }
8606 
resetIfNotNull(T[][] t, boolean detachIfReset, long elapsedRealtimeUs)8607     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset,
8608             long elapsedRealtimeUs) {
8609         if (t != null) {
8610             boolean ret = true;
8611             for (int i = 0; i < t.length; i++) {
8612                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
8613             }
8614             return ret;
8615         }
8616         return true;
8617     }
8618 
resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset, long elapsedRealtimeUs)8619     private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
8620             boolean detachIfReset, long elapsedRealtimeUs) {
8621         if (counter != null) {
8622             counter.reset(detachIfReset, elapsedRealtimeUs);
8623         }
8624         return true;
8625     }
8626 
detachIfNotNull(T t)8627     private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
8628         if (t != null) {
8629             t.detach();
8630         }
8631     }
8632 
detachIfNotNull(T[] t)8633     private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
8634         if (t != null) {
8635             for (int i = 0; i < t.length; i++) {
8636                 detachIfNotNull(t[i]);
8637             }
8638         }
8639     }
8640 
detachIfNotNull(T[][] t)8641     private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
8642         if (t != null) {
8643             for (int i = 0; i < t.length; i++) {
8644                 detachIfNotNull(t[i]);
8645             }
8646         }
8647     }
8648 
detachIfNotNull(ControllerActivityCounterImpl counter)8649     private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
8650         if (counter != null) {
8651             counter.detach();
8652         }
8653     }
8654 
8655     /**
8656      * Accumulates stats for a specific binder transaction.
8657      */
8658     @VisibleForTesting
8659     protected static class BinderCallStats {
8660         static final Comparator<BinderCallStats> COMPARATOR =
8661                 Comparator.comparing(BinderCallStats::getClassName)
8662                         .thenComparing(BinderCallStats::getMethodName);
8663 
8664         public Class<? extends Binder> binderClass;
8665         public int transactionCode;
8666         public String methodName;
8667 
8668         public long callCount;
8669         public long recordedCallCount;
8670         public long recordedCpuTimeMicros;
8671 
8672 
8673         @Override
hashCode()8674         public int hashCode() {
8675             return binderClass.hashCode() * 31 + transactionCode;
8676         }
8677 
8678         @Override
equals(Object obj)8679         public boolean equals(Object obj) {
8680             if (!(obj instanceof BinderCallStats)) {
8681                 return false;
8682             }
8683             BinderCallStats bcsk = (BinderCallStats) obj;
8684             return binderClass.equals(bcsk.binderClass) && transactionCode == bcsk.transactionCode;
8685         }
8686 
getClassName()8687         public String getClassName() {
8688             return binderClass.getName();
8689         }
8690 
getMethodName()8691         public String getMethodName() {
8692             return methodName;
8693         }
8694 
8695         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
ensureMethodName(BinderTransactionNameResolver resolver)8696         public void ensureMethodName(BinderTransactionNameResolver resolver) {
8697             if (methodName == null) {
8698                 methodName = resolver.getMethodName(binderClass, transactionCode);
8699             }
8700         }
8701 
8702         @Override
toString()8703         public String toString() {
8704             return "BinderCallStats{"
8705                     + binderClass
8706                     + " transaction=" + transactionCode
8707                     + " callCount=" + callCount
8708                     + " recordedCallCount=" + recordedCallCount
8709                     + " recorderCpuTimeMicros=" + recordedCpuTimeMicros
8710                     + "}";
8711         }
8712     }
8713 
8714     /**
8715      * The statistics associated with a particular uid.
8716      */
8717     public static class Uid extends BatteryStats.Uid {
8718         /**
8719          * BatteryStatsImpl that we are associated with.
8720          */
8721         protected BatteryStatsImpl mBsi;
8722 
8723         final int mUid;
8724 
8725         /** TimeBase for when uid is in background and device is on battery. */
8726         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
8727         public final TimeBase mOnBatteryBackgroundTimeBase;
8728         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
8729         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
8730 
8731         boolean mWifiRunning;
8732         StopwatchTimer mWifiRunningTimer;
8733 
8734         boolean mFullWifiLockOut;
8735         StopwatchTimer mFullWifiLockTimer;
8736 
8737         boolean mWifiScanStarted;
8738         DualTimer mWifiScanTimer;
8739 
8740         static final int NO_BATCHED_SCAN_STARTED = -1;
8741         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8742         StopwatchTimer[] mWifiBatchedScanTimer;
8743 
8744         int mWifiMulticastWakelockCount;
8745         StopwatchTimer mWifiMulticastTimer;
8746 
8747         StopwatchTimer mAudioTurnedOnTimer;
8748         StopwatchTimer mVideoTurnedOnTimer;
8749         StopwatchTimer mFlashlightTurnedOnTimer;
8750         StopwatchTimer mCameraTurnedOnTimer;
8751         StopwatchTimer mForegroundActivityTimer;
8752         StopwatchTimer mForegroundServiceTimer;
8753         /** Total time spent by the uid holding any partial wakelocks. */
8754         DualTimer mAggregatedPartialWakelockTimer;
8755         DualTimer mBluetoothScanTimer;
8756         DualTimer mBluetoothUnoptimizedScanTimer;
8757         Counter mBluetoothScanResultCounter;
8758         Counter mBluetoothScanResultBgCounter;
8759 
8760         int mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
8761         StopwatchTimer[] mProcessStateTimer;
8762 
8763         boolean mInForegroundService = false;
8764 
8765         BatchTimer mVibratorOnTimer;
8766 
8767         Counter[] mUserActivityCounters;
8768 
8769         LongSamplingCounter[] mNetworkByteActivityCounters;
8770         LongSamplingCounter[] mNetworkPacketActivityCounters;
8771         TimeMultiStateCounter mMobileRadioActiveTime;
8772         LongSamplingCounter mMobileRadioActiveCount;
8773 
8774         /**
8775          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
8776          */
8777         private LongSamplingCounter mMobileRadioApWakeupCount;
8778 
8779         /**
8780          * How many times this UID woke up the Application Processor due to a Wifi packet.
8781          */
8782         private LongSamplingCounter mWifiRadioApWakeupCount;
8783 
8784         /**
8785          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
8786          * Can be null if the UID has had no such activity.
8787          */
8788         private ControllerActivityCounterImpl mWifiControllerActivity;
8789 
8790         /**
8791          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
8792          * Can be null if the UID has had no such activity.
8793          */
8794         private ControllerActivityCounterImpl mBluetoothControllerActivity;
8795 
8796         /**
8797          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
8798          * Can be null if the UID has had no such activity.
8799          */
8800         private ControllerActivityCounterImpl mModemControllerActivity;
8801 
8802         /**
8803          * The CPU times we had at the last history details update.
8804          */
8805         long mLastStepUserTimeMs;
8806         long mLastStepSystemTimeMs;
8807         long mCurStepUserTimeMs;
8808         long mCurStepSystemTimeMs;
8809 
8810         LongSamplingCounter mUserCpuTime;
8811         LongSamplingCounter mSystemCpuTime;
8812         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
8813         TimeMultiStateCounter mCpuActiveTimeMs;
8814 
8815         LongSamplingCounterArray mCpuFreqTimeMs;
8816         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
8817         LongSamplingCounterArray mCpuClusterTimesMs;
8818 
8819         TimeInFreqMultiStateCounter mProcStateTimeMs;
8820         TimeInFreqMultiStateCounter mProcStateScreenOffTimeMs;
8821 
8822         SparseArray<ChildUid> mChildUids;
8823 
8824         /**
8825          * The statistics we have collected for this uid's wake locks.
8826          */
8827         final OverflowArrayMap<Wakelock> mWakelockStats;
8828 
8829         /**
8830          * The statistics we have collected for this uid's syncs.
8831          */
8832         final OverflowArrayMap<DualTimer> mSyncStats;
8833 
8834         /**
8835          * The statistics we have collected for this uid's jobs.
8836          */
8837         final OverflowArrayMap<DualTimer> mJobStats;
8838 
8839         /**
8840          * Count of the jobs that have completed and the reasons why they completed.
8841          */
8842         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
8843 
8844         /**
8845          * Count of app launch events that had associated deferred job counts or info about
8846          * last time a job was run.
8847          */
8848         Counter mJobsDeferredEventCount;
8849 
8850         /**
8851          * Count of deferred jobs that were pending when the app was launched or brought to
8852          * the foreground through a user interaction.
8853          */
8854         Counter mJobsDeferredCount;
8855 
8856         /**
8857          * Sum of time since the last time a job was run for this app before it was launched.
8858          */
8859         LongSamplingCounter mJobsFreshnessTimeMs;
8860 
8861         /**
8862          * Array of counts of instances where the time since the last job was run for the app
8863          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
8864          */
8865         final Counter[] mJobsFreshnessBuckets;
8866 
8867         /**
8868          * The statistics we have collected for this uid's sensor activations.
8869          */
8870         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
8871 
8872         /**
8873          * The statistics we have collected for this uid's processes.
8874          */
8875         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
8876 
8877         /**
8878          * The statistics we have collected for this uid's processes.
8879          */
8880         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
8881 
8882         /**
8883          * The transient wake stats we have collected for this uid's pids.
8884          */
8885         final SparseArray<Pid> mPids = new SparseArray<>();
8886 
8887         /**
8888          * Grand total of system server binder calls made by this uid.
8889          */
8890         private long mBinderCallCount;
8891 
8892         /**
8893          * Detailed information about system server binder calls made by this uid.
8894          */
8895         private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>();
8896 
8897         /**
8898          * Measured charge consumption by this uid while on battery.
8899          * Its '<b>custom</b> power buckets' correspond to the
8900          * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
8901          * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
8902          *
8903          * Will be null if energy consumer data is completely unavailable (in which case
8904          * {@link #mGlobalMeasuredEnergyStats} will also be null) or if the power usage by this uid
8905          * is 0 for every bucket.
8906          */
8907         private MeasuredEnergyStats mUidMeasuredEnergyStats;
8908 
8909         /**
8910          * Estimated total time spent by the system server handling requests from this uid.
8911          */
8912         private long mSystemServiceTimeUs;
8913 
8914         /**
8915          * Estimated proportion of system server binder call CPU cost for this uid.
8916          */
8917         private double mProportionalSystemServiceUsage;
8918 
Uid(BatteryStatsImpl bsi, int uid)8919         public Uid(BatteryStatsImpl bsi, int uid) {
8920             this(bsi, uid, bsi.mClock.elapsedRealtime(), bsi.mClock.uptimeMillis());
8921         }
8922 
Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs)8923         public Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs) {
8924             mBsi = bsi;
8925             mUid = uid;
8926 
8927             /* Observer list of TimeBase object in Uid is short */
8928             mOnBatteryBackgroundTimeBase = new TimeBase(false);
8929             mOnBatteryBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8930             /* Observer list of TimeBase object in Uid is short */
8931             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
8932             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8933 
8934             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8935             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8936             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
8937 
8938             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
8939                 @Override public Wakelock instantiateObject() {
8940                     return new Wakelock(mBsi, Uid.this);
8941                 }
8942             };
8943             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
8944                 @Override public DualTimer instantiateObject() {
8945                     return new DualTimer(mBsi.mClock, Uid.this, SYNC, null,
8946                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8947                 }
8948             };
8949             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
8950                 @Override public DualTimer instantiateObject() {
8951                     return new DualTimer(mBsi.mClock, Uid.this, JOB, null,
8952                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8953                 }
8954             };
8955 
8956             mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, this, WIFI_RUNNING,
8957                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
8958             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, this, FULL_WIFI_LOCK,
8959                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
8960             mWifiScanTimer = new DualTimer(mBsi.mClock, this, WIFI_SCAN,
8961                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8962             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
8963             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, this, WIFI_MULTICAST_ENABLED,
8964                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
8965             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
8966             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
8967             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
8968             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8969             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
8970         }
8971 
8972         @GuardedBy("mBsi")
8973         @VisibleForTesting
setProcessStateForTest(int procState, long elapsedTimeMs)8974         public void setProcessStateForTest(int procState, long elapsedTimeMs) {
8975             mProcessState = procState;
8976             getProcStateTimeCounter(elapsedTimeMs).setState(procState, elapsedTimeMs);
8977             getProcStateScreenOffTimeCounter(elapsedTimeMs).setState(procState, elapsedTimeMs);
8978             final int batteryConsumerProcessState =
8979                     mapUidProcessStateToBatteryConsumerProcessState(procState);
8980             getCpuActiveTimeCounter().setState(batteryConsumerProcessState, elapsedTimeMs);
8981             getMobileRadioActiveTimeCounter().setState(batteryConsumerProcessState, elapsedTimeMs);
8982             final ControllerActivityCounterImpl wifiControllerActivity =
8983                     getWifiControllerActivity();
8984             if (wifiControllerActivity != null) {
8985                 wifiControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs);
8986             }
8987             final ControllerActivityCounterImpl bluetoothControllerActivity =
8988                     getBluetoothControllerActivity();
8989             if (bluetoothControllerActivity != null) {
8990                 bluetoothControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs);
8991             }
8992             final MeasuredEnergyStats energyStats =
8993                     getOrCreateMeasuredEnergyStatsIfSupportedLocked();
8994             if (energyStats != null) {
8995                 energyStats.setState(batteryConsumerProcessState, elapsedTimeMs);
8996             }
8997         }
8998 
8999         @Override
getCpuFreqTimes(int which)9000         public long[] getCpuFreqTimes(int which) {
9001             return nullIfAllZeros(mCpuFreqTimeMs, which);
9002         }
9003 
9004         @Override
getScreenOffCpuFreqTimes(int which)9005         public long[] getScreenOffCpuFreqTimes(int which) {
9006             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
9007         }
9008 
getCpuActiveTimeCounter()9009         private TimeMultiStateCounter getCpuActiveTimeCounter() {
9010             if (mCpuActiveTimeMs == null) {
9011                 final long timestampMs = mBsi.mClock.elapsedRealtime();
9012                 mCpuActiveTimeMs = new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase,
9013                         BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
9014                 mCpuActiveTimeMs.setState(
9015                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
9016                         timestampMs);
9017             }
9018             return mCpuActiveTimeMs;
9019         }
9020 
9021         @Override
getCpuActiveTime()9022         public long getCpuActiveTime() {
9023             if (mCpuActiveTimeMs == null) {
9024                 return 0;
9025             }
9026 
9027             long activeTime = 0;
9028             for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
9029                 activeTime += mCpuActiveTimeMs.getCountForProcessState(procState);
9030             }
9031             return activeTime;
9032         }
9033 
9034         @Override
getCpuActiveTime(int procState)9035         public long getCpuActiveTime(int procState) {
9036             if (mCpuActiveTimeMs == null
9037                     || procState < 0 || procState >= BatteryConsumer.PROCESS_STATE_COUNT) {
9038                 return 0;
9039             }
9040 
9041             return mCpuActiveTimeMs.getCountForProcessState(procState);
9042         }
9043 
9044         @Override
getCpuClusterTimes()9045         public long[] getCpuClusterTimes() {
9046             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
9047         }
9048 
9049         @GuardedBy("mBsi")
9050         @Override
getCpuFreqTimes(long[] timesInFreqMs, int procState)9051         public boolean getCpuFreqTimes(long[] timesInFreqMs, int procState) {
9052             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
9053                 return false;
9054             }
9055             if (mProcStateTimeMs == null) {
9056                 return false;
9057             }
9058             if (!mBsi.mPerProcStateCpuTimesAvailable) {
9059                 mProcStateTimeMs = null;
9060                 return false;
9061             }
9062             return mProcStateTimeMs.getCountsLocked(timesInFreqMs, procState);
9063         }
9064 
9065         @GuardedBy("mBsi")
9066         @Override
getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState)9067         public boolean getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState) {
9068             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
9069                 return false;
9070             }
9071             if (mProcStateScreenOffTimeMs == null) {
9072                 return false;
9073             }
9074             if (!mBsi.mPerProcStateCpuTimesAvailable) {
9075                 mProcStateScreenOffTimeMs = null;
9076                 return false;
9077             }
9078             return mProcStateScreenOffTimeMs.getCountsLocked(timesInFreqMs, procState);
9079         }
9080 
getBinderCallCount()9081         public long getBinderCallCount() {
9082             return mBinderCallCount;
9083         }
9084 
9085         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
getBinderCallStats()9086         public ArraySet<BinderCallStats> getBinderCallStats() {
9087             return mBinderCallStats;
9088         }
9089 
9090         @Override
getProportionalSystemServiceUsage()9091         public  double getProportionalSystemServiceUsage() {
9092             return mProportionalSystemServiceUsage;
9093         }
9094 
9095         @GuardedBy("mBsi")
addIsolatedUid(int isolatedUid)9096         public void addIsolatedUid(int isolatedUid) {
9097             if (mChildUids == null) {
9098                 mChildUids = new SparseArray<>();
9099             } else if (mChildUids.indexOfKey(isolatedUid) >= 0) {
9100                 return;
9101             }
9102             mChildUids.put(isolatedUid, new ChildUid());
9103         }
9104 
removeIsolatedUid(int isolatedUid)9105         public void removeIsolatedUid(int isolatedUid) {
9106             final int idx = mChildUids == null ? -1 : mChildUids.indexOfKey(isolatedUid);
9107             if (idx < 0) {
9108                 return;
9109             }
9110             mChildUids.remove(idx);
9111         }
9112 
9113         @GuardedBy("mBsi")
getChildUid(int childUid)9114         ChildUid getChildUid(int childUid) {
9115             return mChildUids == null ? null : mChildUids.get(childUid);
9116         }
9117 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)9118         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
9119             if (cpuTimesMs == null) {
9120                 return null;
9121             }
9122             final long[] counts = cpuTimesMs.getCountsLocked(which);
9123             if (counts == null) {
9124                 return null;
9125             }
9126             // Return counts only if at least one of the elements is non-zero.
9127             for (int i = counts.length - 1; i >= 0; --i) {
9128                 if (counts[i] != 0) {
9129                     return counts;
9130                 }
9131             }
9132             return null;
9133         }
9134 
9135         @GuardedBy("mBsi")
ensureMultiStateCounters(long timestampMs)9136         private void ensureMultiStateCounters(long timestampMs) {
9137             if (mProcStateTimeMs != null) {
9138                 return;
9139             }
9140 
9141             mProcStateTimeMs =
9142                     new TimeInFreqMultiStateCounter(mBsi.mOnBatteryTimeBase,
9143                             PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(),
9144                             timestampMs);
9145             mProcStateScreenOffTimeMs =
9146                     new TimeInFreqMultiStateCounter(mBsi.mOnBatteryScreenOffTimeBase,
9147                             PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(),
9148                             timestampMs);
9149         }
9150 
9151         @GuardedBy("mBsi")
getProcStateTimeCounter(long timestampMs)9152         private TimeInFreqMultiStateCounter getProcStateTimeCounter(long timestampMs) {
9153             ensureMultiStateCounters(timestampMs);
9154             return mProcStateTimeMs;
9155         }
9156 
9157         @GuardedBy("mBsi")
getProcStateScreenOffTimeCounter(long timestampMs)9158         private TimeInFreqMultiStateCounter getProcStateScreenOffTimeCounter(long timestampMs) {
9159             ensureMultiStateCounters(timestampMs);
9160             return mProcStateScreenOffTimeMs;
9161         }
9162 
9163         @Override
getAggregatedPartialWakelockTimer()9164         public Timer getAggregatedPartialWakelockTimer() {
9165             return mAggregatedPartialWakelockTimer;
9166         }
9167 
9168         @Override
9169         @UnsupportedAppUsage
getWakelockStats()9170         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
9171             return mWakelockStats.getMap();
9172         }
9173 
9174         @Override
getMulticastWakelockStats()9175         public Timer getMulticastWakelockStats() {
9176             return mWifiMulticastTimer;
9177         }
9178 
9179         @Override
getSyncStats()9180         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
9181             return mSyncStats.getMap();
9182         }
9183 
9184         @Override
getJobStats()9185         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
9186             return mJobStats.getMap();
9187         }
9188 
9189         @Override
getJobCompletionStats()9190         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
9191             return mJobCompletions;
9192         }
9193 
9194         @Override
9195         @UnsupportedAppUsage
getSensorStats()9196         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
9197             return mSensorStats;
9198         }
9199 
9200         @Override
9201         @UnsupportedAppUsage
getProcessStats()9202         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
9203             return mProcessStats;
9204         }
9205 
9206         @Override
getPackageStats()9207         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
9208             return mPackageStats;
9209         }
9210 
9211         @Override
9212         @UnsupportedAppUsage
getUid()9213         public int getUid() {
9214             return mUid;
9215         }
9216 
9217         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)9218         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
9219             if (!mWifiRunning) {
9220                 mWifiRunning = true;
9221                 if (mWifiRunningTimer == null) {
9222                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, Uid.this, WIFI_RUNNING,
9223                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
9224                 }
9225                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
9226             }
9227         }
9228 
9229         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)9230         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
9231             if (mWifiRunning) {
9232                 mWifiRunning = false;
9233                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
9234             }
9235         }
9236 
9237         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)9238         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
9239             if (!mFullWifiLockOut) {
9240                 mFullWifiLockOut = true;
9241                 if (mFullWifiLockTimer == null) {
9242                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, Uid.this, FULL_WIFI_LOCK,
9243                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
9244                 }
9245                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
9246             }
9247         }
9248 
9249         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)9250         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
9251             if (mFullWifiLockOut) {
9252                 mFullWifiLockOut = false;
9253                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
9254             }
9255         }
9256 
9257         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)9258         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
9259             if (!mWifiScanStarted) {
9260                 mWifiScanStarted = true;
9261                 if (mWifiScanTimer == null) {
9262                     mWifiScanTimer = new DualTimer(mBsi.mClock, Uid.this, WIFI_SCAN,
9263                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
9264                             mOnBatteryBackgroundTimeBase);
9265                 }
9266                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
9267             }
9268         }
9269 
9270         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)9271         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
9272             if (mWifiScanStarted) {
9273                 mWifiScanStarted = false;
9274                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
9275             }
9276         }
9277 
9278         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)9279         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
9280             int bin = 0;
9281             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
9282                 csph = csph >> 3;
9283                 bin++;
9284             }
9285 
9286             if (mWifiBatchedScanBinStarted == bin) return;
9287 
9288             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
9289                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
9290                         stopRunningLocked(elapsedRealtimeMs);
9291             }
9292             mWifiBatchedScanBinStarted = bin;
9293             if (mWifiBatchedScanTimer[bin] == null) {
9294                 makeWifiBatchedScanBin(bin, null);
9295             }
9296             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
9297         }
9298 
9299         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)9300         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
9301             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
9302                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
9303                         stopRunningLocked(elapsedRealtimeMs);
9304                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
9305             }
9306         }
9307 
9308         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)9309         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
9310             if (mWifiMulticastWakelockCount == 0) {
9311                 if (mWifiMulticastTimer == null) {
9312                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9313                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
9314                 }
9315                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
9316             }
9317             mWifiMulticastWakelockCount++;
9318         }
9319 
9320         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)9321         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
9322             if (mWifiMulticastWakelockCount == 0) {
9323                 return;
9324             }
9325 
9326             mWifiMulticastWakelockCount--;
9327             if (mWifiMulticastWakelockCount == 0) {
9328                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
9329             }
9330         }
9331 
9332         @Override
getWifiControllerActivity()9333         public ControllerActivityCounterImpl getWifiControllerActivity() {
9334             return mWifiControllerActivity;
9335         }
9336 
9337         @Override
getBluetoothControllerActivity()9338         public ControllerActivityCounterImpl getBluetoothControllerActivity() {
9339             return mBluetoothControllerActivity;
9340         }
9341 
9342         @Override
getModemControllerActivity()9343         public ControllerActivityCounter getModemControllerActivity() {
9344             return mModemControllerActivity;
9345         }
9346 
getOrCreateWifiControllerActivityLocked()9347         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
9348             if (mWifiControllerActivity == null) {
9349                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
9350                         mBsi.mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
9351             }
9352             return mWifiControllerActivity;
9353         }
9354 
getOrCreateBluetoothControllerActivityLocked()9355         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
9356             if (mBluetoothControllerActivity == null) {
9357                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
9358                         mBsi.mOnBatteryTimeBase, NUM_BT_TX_LEVELS);
9359             }
9360             return mBluetoothControllerActivity;
9361         }
9362 
getOrCreateModemControllerActivityLocked()9363         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
9364             if (mModemControllerActivity == null) {
9365                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
9366                         mBsi.mOnBatteryTimeBase, ModemActivityInfo.getNumTxPowerLevels());
9367             }
9368             return mModemControllerActivity;
9369         }
9370 
9371         @GuardedBy("mBsi")
getOrCreateMeasuredEnergyStatsLocked()9372         private MeasuredEnergyStats getOrCreateMeasuredEnergyStatsLocked() {
9373             if (mUidMeasuredEnergyStats == null) {
9374                 mUidMeasuredEnergyStats = new MeasuredEnergyStats(mBsi.mMeasuredEnergyStatsConfig);
9375             }
9376             return mUidMeasuredEnergyStats;
9377         }
9378 
9379         @GuardedBy("mBsi")
getOrCreateMeasuredEnergyStatsIfSupportedLocked()9380         private MeasuredEnergyStats getOrCreateMeasuredEnergyStatsIfSupportedLocked() {
9381             if (mUidMeasuredEnergyStats == null && mBsi.mMeasuredEnergyStatsConfig != null) {
9382                 mUidMeasuredEnergyStats = new MeasuredEnergyStats(mBsi.mMeasuredEnergyStatsConfig);
9383             }
9384             return mUidMeasuredEnergyStats;
9385         }
9386 
9387         /** Adds the given charge to the given standard power bucket for this uid. */
9388         @GuardedBy("mBsi")
addChargeToStandardBucketLocked(long chargeDeltaUC, @StandardPowerBucket int powerBucket, long timestampMs)9389         private void addChargeToStandardBucketLocked(long chargeDeltaUC,
9390                 @StandardPowerBucket int powerBucket, long timestampMs) {
9391             final MeasuredEnergyStats measuredEnergyStats =
9392                     getOrCreateMeasuredEnergyStatsLocked();
9393             measuredEnergyStats.updateStandardBucket(powerBucket, chargeDeltaUC, timestampMs);
9394         }
9395 
9396         /** Adds the given charge to the given custom power bucket for this uid. */
9397         @GuardedBy("mBsi")
addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket)9398         private void addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket) {
9399             getOrCreateMeasuredEnergyStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC,
9400                     mBsi.mClock.elapsedRealtime());
9401         }
9402 
9403         /**
9404          * Returns the battery consumption (in microcoulomb) of this uid for a standard power bucket
9405          * of interest.
9406          * @param bucket standard power bucket of interest
9407          * @return consumption (in microcolombs) used by this uid for this power bucket
9408          */
9409         @GuardedBy("mBsi")
getMeasuredBatteryConsumptionUC(@tandardPowerBucket int bucket)9410         public long getMeasuredBatteryConsumptionUC(@StandardPowerBucket int bucket) {
9411             if (mBsi.mGlobalMeasuredEnergyStats == null
9412                     || !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) {
9413                 return POWER_DATA_UNAVAILABLE;
9414             }
9415             if (mUidMeasuredEnergyStats == null) {
9416                 return 0L; // It is supported, but was never filled, so it must be 0
9417             }
9418             return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket);
9419         }
9420 
9421         /**
9422          * Returns the battery consumption (in microcoulombs) of this uid for a standard power
9423          * bucket and a process state, such as Uid.PROCESS_STATE_TOP.
9424          */
9425         @GuardedBy("mBsi")
getMeasuredBatteryConsumptionUC(@tandardPowerBucket int bucket, int processState)9426         public long getMeasuredBatteryConsumptionUC(@StandardPowerBucket int bucket,
9427                 int processState) {
9428             if (mBsi.mGlobalMeasuredEnergyStats == null
9429                     || !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) {
9430                 return POWER_DATA_UNAVAILABLE;
9431             }
9432             if (mUidMeasuredEnergyStats == null) {
9433                 return 0L; // It is supported, but was never filled, so it must be 0
9434             }
9435             return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket, processState);
9436         }
9437 
9438         @GuardedBy("mBsi")
9439         @Override
getCustomConsumerMeasuredBatteryConsumptionUC()9440         public long[] getCustomConsumerMeasuredBatteryConsumptionUC() {
9441             if (mBsi.mGlobalMeasuredEnergyStats == null) {
9442                 return null;
9443             }
9444             if (mUidMeasuredEnergyStats == null) {
9445                 // Custom buckets may exist. But all values for this uid are 0 so we report all 0s.
9446                 return new long[mBsi.mGlobalMeasuredEnergyStats.getNumberCustomPowerBuckets()];
9447             }
9448             return mUidMeasuredEnergyStats.getAccumulatedCustomBucketCharges();
9449         }
9450 
9451         @GuardedBy("mBsi")
9452         @Override
getBluetoothMeasuredBatteryConsumptionUC()9453         public long getBluetoothMeasuredBatteryConsumptionUC() {
9454             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
9455         }
9456 
9457         @GuardedBy("mBsi")
9458         @Override
getBluetoothMeasuredBatteryConsumptionUC( @atteryConsumer.ProcessState int processState)9459         public long getBluetoothMeasuredBatteryConsumptionUC(
9460                 @BatteryConsumer.ProcessState int processState) {
9461             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH,
9462                     processState);
9463         }
9464 
9465         @GuardedBy("mBsi")
9466         @Override
getCpuMeasuredBatteryConsumptionUC()9467         public long getCpuMeasuredBatteryConsumptionUC() {
9468             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
9469         }
9470 
9471         @GuardedBy("mBsi")
9472         @Override
getCpuMeasuredBatteryConsumptionUC( @atteryConsumer.ProcessState int processState)9473         public long getCpuMeasuredBatteryConsumptionUC(
9474                 @BatteryConsumer.ProcessState int processState) {
9475             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU,
9476                     processState);
9477         }
9478 
9479         @GuardedBy("mBsi")
9480         @Override
getGnssMeasuredBatteryConsumptionUC()9481         public long getGnssMeasuredBatteryConsumptionUC() {
9482             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS);
9483         }
9484 
9485         @GuardedBy("mBsi")
9486         @Override
getMobileRadioMeasuredBatteryConsumptionUC()9487         public long getMobileRadioMeasuredBatteryConsumptionUC() {
9488             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO);
9489         }
9490 
9491         @GuardedBy("mBsi")
9492         @Override
getMobileRadioMeasuredBatteryConsumptionUC(int processState)9493         public long getMobileRadioMeasuredBatteryConsumptionUC(int processState) {
9494             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO,
9495                     processState);
9496         }
9497 
9498         @GuardedBy("mBsi")
9499         @Override
getScreenOnMeasuredBatteryConsumptionUC()9500         public long getScreenOnMeasuredBatteryConsumptionUC() {
9501             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
9502         }
9503 
9504         @GuardedBy("mBsi")
9505         @Override
getWifiMeasuredBatteryConsumptionUC()9506         public long getWifiMeasuredBatteryConsumptionUC() {
9507             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
9508         }
9509 
9510         @GuardedBy("mBsi")
9511         @Override
getWifiMeasuredBatteryConsumptionUC(int processState)9512         public long getWifiMeasuredBatteryConsumptionUC(int processState) {
9513             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI,
9514                     processState);
9515         }
9516 
9517         /**
9518          * Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
9519          * since last marked. Also sets the mark time for both these timers.
9520          *
9521          * @see CpuPowerCalculator
9522          *
9523          * @param doCalc if true, then calculate the minimum; else don't bother and return 0. Either
9524          *               way, the mark is set.
9525          */
markProcessForegroundTimeUs(long elapsedRealtimeMs, boolean doCalc)9526         private long markProcessForegroundTimeUs(long elapsedRealtimeMs,
9527                 boolean doCalc) {
9528             long fgTimeUs = 0;
9529             final StopwatchTimer fgTimer = mForegroundActivityTimer;
9530             if (fgTimer != null) {
9531                 if (doCalc) fgTimeUs = fgTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
9532                 fgTimer.setMark(elapsedRealtimeMs);
9533             }
9534 
9535             long topTimeUs = 0;
9536             final StopwatchTimer topTimer = mProcessStateTimer[PROCESS_STATE_TOP];
9537             if (topTimer != null) {
9538                 if (doCalc) topTimeUs = topTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
9539                 topTimer.setMark(elapsedRealtimeMs);
9540             }
9541 
9542             // Return the min of the two
9543             return (topTimeUs < fgTimeUs) ? topTimeUs : fgTimeUs;
9544         }
9545 
9546 
9547         /**
9548          * Gets the uid's time spent using the GNSS since last marked. Also sets the mark time for
9549          * the GNSS timer.
9550          */
markGnssTimeUs(long elapsedRealtimeMs)9551         private long markGnssTimeUs(long elapsedRealtimeMs) {
9552             final Sensor sensor = mSensorStats.get(Sensor.GPS);
9553             if (sensor == null) {
9554                 return 0;
9555             }
9556 
9557             final StopwatchTimer timer = sensor.mTimer;
9558             if (timer == null) {
9559                 return 0;
9560             }
9561 
9562             final long gnssTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
9563             timer.setMark(elapsedRealtimeMs);
9564             return gnssTimeUs;
9565         }
9566 
createAudioTurnedOnTimerLocked()9567         public StopwatchTimer createAudioTurnedOnTimerLocked() {
9568             if (mAudioTurnedOnTimer == null) {
9569                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, AUDIO_TURNED_ON,
9570                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9571             }
9572             return mAudioTurnedOnTimer;
9573         }
9574 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)9575         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
9576             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9577         }
9578 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)9579         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
9580             if (mAudioTurnedOnTimer != null) {
9581                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9582             }
9583         }
9584 
noteResetAudioLocked(long elapsedRealtimeMs)9585         public void noteResetAudioLocked(long elapsedRealtimeMs) {
9586             if (mAudioTurnedOnTimer != null) {
9587                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9588             }
9589         }
9590 
createVideoTurnedOnTimerLocked()9591         public StopwatchTimer createVideoTurnedOnTimerLocked() {
9592             if (mVideoTurnedOnTimer == null) {
9593                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, VIDEO_TURNED_ON,
9594                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9595             }
9596             return mVideoTurnedOnTimer;
9597         }
9598 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)9599         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
9600             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9601         }
9602 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)9603         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
9604             if (mVideoTurnedOnTimer != null) {
9605                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9606             }
9607         }
9608 
noteResetVideoLocked(long elapsedRealtimeMs)9609         public void noteResetVideoLocked(long elapsedRealtimeMs) {
9610             if (mVideoTurnedOnTimer != null) {
9611                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9612             }
9613         }
9614 
createFlashlightTurnedOnTimerLocked()9615         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
9616             if (mFlashlightTurnedOnTimer == null) {
9617                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9618                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9619             }
9620             return mFlashlightTurnedOnTimer;
9621         }
9622 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)9623         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
9624             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9625         }
9626 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)9627         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
9628             if (mFlashlightTurnedOnTimer != null) {
9629                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9630             }
9631         }
9632 
noteResetFlashlightLocked(long elapsedRealtimeMs)9633         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
9634             if (mFlashlightTurnedOnTimer != null) {
9635                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9636             }
9637         }
9638 
createCameraTurnedOnTimerLocked()9639         public StopwatchTimer createCameraTurnedOnTimerLocked() {
9640             if (mCameraTurnedOnTimer == null) {
9641                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, CAMERA_TURNED_ON,
9642                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9643             }
9644             return mCameraTurnedOnTimer;
9645         }
9646 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)9647         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
9648             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9649         }
9650 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)9651         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
9652             if (mCameraTurnedOnTimer != null) {
9653                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9654             }
9655         }
9656 
noteResetCameraLocked(long elapsedRealtimeMs)9657         public void noteResetCameraLocked(long elapsedRealtimeMs) {
9658             if (mCameraTurnedOnTimer != null) {
9659                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9660             }
9661         }
9662 
createForegroundActivityTimerLocked()9663         public StopwatchTimer createForegroundActivityTimerLocked() {
9664             if (mForegroundActivityTimer == null) {
9665                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9666                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
9667             }
9668             return mForegroundActivityTimer;
9669         }
9670 
createForegroundServiceTimerLocked()9671         public StopwatchTimer createForegroundServiceTimerLocked() {
9672             if (mForegroundServiceTimer == null) {
9673                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9674                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
9675             }
9676             return mForegroundServiceTimer;
9677         }
9678 
createAggregatedPartialWakelockTimerLocked()9679         public DualTimer createAggregatedPartialWakelockTimerLocked() {
9680             if (mAggregatedPartialWakelockTimer == null) {
9681                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClock, this,
9682                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
9683                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
9684             }
9685             return mAggregatedPartialWakelockTimer;
9686         }
9687 
createBluetoothScanTimerLocked()9688         public DualTimer createBluetoothScanTimerLocked() {
9689             if (mBluetoothScanTimer == null) {
9690                 mBluetoothScanTimer = new DualTimer(mBsi.mClock, Uid.this, BLUETOOTH_SCAN_ON,
9691                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
9692                         mOnBatteryBackgroundTimeBase);
9693             }
9694             return mBluetoothScanTimer;
9695         }
9696 
createBluetoothUnoptimizedScanTimerLocked()9697         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
9698             if (mBluetoothUnoptimizedScanTimer == null) {
9699                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClock, Uid.this,
9700                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
9701                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
9702             }
9703             return mBluetoothUnoptimizedScanTimer;
9704         }
9705 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)9706         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
9707                 boolean isUnoptimized) {
9708             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
9709             if (isUnoptimized) {
9710                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
9711             }
9712         }
9713 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)9714         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
9715             if (mBluetoothScanTimer != null) {
9716                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
9717             }
9718             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
9719                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
9720             }
9721         }
9722 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)9723         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
9724             if (mBluetoothScanTimer != null) {
9725                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
9726             }
9727             if (mBluetoothUnoptimizedScanTimer != null) {
9728                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
9729             }
9730         }
9731 
createBluetoothScanResultCounterLocked()9732         public Counter createBluetoothScanResultCounterLocked() {
9733             if (mBluetoothScanResultCounter == null) {
9734                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
9735             }
9736             return mBluetoothScanResultCounter;
9737         }
9738 
createBluetoothScanResultBgCounterLocked()9739         public Counter createBluetoothScanResultBgCounterLocked() {
9740             if (mBluetoothScanResultBgCounter == null) {
9741                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
9742             }
9743             return mBluetoothScanResultBgCounter;
9744         }
9745 
noteBluetoothScanResultsLocked(int numNewResults)9746         public void noteBluetoothScanResultsLocked(int numNewResults) {
9747             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
9748             // Uses background timebase, so the count will only be incremented if uid in background.
9749             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
9750         }
9751 
9752         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)9753         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
9754             // We always start, since we want multiple foreground PIDs to nest
9755             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
9756         }
9757 
9758         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)9759         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
9760             if (mForegroundActivityTimer != null) {
9761                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
9762             }
9763         }
9764 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)9765         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
9766             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
9767         }
9768 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)9769         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
9770             if (mForegroundServiceTimer != null) {
9771                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
9772             }
9773         }
9774 
createVibratorOnTimerLocked()9775         public BatchTimer createVibratorOnTimerLocked() {
9776             if (mVibratorOnTimer == null) {
9777                 mVibratorOnTimer = new BatchTimer(mBsi.mClock, Uid.this, VIBRATOR_ON,
9778                         mBsi.mOnBatteryTimeBase);
9779             }
9780             return mVibratorOnTimer;
9781         }
9782 
noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs)9783         public void noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs) {
9784             createVibratorOnTimerLocked().addDuration(mBsi, durationMillis, elapsedRealtimeMs);
9785         }
9786 
noteVibratorOffLocked(long elapsedRealtimeMs)9787         public void noteVibratorOffLocked(long elapsedRealtimeMs) {
9788             if (mVibratorOnTimer != null) {
9789                 mVibratorOnTimer.abortLastDuration(mBsi, elapsedRealtimeMs);
9790             }
9791         }
9792 
9793         @Override
9794         @UnsupportedAppUsage
getWifiRunningTime(long elapsedRealtimeUs, int which)9795         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
9796             if (mWifiRunningTimer == null) {
9797                 return 0;
9798             }
9799             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9800         }
9801 
9802         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)9803         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
9804             if (mFullWifiLockTimer == null) {
9805                 return 0;
9806             }
9807             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9808         }
9809 
9810         @Override
9811         @UnsupportedAppUsage
getWifiScanTime(long elapsedRealtimeUs, int which)9812         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
9813             if (mWifiScanTimer == null) {
9814                 return 0;
9815             }
9816             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9817         }
9818 
9819         @Override
getWifiScanCount(int which)9820         public int getWifiScanCount(int which) {
9821             if (mWifiScanTimer == null) {
9822                 return 0;
9823             }
9824             return mWifiScanTimer.getCountLocked(which);
9825         }
9826 
9827         @Override
getWifiScanTimer()9828         public Timer getWifiScanTimer() {
9829             return mWifiScanTimer;
9830         }
9831 
9832         @Override
getWifiScanBackgroundCount(int which)9833         public int getWifiScanBackgroundCount(int which) {
9834             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
9835                 return 0;
9836             }
9837             return mWifiScanTimer.getSubTimer().getCountLocked(which);
9838         }
9839 
9840         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)9841         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
9842             if (mWifiScanTimer == null) {
9843                 return 0;
9844             }
9845             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
9846             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
9847         }
9848 
9849         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)9850         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
9851             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
9852                 return 0;
9853             }
9854             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
9855             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
9856         }
9857 
9858         @Override
getWifiScanBackgroundTimer()9859         public Timer getWifiScanBackgroundTimer() {
9860             if (mWifiScanTimer == null) {
9861                 return null;
9862             }
9863             return mWifiScanTimer.getSubTimer();
9864         }
9865 
9866         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)9867         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
9868             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
9869             if (mWifiBatchedScanTimer[csphBin] == null) {
9870                 return 0;
9871             }
9872             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
9873         }
9874 
9875         @Override
getWifiBatchedScanCount(int csphBin, int which)9876         public int getWifiBatchedScanCount(int csphBin, int which) {
9877             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
9878             if (mWifiBatchedScanTimer[csphBin] == null) {
9879                 return 0;
9880             }
9881             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
9882         }
9883 
9884         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)9885         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
9886             if (mWifiMulticastTimer == null) {
9887                 return 0;
9888             }
9889             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9890         }
9891 
9892         @Override
getAudioTurnedOnTimer()9893         public Timer getAudioTurnedOnTimer() {
9894             return mAudioTurnedOnTimer;
9895         }
9896 
9897         @Override
getVideoTurnedOnTimer()9898         public Timer getVideoTurnedOnTimer() {
9899             return mVideoTurnedOnTimer;
9900         }
9901 
9902         @Override
getFlashlightTurnedOnTimer()9903         public Timer getFlashlightTurnedOnTimer() {
9904             return mFlashlightTurnedOnTimer;
9905         }
9906 
9907         @Override
getCameraTurnedOnTimer()9908         public Timer getCameraTurnedOnTimer() {
9909             return mCameraTurnedOnTimer;
9910         }
9911 
9912         @Override
getForegroundActivityTimer()9913         public Timer getForegroundActivityTimer() {
9914             return mForegroundActivityTimer;
9915         }
9916 
9917         @Override
getForegroundServiceTimer()9918         public Timer getForegroundServiceTimer() {
9919             return mForegroundServiceTimer;
9920         }
9921 
9922         @Override
getBluetoothScanTimer()9923         public Timer getBluetoothScanTimer() {
9924             return mBluetoothScanTimer;
9925         }
9926 
9927         @Override
getBluetoothScanBackgroundTimer()9928         public Timer getBluetoothScanBackgroundTimer() {
9929             if (mBluetoothScanTimer == null) {
9930                 return null;
9931             }
9932             return mBluetoothScanTimer.getSubTimer();
9933         }
9934 
9935         @Override
getBluetoothUnoptimizedScanTimer()9936         public Timer getBluetoothUnoptimizedScanTimer() {
9937             return mBluetoothUnoptimizedScanTimer;
9938         }
9939 
9940         @Override
getBluetoothUnoptimizedScanBackgroundTimer()9941         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
9942             if (mBluetoothUnoptimizedScanTimer == null) {
9943                 return null;
9944             }
9945             return mBluetoothUnoptimizedScanTimer.getSubTimer();
9946         }
9947 
9948         @Override
getBluetoothScanResultCounter()9949         public Counter getBluetoothScanResultCounter() {
9950             return mBluetoothScanResultCounter;
9951         }
9952 
9953         @Override
getBluetoothScanResultBgCounter()9954         public Counter getBluetoothScanResultBgCounter() {
9955             return mBluetoothScanResultBgCounter;
9956         }
9957 
makeProcessState(int i, Parcel in)9958         void makeProcessState(int i, Parcel in) {
9959             if (i < 0 || i >= NUM_PROCESS_STATE) return;
9960 
9961             detachIfNotNull(mProcessStateTimer[i]);
9962             if (in == null) {
9963                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClock, this, PROCESS_STATE, null,
9964                         mBsi.mOnBatteryTimeBase);
9965             } else {
9966                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClock, this, PROCESS_STATE, null,
9967                         mBsi.mOnBatteryTimeBase, in);
9968             }
9969         }
9970 
9971         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)9972         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
9973             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
9974             if (mProcessStateTimer[state] == null) {
9975                 return 0;
9976             }
9977             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
9978         }
9979 
9980         @Override
getProcessStateTimer(int state)9981         public Timer getProcessStateTimer(int state) {
9982             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
9983             return mProcessStateTimer[state];
9984         }
9985 
9986         @Override
getVibratorOnTimer()9987         public Timer getVibratorOnTimer() {
9988             return mVibratorOnTimer;
9989         }
9990 
9991         @Override
noteUserActivityLocked(@owerManager.UserActivityEvent int event)9992         public void noteUserActivityLocked(@PowerManager.UserActivityEvent int event) {
9993             if (mUserActivityCounters == null) {
9994                 initUserActivityLocked();
9995             }
9996             if (event >= 0 && event < NUM_USER_ACTIVITY_TYPES) {
9997                 mUserActivityCounters[event].stepAtomic();
9998             } else {
9999                 Slog.w(TAG, "Unknown user activity type " + event + " was specified.",
10000                         new Throwable());
10001             }
10002         }
10003 
10004         @Override
hasUserActivity()10005         public boolean hasUserActivity() {
10006             return mUserActivityCounters != null;
10007         }
10008 
10009         @Override
getUserActivityCount(int type, int which)10010         public int getUserActivityCount(int type, int which) {
10011             if (mUserActivityCounters == null) {
10012                 return 0;
10013             }
10014             return mUserActivityCounters[type].getCountLocked(which);
10015         }
10016 
makeWifiBatchedScanBin(int i, Parcel in)10017         void makeWifiBatchedScanBin(int i, Parcel in) {
10018             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
10019 
10020             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
10021             if (collected == null) {
10022                 collected = new ArrayList<StopwatchTimer>();
10023                 mBsi.mWifiBatchedScanTimers.put(i, collected);
10024             }
10025             detachIfNotNull(mWifiBatchedScanTimer[i]);
10026             if (in == null) {
10027                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClock, this, WIFI_BATCHED_SCAN,
10028                         collected, mBsi.mOnBatteryTimeBase);
10029             } else {
10030                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClock, this, WIFI_BATCHED_SCAN,
10031                         collected, mBsi.mOnBatteryTimeBase, in);
10032             }
10033         }
10034 
10035 
initUserActivityLocked()10036         void initUserActivityLocked() {
10037             detachIfNotNull(mUserActivityCounters);
10038             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
10039             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
10040                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
10041             }
10042         }
10043 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)10044         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
10045             ensureNetworkActivityLocked();
10046             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
10047                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
10048                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
10049             } else {
10050                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
10051                         new Throwable());
10052             }
10053         }
10054 
noteMobileRadioActiveTimeLocked(long batteryUptimeDeltaUs, long elapsedTimeMs)10055         void noteMobileRadioActiveTimeLocked(long batteryUptimeDeltaUs, long elapsedTimeMs) {
10056             ensureNetworkActivityLocked();
10057             getMobileRadioActiveTimeCounter().increment(batteryUptimeDeltaUs, elapsedTimeMs);
10058             mMobileRadioActiveCount.addCountLocked(1);
10059         }
10060 
getMobileRadioActiveTimeCounter()10061         private TimeMultiStateCounter getMobileRadioActiveTimeCounter() {
10062             if (mMobileRadioActiveTime == null) {
10063                 final long timestampMs = mBsi.mClock.elapsedRealtime();
10064                 mMobileRadioActiveTime = new TimeMultiStateCounter(
10065                         mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
10066                 mMobileRadioActiveTime.setState(
10067                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
10068                         timestampMs);
10069                 mMobileRadioActiveTime.update(0, timestampMs);
10070             }
10071             return mMobileRadioActiveTime;
10072         }
10073 
10074         @Override
hasNetworkActivity()10075         public boolean hasNetworkActivity() {
10076             return mNetworkByteActivityCounters != null;
10077         }
10078 
10079         @Override
getNetworkActivityBytes(int type, int which)10080         public long getNetworkActivityBytes(int type, int which) {
10081             if (mNetworkByteActivityCounters != null && type >= 0
10082                     && type < mNetworkByteActivityCounters.length) {
10083                 return mNetworkByteActivityCounters[type].getCountLocked(which);
10084             } else {
10085                 return 0;
10086             }
10087         }
10088 
10089         @Override
getNetworkActivityPackets(int type, int which)10090         public long getNetworkActivityPackets(int type, int which) {
10091             if (mNetworkPacketActivityCounters != null && type >= 0
10092                     && type < mNetworkPacketActivityCounters.length) {
10093                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
10094             } else {
10095                 return 0;
10096             }
10097         }
10098 
10099         @Override
getMobileRadioActiveTime(int which)10100         public long getMobileRadioActiveTime(int which) {
10101             return getMobileRadioActiveTimeInProcessState(BatteryConsumer.PROCESS_STATE_ANY);
10102         }
10103 
10104         @Override
getMobileRadioActiveTimeInProcessState( @atteryConsumer.ProcessState int processState)10105         public long getMobileRadioActiveTimeInProcessState(
10106                 @BatteryConsumer.ProcessState int processState) {
10107             if (mMobileRadioActiveTime == null) {
10108                 return 0;
10109             }
10110             if (processState == BatteryConsumer.PROCESS_STATE_ANY) {
10111                 return mMobileRadioActiveTime.getTotalCountLocked();
10112             } else {
10113                 return mMobileRadioActiveTime.getCountForProcessState(processState);
10114             }
10115         }
10116 
10117         @Override
getMobileRadioActiveCount(int which)10118         public int getMobileRadioActiveCount(int which) {
10119             return mMobileRadioActiveCount != null
10120                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
10121         }
10122 
10123         @Override
getUserCpuTimeUs(int which)10124         public long getUserCpuTimeUs(int which) {
10125             return mUserCpuTime.getCountLocked(which);
10126         }
10127 
10128         @Override
getSystemCpuTimeUs(int which)10129         public long getSystemCpuTimeUs(int which) {
10130             return mSystemCpuTime.getCountLocked(which);
10131         }
10132 
10133         @Override
getTimeAtCpuSpeed(int cluster, int step, int which)10134         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
10135             if (mCpuClusterSpeedTimesUs != null) {
10136                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
10137                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
10138                     if (cpuSpeedTimesUs != null) {
10139                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
10140                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
10141                             if (c != null) {
10142                                 return c.getCountLocked(which);
10143                             }
10144                         }
10145                     }
10146                 }
10147             }
10148             return 0;
10149         }
10150 
noteMobileRadioApWakeupLocked()10151         public void noteMobileRadioApWakeupLocked() {
10152             if (mMobileRadioApWakeupCount == null) {
10153                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
10154             }
10155             mMobileRadioApWakeupCount.addCountLocked(1);
10156         }
10157 
10158         @Override
getMobileRadioApWakeupCount(int which)10159         public long getMobileRadioApWakeupCount(int which) {
10160             if (mMobileRadioApWakeupCount != null) {
10161                 return mMobileRadioApWakeupCount.getCountLocked(which);
10162             }
10163             return 0;
10164         }
10165 
noteWifiRadioApWakeupLocked()10166         public void noteWifiRadioApWakeupLocked() {
10167             if (mWifiRadioApWakeupCount == null) {
10168                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
10169             }
10170             mWifiRadioApWakeupCount.addCountLocked(1);
10171         }
10172 
10173         @Override
getWifiRadioApWakeupCount(int which)10174         public long getWifiRadioApWakeupCount(int which) {
10175             if (mWifiRadioApWakeupCount != null) {
10176                 return mWifiRadioApWakeupCount.getCountLocked(which);
10177             }
10178             return 0;
10179         }
10180 
10181         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)10182         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
10183             sb.setLength(0);
10184             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
10185             if (deferredEventCount == 0) {
10186                 return;
10187             }
10188             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
10189             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
10190             sb.append(deferredEventCount); sb.append(',');
10191             sb.append(deferredCount); sb.append(',');
10192             sb.append(totalLatency);
10193             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
10194                 if (mJobsFreshnessBuckets[i] == null) {
10195                     sb.append(",0");
10196                 } else {
10197                     sb.append(",");
10198                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
10199                 }
10200             }
10201         }
10202 
10203         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)10204         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
10205             sb.setLength(0);
10206             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
10207             if (deferredEventCount == 0) {
10208                 return;
10209             }
10210             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
10211             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
10212             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
10213             sb.append("count="); sb.append(deferredCount); sb.append(", ");
10214             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
10215             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
10216                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
10217                 if (mJobsFreshnessBuckets[i] == null) {
10218                     sb.append("0");
10219                 } else {
10220                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
10221                 }
10222                 sb.append(" ");
10223             }
10224         }
10225 
ensureNetworkActivityLocked()10226         void ensureNetworkActivityLocked() {
10227             if (mNetworkByteActivityCounters != null) {
10228                 return;
10229             }
10230 
10231             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
10232             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
10233             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10234                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
10235                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
10236             }
10237             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
10238         }
10239 
10240         /**
10241          * Clear all stats for this uid.  Returns true if the uid is completely
10242          * inactive so can be dropped.
10243          */
10244         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptimeUs, long realtimeUs, int resetReason)10245         public boolean reset(long uptimeUs, long realtimeUs, int resetReason) {
10246             boolean active = false;
10247 
10248             mOnBatteryBackgroundTimeBase.init(uptimeUs, realtimeUs);
10249             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeUs, realtimeUs);
10250 
10251             if (mWifiRunningTimer != null) {
10252                 active |= !mWifiRunningTimer.reset(false, realtimeUs);
10253                 active |= mWifiRunning;
10254             }
10255             if (mFullWifiLockTimer != null) {
10256                 active |= !mFullWifiLockTimer.reset(false, realtimeUs);
10257                 active |= mFullWifiLockOut;
10258             }
10259             if (mWifiScanTimer != null) {
10260                 active |= !mWifiScanTimer.reset(false, realtimeUs);
10261                 active |= mWifiScanStarted;
10262             }
10263             if (mWifiBatchedScanTimer != null) {
10264                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
10265                     if (mWifiBatchedScanTimer[i] != null) {
10266                         active |= !mWifiBatchedScanTimer[i].reset(false, realtimeUs);
10267                     }
10268                 }
10269                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
10270             }
10271             if (mWifiMulticastTimer != null) {
10272                 active |= !mWifiMulticastTimer.reset(false, realtimeUs);
10273                 active |= (mWifiMulticastWakelockCount > 0);
10274             }
10275 
10276             active |= !resetIfNotNull(mAudioTurnedOnTimer, false, realtimeUs);
10277             active |= !resetIfNotNull(mVideoTurnedOnTimer, false, realtimeUs);
10278             active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false, realtimeUs);
10279             active |= !resetIfNotNull(mCameraTurnedOnTimer, false, realtimeUs);
10280             active |= !resetIfNotNull(mForegroundActivityTimer, false, realtimeUs);
10281             active |= !resetIfNotNull(mForegroundServiceTimer, false, realtimeUs);
10282             active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false, realtimeUs);
10283             active |= !resetIfNotNull(mBluetoothScanTimer, false, realtimeUs);
10284             active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false, realtimeUs);
10285 
10286             resetIfNotNull(mBluetoothScanResultCounter, false, realtimeUs);
10287             resetIfNotNull(mBluetoothScanResultBgCounter, false, realtimeUs);
10288 
10289             if (mProcessStateTimer != null) {
10290                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
10291                     active |= !resetIfNotNull(mProcessStateTimer[i], false, realtimeUs);
10292                 }
10293                 active |= (mProcessState != Uid.PROCESS_STATE_NONEXISTENT);
10294             }
10295             if (mVibratorOnTimer != null) {
10296                 if (mVibratorOnTimer.reset(false, realtimeUs)) {
10297                     mVibratorOnTimer.detach();
10298                     mVibratorOnTimer = null;
10299                 } else {
10300                     active = true;
10301                 }
10302             }
10303 
10304             resetIfNotNull(mUserActivityCounters, false, realtimeUs);
10305 
10306             resetIfNotNull(mNetworkByteActivityCounters, false, realtimeUs);
10307             resetIfNotNull(mNetworkPacketActivityCounters, false, realtimeUs);
10308             resetIfNotNull(mMobileRadioActiveTime, false, realtimeUs);
10309             resetIfNotNull(mMobileRadioActiveCount, false, realtimeUs);
10310 
10311             resetIfNotNull(mWifiControllerActivity, false, realtimeUs);
10312             resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs);
10313             resetIfNotNull(mModemControllerActivity, false, realtimeUs);
10314 
10315             if (resetReason == RESET_REASON_MEASURED_ENERGY_BUCKETS_CHANGE) {
10316                 mUidMeasuredEnergyStats = null;
10317             } else {
10318                 MeasuredEnergyStats.resetIfNotNull(mUidMeasuredEnergyStats);
10319             }
10320 
10321             resetIfNotNull(mUserCpuTime, false, realtimeUs);
10322             resetIfNotNull(mSystemCpuTime, false, realtimeUs);
10323 
10324             resetIfNotNull(mCpuClusterSpeedTimesUs, false, realtimeUs);
10325 
10326             resetIfNotNull(mCpuFreqTimeMs, false, realtimeUs /* unused */);
10327             resetIfNotNull(mScreenOffCpuFreqTimeMs, false, realtimeUs /* unused */);
10328 
10329 
10330             resetIfNotNull(mCpuActiveTimeMs, false, realtimeUs /* unused */);
10331             resetIfNotNull(mCpuClusterTimesMs, false, realtimeUs /* unused */);
10332 
10333             resetIfNotNull(mProcStateTimeMs, false, realtimeUs /* unused */);
10334 
10335             resetIfNotNull(mProcStateScreenOffTimeMs, false, realtimeUs /* unused */);
10336 
10337             resetIfNotNull(mMobileRadioApWakeupCount, false, realtimeUs);
10338 
10339             resetIfNotNull(mWifiRadioApWakeupCount, false, realtimeUs);
10340 
10341 
10342             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
10343             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
10344                 Wakelock wl = wakeStats.valueAt(iw);
10345                 if (wl.reset(realtimeUs)) {
10346                     wakeStats.removeAt(iw);
10347                 } else {
10348                     active = true;
10349                 }
10350             }
10351             final long realtimeMs = realtimeUs / 1000;
10352             mWakelockStats.cleanup(realtimeMs);
10353             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
10354             for (int is=syncStats.size()-1; is>=0; is--) {
10355                 DualTimer timer = syncStats.valueAt(is);
10356                 if (timer.reset(false, realtimeUs)) {
10357                     syncStats.removeAt(is);
10358                     timer.detach();
10359                 } else {
10360                     active = true;
10361                 }
10362             }
10363             mSyncStats.cleanup(realtimeMs);
10364             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
10365             for (int ij=jobStats.size()-1; ij>=0; ij--) {
10366                 DualTimer timer = jobStats.valueAt(ij);
10367                 if (timer.reset(false, realtimeUs)) {
10368                     jobStats.removeAt(ij);
10369                     timer.detach();
10370                 } else {
10371                     active = true;
10372                 }
10373             }
10374             mJobStats.cleanup(realtimeMs);
10375             mJobCompletions.clear();
10376 
10377             resetIfNotNull(mJobsDeferredEventCount, false, realtimeUs);
10378             resetIfNotNull(mJobsDeferredCount, false, realtimeUs);
10379             resetIfNotNull(mJobsFreshnessTimeMs, false, realtimeUs /* unused */);
10380             resetIfNotNull(mJobsFreshnessBuckets, false, realtimeUs);
10381 
10382             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
10383                 Sensor s = mSensorStats.valueAt(ise);
10384                 if (s.reset(realtimeUs)) {
10385                     mSensorStats.removeAt(ise);
10386                 } else {
10387                     active = true;
10388                 }
10389             }
10390 
10391             for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
10392                 Proc proc = mProcessStats.valueAt(ip);
10393                 proc.detach();
10394             }
10395             mProcessStats.clear();
10396 
10397             for (int i = mPids.size() - 1; i >= 0; i--) {
10398                 Pid pid = mPids.valueAt(i);
10399                 if (pid.mWakeNesting > 0) {
10400                     active = true;
10401                 } else {
10402                     mPids.removeAt(i);
10403                 }
10404             }
10405 
10406 
10407             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
10408                 Pkg p = mPackageStats.valueAt(i);
10409                 p.detach();
10410             }
10411             mPackageStats.clear();
10412 
10413             mBinderCallCount = 0;
10414             mBinderCallStats.clear();
10415 
10416             mProportionalSystemServiceUsage = 0;
10417 
10418             mLastStepUserTimeMs = mLastStepSystemTimeMs = 0;
10419             mCurStepUserTimeMs = mCurStepSystemTimeMs = 0;
10420 
10421 
10422             return !active;
10423         }
10424 
10425         /**
10426          * This method MUST be called whenever the Uid object is destructed, otherwise it is a
10427          * memory leak in {@link TimeBase#mObservers} list.
10428          * Typically the Uid object is destructed when it is removed from
10429          * {@link BatteryStatsImpl#mUidStats}
10430          */
detachFromTimeBase()10431         void detachFromTimeBase() {
10432             detachIfNotNull(mWifiRunningTimer);
10433             detachIfNotNull(mFullWifiLockTimer);
10434             detachIfNotNull(mWifiScanTimer);
10435             detachIfNotNull(mWifiBatchedScanTimer);
10436             detachIfNotNull(mWifiMulticastTimer);
10437             detachIfNotNull(mAudioTurnedOnTimer);
10438             detachIfNotNull(mVideoTurnedOnTimer);
10439             detachIfNotNull(mFlashlightTurnedOnTimer);
10440 
10441             detachIfNotNull(mCameraTurnedOnTimer);
10442             detachIfNotNull(mForegroundActivityTimer);
10443             detachIfNotNull(mForegroundServiceTimer);
10444 
10445             detachIfNotNull(mAggregatedPartialWakelockTimer);
10446 
10447             detachIfNotNull(mBluetoothScanTimer);
10448             detachIfNotNull(mBluetoothUnoptimizedScanTimer);
10449             detachIfNotNull(mBluetoothScanResultCounter);
10450             detachIfNotNull(mBluetoothScanResultBgCounter);
10451 
10452             detachIfNotNull(mProcessStateTimer);
10453 
10454             detachIfNotNull(mVibratorOnTimer);
10455 
10456             detachIfNotNull(mUserActivityCounters);
10457 
10458             detachIfNotNull(mNetworkByteActivityCounters);
10459             detachIfNotNull(mNetworkPacketActivityCounters);
10460 
10461             detachIfNotNull(mMobileRadioActiveTime);
10462             detachIfNotNull(mMobileRadioActiveCount);
10463             detachIfNotNull(mMobileRadioApWakeupCount);
10464             detachIfNotNull(mWifiRadioApWakeupCount);
10465 
10466             detachIfNotNull(mWifiControllerActivity);
10467             detachIfNotNull(mBluetoothControllerActivity);
10468             detachIfNotNull(mModemControllerActivity);
10469 
10470             mPids.clear();
10471 
10472             detachIfNotNull(mUserCpuTime);
10473             detachIfNotNull(mSystemCpuTime);
10474 
10475             detachIfNotNull(mCpuClusterSpeedTimesUs);
10476 
10477             detachIfNotNull(mCpuActiveTimeMs);
10478             detachIfNotNull(mCpuFreqTimeMs);
10479 
10480             detachIfNotNull(mScreenOffCpuFreqTimeMs);
10481 
10482             detachIfNotNull(mCpuClusterTimesMs);
10483 
10484             detachIfNotNull(mProcStateTimeMs);
10485 
10486             detachIfNotNull(mProcStateScreenOffTimeMs);
10487 
10488             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
10489             for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
10490                 Wakelock wl = wakeStats.valueAt(iw);
10491                 wl.detachFromTimeBase();
10492             }
10493             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
10494             for (int is = syncStats.size() - 1; is >= 0; is--) {
10495                 DualTimer timer = syncStats.valueAt(is);
10496                 detachIfNotNull(timer);
10497             }
10498             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
10499             for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
10500                 DualTimer timer = jobStats.valueAt(ij);
10501                 detachIfNotNull(timer);
10502             }
10503 
10504             detachIfNotNull(mJobsDeferredEventCount);
10505             detachIfNotNull(mJobsDeferredCount);
10506             detachIfNotNull(mJobsFreshnessTimeMs);
10507             detachIfNotNull(mJobsFreshnessBuckets);
10508 
10509 
10510             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
10511                 Sensor s = mSensorStats.valueAt(ise);
10512                 s.detachFromTimeBase();
10513             }
10514 
10515             for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
10516                 Proc proc = mProcessStats.valueAt(ip);
10517                 proc.detach();
10518             }
10519             mProcessStats.clear();
10520 
10521             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
10522                 Pkg p = mPackageStats.valueAt(i);
10523                 p.detach();
10524             }
10525             mPackageStats.clear();
10526         }
10527 
writeJobCompletionsToParcelLocked(Parcel out)10528         void writeJobCompletionsToParcelLocked(Parcel out) {
10529             int NJC = mJobCompletions.size();
10530             out.writeInt(NJC);
10531             for (int ijc=0; ijc<NJC; ijc++) {
10532                 out.writeString(mJobCompletions.keyAt(ijc));
10533                 SparseIntArray types = mJobCompletions.valueAt(ijc);
10534                 int NT = types.size();
10535                 out.writeInt(NT);
10536                 for (int it=0; it<NT; it++) {
10537                     out.writeInt(types.keyAt(it));
10538                     out.writeInt(types.valueAt(it));
10539                 }
10540             }
10541         }
10542 
writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs)10543         void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
10544             mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
10545             mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
10546 
10547             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
10548             int NW = wakeStats.size();
10549             out.writeInt(NW);
10550             for (int iw=0; iw<NW; iw++) {
10551                 out.writeString(wakeStats.keyAt(iw));
10552                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
10553                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
10554             }
10555 
10556             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
10557             int NS = syncStats.size();
10558             out.writeInt(NS);
10559             for (int is=0; is<NS; is++) {
10560                 out.writeString(syncStats.keyAt(is));
10561                 DualTimer timer = syncStats.valueAt(is);
10562                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
10563             }
10564 
10565             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
10566             int NJ = jobStats.size();
10567             out.writeInt(NJ);
10568             for (int ij=0; ij<NJ; ij++) {
10569                 out.writeString(jobStats.keyAt(ij));
10570                 DualTimer timer = jobStats.valueAt(ij);
10571                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
10572             }
10573 
10574             writeJobCompletionsToParcelLocked(out);
10575 
10576             mJobsDeferredEventCount.writeToParcel(out);
10577             mJobsDeferredCount.writeToParcel(out);
10578             mJobsFreshnessTimeMs.writeToParcel(out);
10579             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
10580                 Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
10581             }
10582 
10583             int NSE = mSensorStats.size();
10584             out.writeInt(NSE);
10585             for (int ise=0; ise<NSE; ise++) {
10586                 out.writeInt(mSensorStats.keyAt(ise));
10587                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
10588                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
10589             }
10590 
10591             int NP = mProcessStats.size();
10592             out.writeInt(NP);
10593             for (int ip=0; ip<NP; ip++) {
10594                 out.writeString(mProcessStats.keyAt(ip));
10595                 Uid.Proc proc = mProcessStats.valueAt(ip);
10596                 proc.writeToParcelLocked(out);
10597             }
10598 
10599             out.writeInt(mPackageStats.size());
10600             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
10601                 out.writeString(pkgEntry.getKey());
10602                 Uid.Pkg pkg = pkgEntry.getValue();
10603                 pkg.writeToParcelLocked(out);
10604             }
10605 
10606             if (mWifiRunningTimer != null) {
10607                 out.writeInt(1);
10608                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
10609             } else {
10610                 out.writeInt(0);
10611             }
10612             if (mFullWifiLockTimer != null) {
10613                 out.writeInt(1);
10614                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
10615             } else {
10616                 out.writeInt(0);
10617             }
10618             if (mWifiScanTimer != null) {
10619                 out.writeInt(1);
10620                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
10621             } else {
10622                 out.writeInt(0);
10623             }
10624             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
10625                 if (mWifiBatchedScanTimer[i] != null) {
10626                     out.writeInt(1);
10627                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
10628                 } else {
10629                     out.writeInt(0);
10630                 }
10631             }
10632             if (mWifiMulticastTimer != null) {
10633                 out.writeInt(1);
10634                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
10635             } else {
10636                 out.writeInt(0);
10637             }
10638 
10639             if (mAudioTurnedOnTimer != null) {
10640                 out.writeInt(1);
10641                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
10642             } else {
10643                 out.writeInt(0);
10644             }
10645             if (mVideoTurnedOnTimer != null) {
10646                 out.writeInt(1);
10647                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
10648             } else {
10649                 out.writeInt(0);
10650             }
10651             if (mFlashlightTurnedOnTimer != null) {
10652                 out.writeInt(1);
10653                 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
10654             } else {
10655                 out.writeInt(0);
10656             }
10657             if (mCameraTurnedOnTimer != null) {
10658                 out.writeInt(1);
10659                 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
10660             } else {
10661                 out.writeInt(0);
10662             }
10663             if (mForegroundActivityTimer != null) {
10664                 out.writeInt(1);
10665                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
10666             } else {
10667                 out.writeInt(0);
10668             }
10669             if (mForegroundServiceTimer != null) {
10670                 out.writeInt(1);
10671                 mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
10672             } else {
10673                 out.writeInt(0);
10674             }
10675             if (mAggregatedPartialWakelockTimer != null) {
10676                 out.writeInt(1);
10677                 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
10678             } else {
10679                 out.writeInt(0);
10680             }
10681             if (mBluetoothScanTimer != null) {
10682                 out.writeInt(1);
10683                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
10684             } else {
10685                 out.writeInt(0);
10686             }
10687             if (mBluetoothUnoptimizedScanTimer != null) {
10688                 out.writeInt(1);
10689                 mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
10690             } else {
10691                 out.writeInt(0);
10692             }
10693             if (mBluetoothScanResultCounter != null) {
10694                 out.writeInt(1);
10695                 mBluetoothScanResultCounter.writeToParcel(out);
10696             } else {
10697                 out.writeInt(0);
10698             }
10699             if (mBluetoothScanResultBgCounter != null) {
10700                 out.writeInt(1);
10701                 mBluetoothScanResultBgCounter.writeToParcel(out);
10702             } else {
10703                 out.writeInt(0);
10704             }
10705             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
10706                 if (mProcessStateTimer[i] != null) {
10707                     out.writeInt(1);
10708                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
10709                 } else {
10710                     out.writeInt(0);
10711                 }
10712             }
10713             if (mVibratorOnTimer != null) {
10714                 out.writeInt(1);
10715                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
10716             } else {
10717                 out.writeInt(0);
10718             }
10719             if (mUserActivityCounters != null) {
10720                 out.writeInt(1);
10721                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
10722                     mUserActivityCounters[i].writeToParcel(out);
10723                 }
10724             } else {
10725                 out.writeInt(0);
10726             }
10727             if (mNetworkByteActivityCounters != null) {
10728                 out.writeInt(1);
10729                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10730                     mNetworkByteActivityCounters[i].writeToParcel(out);
10731                     mNetworkPacketActivityCounters[i].writeToParcel(out);
10732                 }
10733                 if (mMobileRadioActiveTime != null) {
10734                     out.writeBoolean(true);
10735                     mMobileRadioActiveTime.writeToParcel(out);
10736                 } else {
10737                     out.writeBoolean(false);
10738                 }
10739                 mMobileRadioActiveCount.writeToParcel(out);
10740             } else {
10741                 out.writeInt(0);
10742             }
10743 
10744             if (mWifiControllerActivity != null) {
10745                 out.writeInt(1);
10746                 mWifiControllerActivity.writeToParcel(out, 0);
10747             } else {
10748                 out.writeInt(0);
10749             }
10750 
10751             if (mBluetoothControllerActivity != null) {
10752                 out.writeInt(1);
10753                 mBluetoothControllerActivity.writeToParcel(out, 0);
10754             } else {
10755                 out.writeInt(0);
10756             }
10757 
10758             if (mModemControllerActivity != null) {
10759                 out.writeInt(1);
10760                 mModemControllerActivity.writeToParcel(out, 0);
10761             } else {
10762                 out.writeInt(0);
10763             }
10764 
10765             if (mUidMeasuredEnergyStats != null) {
10766                 out.writeInt(1);
10767                 mUidMeasuredEnergyStats.writeToParcel(out);
10768             } else {
10769                 out.writeInt(0);
10770             }
10771 
10772             mUserCpuTime.writeToParcel(out);
10773             mSystemCpuTime.writeToParcel(out);
10774 
10775             mBsi.writeCpuSpeedCountersToParcel(out, mCpuClusterSpeedTimesUs);
10776 
10777             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
10778             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
10779 
10780             if (mCpuActiveTimeMs != null) {
10781                 out.writeInt(mCpuActiveTimeMs.getStateCount());
10782                 mCpuActiveTimeMs.writeToParcel(out);
10783             } else {
10784                 out.writeInt(0);
10785             }
10786 
10787             mCpuClusterTimesMs.writeToParcel(out);
10788 
10789             if (mProcStateTimeMs != null) {
10790                 out.writeInt(mProcStateTimeMs.getStateCount());
10791                 mProcStateTimeMs.writeToParcel(out);
10792             } else {
10793                 out.writeInt(0);
10794             }
10795             if (mProcStateScreenOffTimeMs != null) {
10796                 out.writeInt(mProcStateScreenOffTimeMs.getStateCount());
10797                 mProcStateScreenOffTimeMs.writeToParcel(out);
10798             } else {
10799                 out.writeInt(0);
10800             }
10801 
10802             if (mMobileRadioApWakeupCount != null) {
10803                 out.writeInt(1);
10804                 mMobileRadioApWakeupCount.writeToParcel(out);
10805             } else {
10806                 out.writeInt(0);
10807             }
10808 
10809             if (mWifiRadioApWakeupCount != null) {
10810                 out.writeInt(1);
10811                 mWifiRadioApWakeupCount.writeToParcel(out);
10812             } else {
10813                 out.writeInt(0);
10814             }
10815             out.writeDouble(mProportionalSystemServiceUsage);
10816         }
10817 
readJobCompletionsFromParcelLocked(Parcel in)10818         void readJobCompletionsFromParcelLocked(Parcel in) {
10819             int numJobCompletions = in.readInt();
10820             mJobCompletions.clear();
10821             for (int j = 0; j < numJobCompletions; j++) {
10822                 String jobName = in.readString();
10823                 int numTypes = in.readInt();
10824                 if (numTypes > 0) {
10825                     SparseIntArray types = new SparseIntArray();
10826                     for (int k = 0; k < numTypes; k++) {
10827                         int type = in.readInt();
10828                         int count = in.readInt();
10829                         types.put(type, count);
10830                     }
10831                     mJobCompletions.put(jobName, types);
10832                 }
10833             }
10834         }
10835 
10836         @GuardedBy("mBsi")
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in)10837         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
10838             final long timestampMs = mBsi.mClock.elapsedRealtime();
10839             mOnBatteryBackgroundTimeBase.readFromParcel(in);
10840             mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
10841 
10842             int numWakelocks = in.readInt();
10843             mWakelockStats.clear();
10844             for (int j = 0; j < numWakelocks; j++) {
10845                 String wakelockName = in.readString();
10846                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
10847                 wakelock.readFromParcelLocked(
10848                         timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
10849                 mWakelockStats.add(wakelockName, wakelock);
10850             }
10851 
10852             int numSyncs = in.readInt();
10853             mSyncStats.clear();
10854             for (int j = 0; j < numSyncs; j++) {
10855                 String syncName = in.readString();
10856                 if (in.readInt() != 0) {
10857                     mSyncStats.add(syncName, new DualTimer(mBsi.mClock, Uid.this, SYNC, null,
10858                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
10859                 }
10860             }
10861 
10862             int numJobs = in.readInt();
10863             mJobStats.clear();
10864             for (int j = 0; j < numJobs; j++) {
10865                 String jobName = in.readString();
10866                 if (in.readInt() != 0) {
10867                     mJobStats.add(jobName, new DualTimer(mBsi.mClock, Uid.this, JOB, null,
10868                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
10869                 }
10870             }
10871 
10872             readJobCompletionsFromParcelLocked(in);
10873 
10874             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
10875             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
10876             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
10877             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
10878                 mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
10879                         in);
10880             }
10881 
10882             int numSensors = in.readInt();
10883             mSensorStats.clear();
10884             for (int k = 0; k < numSensors; k++) {
10885                 int sensorNumber = in.readInt();
10886                 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
10887                 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
10888                         in);
10889                 mSensorStats.put(sensorNumber, sensor);
10890             }
10891 
10892             int numProcs = in.readInt();
10893             mProcessStats.clear();
10894             for (int k = 0; k < numProcs; k++) {
10895                 String processName = in.readString();
10896                 Uid.Proc proc = new Proc(mBsi, processName);
10897                 proc.readFromParcelLocked(in);
10898                 mProcessStats.put(processName, proc);
10899             }
10900 
10901             int numPkgs = in.readInt();
10902             mPackageStats.clear();
10903             for (int l = 0; l < numPkgs; l++) {
10904                 String packageName = in.readString();
10905                 Uid.Pkg pkg = new Pkg(mBsi);
10906                 pkg.readFromParcelLocked(in);
10907                 mPackageStats.put(packageName, pkg);
10908             }
10909 
10910             mWifiRunning = false;
10911             if (in.readInt() != 0) {
10912                 mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, Uid.this, WIFI_RUNNING,
10913                         mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
10914             } else {
10915                 mWifiRunningTimer = null;
10916             }
10917             mFullWifiLockOut = false;
10918             if (in.readInt() != 0) {
10919                 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, Uid.this, FULL_WIFI_LOCK,
10920                         mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
10921             } else {
10922                 mFullWifiLockTimer = null;
10923             }
10924             mWifiScanStarted = false;
10925             if (in.readInt() != 0) {
10926                 mWifiScanTimer = new DualTimer(mBsi.mClock, Uid.this, WIFI_SCAN,
10927                         mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
10928                         in);
10929             } else {
10930                 mWifiScanTimer = null;
10931             }
10932             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
10933             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
10934                 if (in.readInt() != 0) {
10935                     makeWifiBatchedScanBin(i, in);
10936                 } else {
10937                     mWifiBatchedScanTimer[i] = null;
10938                 }
10939             }
10940             mWifiMulticastWakelockCount = 0;
10941             if (in.readInt() != 0) {
10942                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
10943                         WIFI_MULTICAST_ENABLED,
10944                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
10945             } else {
10946                 mWifiMulticastTimer = null;
10947             }
10948             if (in.readInt() != 0) {
10949                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, AUDIO_TURNED_ON,
10950                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
10951             } else {
10952                 mAudioTurnedOnTimer = null;
10953             }
10954             if (in.readInt() != 0) {
10955                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, VIDEO_TURNED_ON,
10956                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
10957             } else {
10958                 mVideoTurnedOnTimer = null;
10959             }
10960             if (in.readInt() != 0) {
10961                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
10962                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
10963             } else {
10964                 mFlashlightTurnedOnTimer = null;
10965             }
10966             if (in.readInt() != 0) {
10967                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, CAMERA_TURNED_ON,
10968                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
10969             } else {
10970                 mCameraTurnedOnTimer = null;
10971             }
10972             if (in.readInt() != 0) {
10973                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
10974                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
10975             } else {
10976                 mForegroundActivityTimer = null;
10977             }
10978             if (in.readInt() != 0) {
10979                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
10980                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
10981             } else {
10982                 mForegroundServiceTimer = null;
10983             }
10984             if (in.readInt() != 0) {
10985                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClock, this,
10986                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
10987                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
10988                         in);
10989             } else {
10990                 mAggregatedPartialWakelockTimer = null;
10991             }
10992             if (in.readInt() != 0) {
10993                 mBluetoothScanTimer = new DualTimer(mBsi.mClock, Uid.this, BLUETOOTH_SCAN_ON,
10994                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
10995                         mOnBatteryBackgroundTimeBase, in);
10996             } else {
10997                 mBluetoothScanTimer = null;
10998             }
10999             if (in.readInt() != 0) {
11000                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClock, Uid.this,
11001                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
11002                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
11003             } else {
11004                 mBluetoothUnoptimizedScanTimer = null;
11005             }
11006             if (in.readInt() != 0) {
11007                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
11008             } else {
11009                 mBluetoothScanResultCounter = null;
11010             }
11011             if (in.readInt() != 0) {
11012                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
11013             } else {
11014                 mBluetoothScanResultBgCounter = null;
11015             }
11016             mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
11017             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
11018                 if (in.readInt() != 0) {
11019                     makeProcessState(i, in);
11020                 } else {
11021                     mProcessStateTimer[i] = null;
11022                 }
11023             }
11024             if (in.readInt() != 0) {
11025                 mVibratorOnTimer = new BatchTimer(mBsi.mClock, Uid.this, VIBRATOR_ON,
11026                         mBsi.mOnBatteryTimeBase, in);
11027             } else {
11028                 mVibratorOnTimer = null;
11029             }
11030             if (in.readInt() != 0) {
11031                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
11032                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
11033                     mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
11034                 }
11035             } else {
11036                 mUserActivityCounters = null;
11037             }
11038             if (in.readInt() != 0) {
11039                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
11040                 mNetworkPacketActivityCounters
11041                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
11042                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11043                     mNetworkByteActivityCounters[i]
11044                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
11045                     mNetworkPacketActivityCounters[i]
11046                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
11047                 }
11048                 if (in.readBoolean()) {
11049                     mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in,
11050                             mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
11051                             timestampMs);
11052                 }
11053 
11054                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
11055             } else {
11056                 mNetworkByteActivityCounters = null;
11057                 mNetworkPacketActivityCounters = null;
11058             }
11059 
11060             if (in.readInt() != 0) {
11061                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
11062                         mBsi.mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS, in);
11063             } else {
11064                 mWifiControllerActivity = null;
11065             }
11066 
11067             if (in.readInt() != 0) {
11068                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
11069                         mBsi.mOnBatteryTimeBase, NUM_BT_TX_LEVELS, in);
11070             } else {
11071                 mBluetoothControllerActivity = null;
11072             }
11073 
11074             if (in.readInt() != 0) {
11075                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
11076                         mBsi.mOnBatteryTimeBase, ModemActivityInfo.getNumTxPowerLevels(), in);
11077             } else {
11078                 mModemControllerActivity = null;
11079             }
11080 
11081             if (in.readInt() != 0) {
11082                 mUidMeasuredEnergyStats = new MeasuredEnergyStats(mBsi.mMeasuredEnergyStatsConfig,
11083                         in);
11084             }
11085 
11086             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
11087             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
11088 
11089             mCpuClusterSpeedTimesUs = mBsi.readCpuSpeedCountersFromParcel(in);
11090 
11091             mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
11092             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
11093                     in, mBsi.mOnBatteryScreenOffTimeBase);
11094 
11095             int stateCount = in.readInt();
11096             if (stateCount != 0) {
11097                 mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in,
11098                         mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
11099                         timestampMs);
11100             }
11101             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
11102 
11103             stateCount = in.readInt();
11104             if (stateCount != 0) {
11105                 mProcStateTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
11106                         mBsi.mOnBatteryTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
11107                         mBsi.getCpuFreqCount(), mBsi.mClock.elapsedRealtime());
11108             } else {
11109                 mProcStateTimeMs = null;
11110             }
11111 
11112             stateCount = in.readInt();
11113             if (stateCount != 0) {
11114                 mProcStateScreenOffTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
11115                         mBsi.mOnBatteryScreenOffTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
11116                         mBsi.getCpuFreqCount(), mBsi.mClock.elapsedRealtime());
11117             } else {
11118                 mProcStateScreenOffTimeMs = null;
11119             }
11120 
11121             if (in.readInt() != 0) {
11122                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
11123             } else {
11124                 mMobileRadioApWakeupCount = null;
11125             }
11126 
11127             if (in.readInt() != 0) {
11128                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
11129             } else {
11130                 mWifiRadioApWakeupCount = null;
11131             }
11132 
11133             mProportionalSystemServiceUsage = in.readDouble();
11134         }
11135 
noteJobsDeferredLocked(int numDeferred, long sinceLast)11136         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
11137             mJobsDeferredEventCount.addAtomic(1);
11138             mJobsDeferredCount.addAtomic(numDeferred);
11139             if (sinceLast != 0) {
11140                 // Add the total time, which can be divided by the event count to get an average
11141                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
11142                 // Also keep track of how many times there were in these different buckets.
11143                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
11144                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
11145                         if (mJobsFreshnessBuckets[i] == null) {
11146                             mJobsFreshnessBuckets[i] = new Counter(
11147                                     mBsi.mOnBatteryTimeBase);
11148                         }
11149                         mJobsFreshnessBuckets[i].addAtomic(1);
11150                         break;
11151                     }
11152                 }
11153             }
11154         }
11155 
11156         // Reusable object used as a key to lookup values in mBinderCallStats
11157         private static BinderCallStats sTempBinderCallStats = new BinderCallStats();
11158 
11159         /**
11160          * Notes incoming binder call stats associated with this work source UID.
11161          */
noteBinderCallStatsLocked(long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)11162         public void noteBinderCallStatsLocked(long incrementalCallCount,
11163                 Collection<BinderCallsStats.CallStat> callStats) {
11164             if (DEBUG) {
11165                 Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], "
11166                         + " incrementalCallCount: " + incrementalCallCount + " callStats = ["
11167                         + new ArrayList<>(callStats) + "]");
11168             }
11169             mBinderCallCount += incrementalCallCount;
11170             for (BinderCallsStats.CallStat stat : callStats) {
11171                 BinderCallStats bcs;
11172                 sTempBinderCallStats.binderClass = stat.binderClass;
11173                 sTempBinderCallStats.transactionCode = stat.transactionCode;
11174                 int index = mBinderCallStats.indexOf(sTempBinderCallStats);
11175                 if (index >= 0) {
11176                     bcs = mBinderCallStats.valueAt(index);
11177                 } else {
11178                     bcs = new BinderCallStats();
11179                     bcs.binderClass = stat.binderClass;
11180                     bcs.transactionCode = stat.transactionCode;
11181                     mBinderCallStats.add(bcs);
11182                 }
11183 
11184                 bcs.callCount += stat.incrementalCallCount;
11185                 bcs.recordedCallCount = stat.recordedCallCount;
11186                 bcs.recordedCpuTimeMicros = stat.cpuTimeMicros;
11187             }
11188         }
11189 
11190         /**
11191          * The statistics associated with a particular wake lock.
11192          */
11193         public static class Wakelock extends BatteryStats.Uid.Wakelock {
11194             /**
11195              * BatteryStatsImpl that we are associated with.
11196              */
11197             protected BatteryStatsImpl mBsi;
11198 
11199             /**
11200              * BatteryStatsImpl that we are associated with.
11201              */
11202             protected Uid mUid;
11203 
11204             /**
11205              * How long (in ms) this uid has been keeping the device partially awake.
11206              * Tracks both the total time and the time while the app was in the background.
11207              */
11208             DualTimer mTimerPartial;
11209 
11210             /**
11211              * How long (in ms) this uid has been keeping the device fully awake.
11212              */
11213             StopwatchTimer mTimerFull;
11214 
11215             /**
11216              * How long (in ms) this uid has had a window keeping the device awake.
11217              */
11218             StopwatchTimer mTimerWindow;
11219 
11220             /**
11221              * How long (in ms) this uid has had a draw wake lock.
11222              */
11223             StopwatchTimer mTimerDraw;
11224 
Wakelock(BatteryStatsImpl bsi, Uid uid)11225             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
11226                 mBsi = bsi;
11227                 mUid = uid;
11228             }
11229 
11230             /**
11231              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
11232              * proper timer pool from the given BatteryStatsImpl object.
11233              *
11234              * @param in the Parcel to be read from.
11235              * return a new Timer, or null.
11236              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)11237             private StopwatchTimer readStopwatchTimerFromParcel(int type,
11238                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
11239                 if (in.readInt() == 0) {
11240                     return null;
11241                 }
11242 
11243                 return new StopwatchTimer(mBsi.mClock, mUid, type, pool, timeBase, in);
11244             }
11245 
11246             /**
11247              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
11248              * proper timer pool from the given BatteryStatsImpl object.
11249              *
11250              * @param in the Parcel to be read from.
11251              * return a new Timer, or null.
11252              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)11253             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
11254                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
11255                 if (in.readInt() == 0) {
11256                     return null;
11257                 }
11258 
11259                 return new DualTimer(mBsi.mClock, mUid, type, pool, timeBase, bgTimeBase, in);
11260             }
11261 
reset(long elapsedRealtimeUs)11262             boolean reset(long elapsedRealtimeUs) {
11263                 boolean wlactive = false;
11264 
11265                 wlactive |= !resetIfNotNull(mTimerFull, false, elapsedRealtimeUs);
11266                 wlactive |= !resetIfNotNull(mTimerPartial, false, elapsedRealtimeUs);
11267                 wlactive |= !resetIfNotNull(mTimerWindow, false, elapsedRealtimeUs);
11268                 wlactive |= !resetIfNotNull(mTimerDraw, false, elapsedRealtimeUs);
11269 
11270                 if (!wlactive) {
11271                     detachIfNotNull(mTimerFull);
11272                     mTimerFull = null;
11273 
11274                     detachIfNotNull(mTimerPartial);
11275                     mTimerPartial = null;
11276 
11277                     detachIfNotNull(mTimerWindow);
11278                     mTimerWindow = null;
11279 
11280                     detachIfNotNull(mTimerDraw);
11281                     mTimerDraw = null;
11282                 }
11283                 return !wlactive;
11284             }
11285 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)11286             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
11287                     TimeBase screenOffBgTimeBase, Parcel in) {
11288                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
11289                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
11290                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
11291                         mBsi.mFullTimers, timeBase, in);
11292                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
11293                         mBsi.mWindowTimers, timeBase, in);
11294                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
11295                         mBsi.mDrawTimers, timeBase, in);
11296             }
11297 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)11298             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
11299                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
11300                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
11301                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
11302                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
11303             }
11304 
11305             @Override
11306             @UnsupportedAppUsage
getWakeTime(int type)11307             public Timer getWakeTime(int type) {
11308                 switch (type) {
11309                 case WAKE_TYPE_FULL: return mTimerFull;
11310                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
11311                 case WAKE_TYPE_WINDOW: return mTimerWindow;
11312                 case WAKE_TYPE_DRAW: return mTimerDraw;
11313                 default: throw new IllegalArgumentException("type = " + type);
11314                 }
11315             }
11316 
detachFromTimeBase()11317             public void detachFromTimeBase() {
11318                 detachIfNotNull(mTimerPartial);
11319                 detachIfNotNull(mTimerFull);
11320                 detachIfNotNull(mTimerWindow);
11321                 detachIfNotNull(mTimerDraw);
11322             }
11323         }
11324 
11325         public static class Sensor extends BatteryStats.Uid.Sensor {
11326             /**
11327              * BatteryStatsImpl that we are associated with.
11328              */
11329             protected BatteryStatsImpl mBsi;
11330 
11331             /**
11332              * Uid that we are associated with.
11333              */
11334             protected Uid mUid;
11335 
11336             final int mHandle;
11337             DualTimer mTimer;
11338 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)11339             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
11340                 mBsi = bsi;
11341                 mUid = uid;
11342                 mHandle = handle;
11343             }
11344 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)11345             private DualTimer readTimersFromParcel(
11346                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
11347                 if (in.readInt() == 0) {
11348                     return null;
11349                 }
11350 
11351                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
11352                 if (pool == null) {
11353                     pool = new ArrayList<StopwatchTimer>();
11354                     mBsi.mSensorTimers.put(mHandle, pool);
11355                 }
11356                 return new DualTimer(mBsi.mClock, mUid, 0, pool, timeBase, bgTimeBase, in);
11357             }
11358 
reset(long elapsedRealtimeUs)11359             boolean reset(long elapsedRealtimeUs) {
11360                 if (mTimer.reset(true, elapsedRealtimeUs)) {
11361                     mTimer = null;
11362                     return true;
11363                 }
11364                 return false;
11365             }
11366 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)11367             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
11368                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
11369             }
11370 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)11371             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
11372                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
11373             }
11374 
11375             @Override
11376             @UnsupportedAppUsage
getSensorTime()11377             public Timer getSensorTime() {
11378                 return mTimer;
11379             }
11380 
11381             @Override
getSensorBackgroundTime()11382             public Timer getSensorBackgroundTime() {
11383                 if (mTimer == null) {
11384                     return null;
11385                 }
11386                 return mTimer.getSubTimer();
11387             }
11388 
11389             @Override
11390             @UnsupportedAppUsage
getHandle()11391             public int getHandle() {
11392                 return mHandle;
11393             }
11394 
detachFromTimeBase()11395             public void  detachFromTimeBase() {
11396                 detachIfNotNull(mTimer);
11397             }
11398         }
11399 
11400         /**
11401          * The statistics associated with a particular process.
11402          */
11403         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
11404             /**
11405              * BatteryStatsImpl that we are associated with.
11406              */
11407             protected BatteryStatsImpl mBsi;
11408 
11409             /**
11410              * The name of this process.
11411              */
11412             final String mName;
11413 
11414             /**
11415              * Remains true until removed from the stats.
11416              */
11417             boolean mActive = true;
11418 
11419             /**
11420              * Total time (in ms) spent executing in user code.
11421              */
11422             long mUserTimeMs;
11423 
11424             /**
11425              * Total time (in ms) spent executing in kernel code.
11426              */
11427             long mSystemTimeMs;
11428 
11429             /**
11430              * Amount of time (in ms) the process was running in the foreground.
11431              */
11432             long mForegroundTimeMs;
11433 
11434             /**
11435              * Number of times the process has been started.
11436              */
11437             int mStarts;
11438 
11439             /**
11440              * Number of times the process has crashed.
11441              */
11442             int mNumCrashes;
11443 
11444             /**
11445              * Number of times the process has had an ANR.
11446              */
11447             int mNumAnrs;
11448 
11449             ArrayList<ExcessivePower> mExcessivePower;
11450 
Proc(BatteryStatsImpl bsi, String name)11451             public Proc(BatteryStatsImpl bsi, String name) {
11452                 mBsi = bsi;
11453                 mName = name;
11454                 mBsi.mOnBatteryTimeBase.add(this);
11455             }
11456 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)11457             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
11458                     long baseRealtimeUs) {
11459             }
11460 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)11461             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
11462                     long baseRealtimeUs) {
11463             }
11464 
11465             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)11466             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
11467                 if (detachIfReset) {
11468                     this.detach();
11469                 }
11470                 return true;
11471             }
11472 
11473             @Override
detach()11474             public void detach() {
11475                 mActive = false;
11476                 mBsi.mOnBatteryTimeBase.remove(this);
11477             }
11478 
countExcessivePowers()11479             public int countExcessivePowers() {
11480                 return mExcessivePower != null ? mExcessivePower.size() : 0;
11481             }
11482 
getExcessivePower(int i)11483             public ExcessivePower getExcessivePower(int i) {
11484                 if (mExcessivePower != null) {
11485                     return mExcessivePower.get(i);
11486                 }
11487                 return null;
11488             }
11489 
addExcessiveCpu(long overTimeMs, long usedTimeMs)11490             public void addExcessiveCpu(long overTimeMs, long usedTimeMs) {
11491                 if (mExcessivePower == null) {
11492                     mExcessivePower = new ArrayList<ExcessivePower>();
11493                 }
11494                 ExcessivePower ew = new ExcessivePower();
11495                 ew.type = ExcessivePower.TYPE_CPU;
11496                 ew.overTime = overTimeMs;
11497                 ew.usedTime = usedTimeMs;
11498                 mExcessivePower.add(ew);
11499             }
11500 
writeExcessivePowerToParcelLocked(Parcel out)11501             void writeExcessivePowerToParcelLocked(Parcel out) {
11502                 if (mExcessivePower == null) {
11503                     out.writeInt(0);
11504                     return;
11505                 }
11506 
11507                 final int N = mExcessivePower.size();
11508                 out.writeInt(N);
11509                 for (int i=0; i<N; i++) {
11510                     ExcessivePower ew = mExcessivePower.get(i);
11511                     out.writeInt(ew.type);
11512                     out.writeLong(ew.overTime);
11513                     out.writeLong(ew.usedTime);
11514                 }
11515             }
11516 
readExcessivePowerFromParcelLocked(Parcel in)11517             void readExcessivePowerFromParcelLocked(Parcel in) {
11518                 final int N = in.readInt();
11519                 if (N == 0) {
11520                     mExcessivePower = null;
11521                     return;
11522                 }
11523 
11524                 if (N > 10000) {
11525                     throw new ParcelFormatException(
11526                             "File corrupt: too many excessive power entries " + N);
11527                 }
11528 
11529                 mExcessivePower = new ArrayList<>();
11530                 for (int i=0; i<N; i++) {
11531                     ExcessivePower ew = new ExcessivePower();
11532                     ew.type = in.readInt();
11533                     ew.overTime = in.readLong();
11534                     ew.usedTime = in.readLong();
11535                     mExcessivePower.add(ew);
11536                 }
11537             }
11538 
writeToParcelLocked(Parcel out)11539             void writeToParcelLocked(Parcel out) {
11540                 out.writeLong(mUserTimeMs);
11541                 out.writeLong(mSystemTimeMs);
11542                 out.writeLong(mForegroundTimeMs);
11543                 out.writeInt(mStarts);
11544                 out.writeInt(mNumCrashes);
11545                 out.writeInt(mNumAnrs);
11546                 writeExcessivePowerToParcelLocked(out);
11547             }
11548 
readFromParcelLocked(Parcel in)11549             void readFromParcelLocked(Parcel in) {
11550                 mUserTimeMs = in.readLong();
11551                 mSystemTimeMs = in.readLong();
11552                 mForegroundTimeMs = in.readLong();
11553                 mStarts = in.readInt();
11554                 mNumCrashes = in.readInt();
11555                 mNumAnrs = in.readInt();
11556                 readExcessivePowerFromParcelLocked(in);
11557             }
11558 
11559             @UnsupportedAppUsage
addCpuTimeLocked(int utimeMs, int stimeMs)11560             public void addCpuTimeLocked(int utimeMs, int stimeMs) {
11561                 addCpuTimeLocked(utimeMs, stimeMs, mBsi.mOnBatteryTimeBase.isRunning());
11562             }
11563 
addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning)11564             public void addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning) {
11565                 if (isRunning) {
11566                     mUserTimeMs += utimeMs;
11567                     mSystemTimeMs += stimeMs;
11568                 }
11569             }
11570 
11571             @UnsupportedAppUsage
addForegroundTimeLocked(long ttimeMs)11572             public void addForegroundTimeLocked(long ttimeMs) {
11573                 mForegroundTimeMs += ttimeMs;
11574             }
11575 
11576             @UnsupportedAppUsage
incStartsLocked()11577             public void incStartsLocked() {
11578                 mStarts++;
11579             }
11580 
incNumCrashesLocked()11581             public void incNumCrashesLocked() {
11582                 mNumCrashes++;
11583             }
11584 
incNumAnrsLocked()11585             public void incNumAnrsLocked() {
11586                 mNumAnrs++;
11587             }
11588 
11589             @Override
isActive()11590             public boolean isActive() {
11591                 return mActive;
11592             }
11593 
11594             @Override
11595             @UnsupportedAppUsage
getUserTime(int which)11596             public long getUserTime(int which) {
11597                 return mUserTimeMs;
11598             }
11599 
11600             @Override
11601             @UnsupportedAppUsage
getSystemTime(int which)11602             public long getSystemTime(int which) {
11603                 return mSystemTimeMs;
11604             }
11605 
11606             @Override
11607             @UnsupportedAppUsage
getForegroundTime(int which)11608             public long getForegroundTime(int which) {
11609                 return mForegroundTimeMs;
11610             }
11611 
11612             @Override
11613             @UnsupportedAppUsage
getStarts(int which)11614             public int getStarts(int which) {
11615                 return mStarts;
11616             }
11617 
11618             @Override
getNumCrashes(int which)11619             public int getNumCrashes(int which) {
11620                 return mNumCrashes;
11621             }
11622 
11623             @Override
getNumAnrs(int which)11624             public int getNumAnrs(int which) {
11625                 return mNumAnrs;
11626             }
11627         }
11628 
11629         /**
11630          * The statistics associated with a particular package.
11631          */
11632         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
11633             /**
11634              * BatteryStatsImpl that we are associated with.
11635              */
11636             protected BatteryStatsImpl mBsi;
11637 
11638             /**
11639              * Number of times wakeup alarms have occurred for this app.
11640              * On screen-off timebase starting in report v25.
11641              */
11642             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
11643 
11644             /**
11645              * The statics we have collected for this package's services.
11646              */
11647             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
11648 
Pkg(BatteryStatsImpl bsi)11649             public Pkg(BatteryStatsImpl bsi) {
11650                 mBsi = bsi;
11651                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
11652             }
11653 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)11654             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
11655                     long baseRealtimeUs) {
11656             }
11657 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)11658             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
11659                     long baseRealtimeUs) {
11660             }
11661 
11662             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)11663             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
11664                 if (detachIfReset) {
11665                     this.detach();
11666                 }
11667                 return true;
11668             }
11669 
11670             @Override
detach()11671             public void detach() {
11672                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
11673                 for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
11674                     detachIfNotNull(mWakeupAlarms.valueAt(j));
11675                 }
11676                 for (int j = mServiceStats.size() - 1; j >= 0; j--) {
11677                     detachIfNotNull(mServiceStats.valueAt(j));
11678                 }
11679             }
11680 
readFromParcelLocked(Parcel in)11681             void readFromParcelLocked(Parcel in) {
11682                 int numWA = in.readInt();
11683                 mWakeupAlarms.clear();
11684                 for (int i=0; i<numWA; i++) {
11685                     String tag = in.readString();
11686                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
11687                 }
11688 
11689                 int numServs = in.readInt();
11690                 mServiceStats.clear();
11691                 for (int m = 0; m < numServs; m++) {
11692                     String serviceName = in.readString();
11693                     Uid.Pkg.Serv serv = new Serv(mBsi);
11694                     mServiceStats.put(serviceName, serv);
11695 
11696                     serv.readFromParcelLocked(in);
11697                 }
11698             }
11699 
writeToParcelLocked(Parcel out)11700             void writeToParcelLocked(Parcel out) {
11701                 int numWA = mWakeupAlarms.size();
11702                 out.writeInt(numWA);
11703                 for (int i=0; i<numWA; i++) {
11704                     out.writeString(mWakeupAlarms.keyAt(i));
11705                     mWakeupAlarms.valueAt(i).writeToParcel(out);
11706                 }
11707 
11708                 final int NS = mServiceStats.size();
11709                 out.writeInt(NS);
11710                 for (int i=0; i<NS; i++) {
11711                     out.writeString(mServiceStats.keyAt(i));
11712                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
11713                     serv.writeToParcelLocked(out);
11714                 }
11715             }
11716 
11717             @Override
getWakeupAlarmStats()11718             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
11719                 return mWakeupAlarms;
11720             }
11721 
noteWakeupAlarmLocked(String tag)11722             public void noteWakeupAlarmLocked(String tag) {
11723                 Counter c = mWakeupAlarms.get(tag);
11724                 if (c == null) {
11725                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
11726                     mWakeupAlarms.put(tag, c);
11727                 }
11728                 c.stepAtomic();
11729             }
11730 
11731             @Override
getServiceStats()11732             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
11733                 return mServiceStats;
11734             }
11735 
11736             /**
11737              * The statistics associated with a particular service.
11738              */
11739             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
11740                 /**
11741                  * BatteryStatsImpl that we are associated with.
11742                  */
11743                 protected BatteryStatsImpl mBsi;
11744 
11745                 /**
11746                  * The android package in which this service resides.
11747                  */
11748                 protected Pkg mPkg;
11749 
11750                 /**
11751                  * Total time (ms in battery uptime) the service has been left started.
11752                  */
11753                 protected long mStartTimeMs;
11754 
11755                 /**
11756                  * If service has been started and not yet stopped, this is
11757                  * when it was started.
11758                  */
11759                 protected long mRunningSinceMs;
11760 
11761                 /**
11762                  * True if we are currently running.
11763                  */
11764                 protected boolean mRunning;
11765 
11766                 /**
11767                  * Total number of times startService() has been called.
11768                  */
11769                 protected int mStarts;
11770 
11771                 /**
11772                  * Total time (ms in battery uptime) the service has been left launched.
11773                  */
11774                 protected long mLaunchedTimeMs;
11775 
11776                 /**
11777                  * If service has been launched and not yet exited, this is
11778                  * when it was launched (ms in battery uptime).
11779                  */
11780                 protected long mLaunchedSinceMs;
11781 
11782                 /**
11783                  * True if we are currently launched.
11784                  */
11785                 protected boolean mLaunched;
11786 
11787                 /**
11788                  * Total number times the service has been launched.
11789                  */
11790                 protected int mLaunches;
11791 
11792                 /**
11793                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
11794                  */
Serv(BatteryStatsImpl bsi)11795                 public Serv(BatteryStatsImpl bsi) {
11796                     mBsi = bsi;
11797                     mBsi.mOnBatteryTimeBase.add(this);
11798                 }
11799 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)11800                 public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
11801                         long baseRealtimeUs) {
11802                 }
11803 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)11804                 public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
11805                         long baseRealtimeUs) {
11806                 }
11807 
11808                 @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)11809                 public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
11810                     if (detachIfReset) {
11811                         this.detach();
11812                     }
11813                     return true;
11814                 }
11815 
11816                 /**
11817                  * Remove this Serv as a listener from the time base.
11818                  Ms*/
11819                 @Override
detach()11820                 public void detach() {
11821                     mBsi.mOnBatteryTimeBase.remove(this);
11822                 }
11823 
readFromParcelLocked(Parcel in)11824                 public void readFromParcelLocked(Parcel in) {
11825                     mStartTimeMs = in.readLong();
11826                     mRunningSinceMs = in.readLong();
11827                     mRunning = in.readInt() != 0;
11828                     mStarts = in.readInt();
11829                     mLaunchedTimeMs = in.readLong();
11830                     mLaunchedSinceMs = in.readLong();
11831                     mLaunched = in.readInt() != 0;
11832                     mLaunches = in.readInt();
11833                 }
11834 
writeToParcelLocked(Parcel out)11835                 public void writeToParcelLocked(Parcel out) {
11836                     out.writeLong(mStartTimeMs);
11837                     out.writeLong(mRunningSinceMs);
11838                     out.writeInt(mRunning ? 1 : 0);
11839                     out.writeInt(mStarts);
11840                     out.writeLong(mLaunchedTimeMs);
11841                     out.writeLong(mLaunchedSinceMs);
11842                     out.writeInt(mLaunched ? 1 : 0);
11843                     out.writeInt(mLaunches);
11844                 }
11845 
getLaunchTimeToNowLocked(long batteryUptimeMs)11846                 public long getLaunchTimeToNowLocked(long batteryUptimeMs) {
11847                     if (!mLaunched) return mLaunchedTimeMs;
11848                     return mLaunchedTimeMs + batteryUptimeMs - mLaunchedSinceMs;
11849                 }
11850 
getStartTimeToNowLocked(long batteryUptimeMs)11851                 public long getStartTimeToNowLocked(long batteryUptimeMs) {
11852                     if (!mRunning) return mStartTimeMs;
11853                     return mStartTimeMs + batteryUptimeMs - mRunningSinceMs;
11854                 }
11855 
11856                 @UnsupportedAppUsage
startLaunchedLocked()11857                 public void startLaunchedLocked() {
11858                     startLaunchedLocked(mBsi.mClock.uptimeMillis());
11859                 }
11860 
startLaunchedLocked(long uptimeMs)11861                 public void startLaunchedLocked(long uptimeMs) {
11862                     if (!mLaunched) {
11863                         mLaunches++;
11864                         mLaunchedSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
11865                         mLaunched = true;
11866                     }
11867                 }
11868 
11869                 @UnsupportedAppUsage
stopLaunchedLocked()11870                 public void stopLaunchedLocked() {
11871                     stopLaunchedLocked(mBsi.mClock.uptimeMillis());
11872                 }
11873 
stopLaunchedLocked(long uptimeMs)11874                 public void stopLaunchedLocked(long uptimeMs) {
11875                     if (mLaunched) {
11876                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
11877                                 - mLaunchedSinceMs;
11878                         if (timeMs > 0) {
11879                             mLaunchedTimeMs += timeMs;
11880                         } else {
11881                             mLaunches--;
11882                         }
11883                         mLaunched = false;
11884                     }
11885                 }
11886 
11887                 @UnsupportedAppUsage
startRunningLocked()11888                 public void startRunningLocked() {
11889                     startRunningLocked(mBsi.mClock.uptimeMillis());
11890                 }
11891 
startRunningLocked(long uptimeMs)11892                 public void startRunningLocked(long uptimeMs) {
11893                     if (!mRunning) {
11894                         mStarts++;
11895                         mRunningSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
11896                         mRunning = true;
11897                     }
11898                 }
11899 
11900                 @UnsupportedAppUsage
stopRunningLocked()11901                 public void stopRunningLocked() {
11902                     stopRunningLocked(mBsi.mClock.uptimeMillis());
11903                 }
11904 
stopRunningLocked(long uptimeMs)11905                 public void stopRunningLocked(long uptimeMs) {
11906                     if (mRunning) {
11907                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
11908                                 - mRunningSinceMs;
11909                         if (timeMs > 0) {
11910                             mStartTimeMs += timeMs;
11911                         } else {
11912                             mStarts--;
11913                         }
11914                         mRunning = false;
11915                     }
11916                 }
11917 
11918                 @UnsupportedAppUsage
getBatteryStats()11919                 public BatteryStatsImpl getBatteryStats() {
11920                     return mBsi;
11921                 }
11922 
11923                 @Override
getLaunches(int which)11924                 public int getLaunches(int which) {
11925                     return mLaunches;
11926                 }
11927 
11928                 @Override
getStartTime(long now, int which)11929                 public long getStartTime(long now, int which) {
11930                     return getStartTimeToNowLocked(now);
11931                 }
11932 
11933                 @Override
getStarts(int which)11934                 public int getStarts(int which) {
11935                     return mStarts;
11936                 }
11937             }
11938 
newServiceStatsLocked()11939             final Serv newServiceStatsLocked() {
11940                 return new Serv(mBsi);
11941             }
11942         }
11943 
11944         private class ChildUid {
11945             public final TimeMultiStateCounter cpuActiveCounter;
11946             public final LongArrayMultiStateCounter cpuTimeInFreqCounter;
11947 
ChildUid()11948             ChildUid() {
11949                 final long timestampMs = mBsi.mClock.elapsedRealtime();
11950                 cpuActiveCounter =
11951                         new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase, 1, timestampMs);
11952                 cpuActiveCounter.setState(0, timestampMs);
11953 
11954                 if (mBsi.trackPerProcStateCpuTimes()) {
11955                     final int cpuFreqCount = mBsi.getCpuFreqCount();
11956 
11957                     cpuTimeInFreqCounter = new LongArrayMultiStateCounter(1, cpuFreqCount);
11958 
11959                     // Set initial values to all 0. This is a child UID and we want to include
11960                     // the entirety of its CPU time-in-freq stats into the parent's stats.
11961                     cpuTimeInFreqCounter.updateValues(
11962                             new LongArrayMultiStateCounter.LongArrayContainer(cpuFreqCount),
11963                             timestampMs);
11964                 } else {
11965                     cpuTimeInFreqCounter = null;
11966                 }
11967             }
11968         }
11969 
11970         /**
11971          * Retrieve the statistics object for a particular process, creating
11972          * if needed.
11973          */
getProcessStatsLocked(String name)11974         public Proc getProcessStatsLocked(String name) {
11975             Proc ps = mProcessStats.get(name);
11976             if (ps == null) {
11977                 ps = new Proc(mBsi, name);
11978                 mProcessStats.put(name, ps);
11979             }
11980 
11981             return ps;
11982         }
11983 
11984         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState, long elapsedRealtimeMs, long uptimeMs)11985         public void updateUidProcessStateLocked(int procState,
11986                 long elapsedRealtimeMs, long uptimeMs) {
11987             int uidRunningState;
11988             // Make special note of Foreground Services
11989             final boolean userAwareService =
11990                     (ActivityManager.isForegroundService(procState));
11991             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
11992 
11993             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
11994                 return;
11995             }
11996 
11997             if (mProcessState != uidRunningState) {
11998                 if (mProcessState != Uid.PROCESS_STATE_NONEXISTENT) {
11999                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
12000                 }
12001                 if (uidRunningState != Uid.PROCESS_STATE_NONEXISTENT) {
12002                     if (mProcessStateTimer[uidRunningState] == null) {
12003                         makeProcessState(uidRunningState, null);
12004                     }
12005                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
12006                 }
12007 
12008                 if (mBsi.trackPerProcStateCpuTimes()) {
12009                     mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs);
12010 
12011                     LongArrayMultiStateCounter onBatteryCounter =
12012                             getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
12013                     LongArrayMultiStateCounter onBatteryScreenOffCounter =
12014                             getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
12015 
12016                     onBatteryCounter.setState(uidRunningState, elapsedRealtimeMs);
12017                     onBatteryScreenOffCounter.setState(uidRunningState, elapsedRealtimeMs);
12018                 }
12019 
12020                 final int prevBatteryConsumerProcessState =
12021                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState);
12022 
12023                 mProcessState = uidRunningState;
12024 
12025                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
12026                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
12027 
12028                 final int batteryConsumerProcessState =
12029                         mapUidProcessStateToBatteryConsumerProcessState(uidRunningState);
12030                 getCpuActiveTimeCounter().setState(batteryConsumerProcessState, elapsedRealtimeMs);
12031 
12032                 getMobileRadioActiveTimeCounter()
12033                         .setState(batteryConsumerProcessState, elapsedRealtimeMs);
12034 
12035                 final ControllerActivityCounterImpl wifiControllerActivity =
12036                         getWifiControllerActivity();
12037                 if (wifiControllerActivity != null) {
12038                     wifiControllerActivity.setState(batteryConsumerProcessState, elapsedRealtimeMs);
12039                 }
12040 
12041                 final ControllerActivityCounterImpl bluetoothControllerActivity =
12042                         getBluetoothControllerActivity();
12043                 if (bluetoothControllerActivity != null) {
12044                     bluetoothControllerActivity.setState(batteryConsumerProcessState,
12045                             elapsedRealtimeMs);
12046                 }
12047 
12048                 final MeasuredEnergyStats energyStats =
12049                         getOrCreateMeasuredEnergyStatsIfSupportedLocked();
12050                 if (energyStats != null) {
12051                     energyStats.setState(batteryConsumerProcessState, elapsedRealtimeMs);
12052                 }
12053                 maybeScheduleExternalStatsSync(prevBatteryConsumerProcessState,
12054                         batteryConsumerProcessState);
12055             }
12056 
12057             if (userAwareService != mInForegroundService) {
12058                 if (userAwareService) {
12059                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
12060                 } else {
12061                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
12062                 }
12063                 mInForegroundService = userAwareService;
12064             }
12065         }
12066 
12067         @GuardedBy("mBsi")
maybeScheduleExternalStatsSync( @atteryConsumer.ProcessState int oldProcessState, @BatteryConsumer.ProcessState int newProcessState)12068         private void maybeScheduleExternalStatsSync(
12069                 @BatteryConsumer.ProcessState int oldProcessState,
12070                 @BatteryConsumer.ProcessState int newProcessState) {
12071             if (oldProcessState == newProcessState) {
12072                 return;
12073             }
12074             // Transitions between BACKGROUND and such non-foreground states like cached
12075             // or nonexistent do not warrant doing a sync.  If some of the stats for those
12076             // proc states bleed into the PROCESS_STATE_BACKGROUND, that's ok.
12077             if ((oldProcessState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED
12078                     && newProcessState == BatteryConsumer.PROCESS_STATE_BACKGROUND)
12079                     || (oldProcessState == BatteryConsumer.PROCESS_STATE_BACKGROUND
12080                     && newProcessState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED)) {
12081                 return;
12082             }
12083 
12084             int flags = ExternalStatsSync.UPDATE_ON_PROC_STATE_CHANGE;
12085             // Skip querying for inactive radio, where power usage is probably negligible.
12086             if (!BatteryStatsImpl.isActiveRadioPowerState(mBsi.mMobileRadioPowerState)) {
12087                 flags &= ~ExternalStatsSync.UPDATE_RADIO;
12088             }
12089 
12090             mBsi.mExternalSync.scheduleSyncDueToProcessStateChange(flags,
12091                     mBsi.mConstants.PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
12092         }
12093 
12094         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()12095         public boolean isInBackground() {
12096             // Note that PROCESS_STATE_CACHED and Uid.PROCESS_STATE_NONEXISTENT is
12097             // also considered to be 'background' for our purposes, because it's not foreground.
12098             return mProcessState >= PROCESS_STATE_BACKGROUND;
12099         }
12100 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)12101         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
12102             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
12103             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
12104         }
12105 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)12106         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
12107             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
12108             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
12109         }
12110 
getPidStats()12111         public SparseArray<? extends Pid> getPidStats() {
12112             return mPids;
12113         }
12114 
getPidStatsLocked(int pid)12115         public Pid getPidStatsLocked(int pid) {
12116             Pid p = mPids.get(pid);
12117             if (p == null) {
12118                 p = new Pid();
12119                 mPids.put(pid, p);
12120             }
12121             return p;
12122         }
12123 
12124         /**
12125          * Retrieve the statistics object for a particular service, creating
12126          * if needed.
12127          */
getPackageStatsLocked(String name)12128         public Pkg getPackageStatsLocked(String name) {
12129             Pkg ps = mPackageStats.get(name);
12130             if (ps == null) {
12131                 ps = new Pkg(mBsi);
12132                 mPackageStats.put(name, ps);
12133             }
12134 
12135             return ps;
12136         }
12137 
12138         /**
12139          * Retrieve the statistics object for a particular service, creating
12140          * if needed.
12141          */
getServiceStatsLocked(String pkg, String serv)12142         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
12143             Pkg ps = getPackageStatsLocked(pkg);
12144             Pkg.Serv ss = ps.mServiceStats.get(serv);
12145             if (ss == null) {
12146                 ss = ps.newServiceStatsLocked();
12147                 ps.mServiceStats.put(serv, ss);
12148             }
12149 
12150             return ss;
12151         }
12152 
readSyncSummaryFromParcelLocked(String name, Parcel in)12153         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
12154             DualTimer timer = mSyncStats.instantiateObject();
12155             timer.readSummaryFromParcelLocked(in);
12156             mSyncStats.add(name, timer);
12157         }
12158 
readJobSummaryFromParcelLocked(String name, Parcel in)12159         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
12160             DualTimer timer = mJobStats.instantiateObject();
12161             timer.readSummaryFromParcelLocked(in);
12162             mJobStats.add(name, timer);
12163         }
12164 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)12165         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
12166             Wakelock wl = new Wakelock(mBsi, this);
12167             mWakelockStats.add(wlName, wl);
12168             if (in.readInt() != 0) {
12169                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
12170             }
12171             if (in.readInt() != 0) {
12172                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
12173             }
12174             if (in.readInt() != 0) {
12175                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
12176             }
12177             if (in.readInt() != 0) {
12178                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
12179             }
12180         }
12181 
getSensorTimerLocked(int sensor, boolean create)12182         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
12183             Sensor se = mSensorStats.get(sensor);
12184             if (se == null) {
12185                 if (!create) {
12186                     return null;
12187                 }
12188                 se = new Sensor(mBsi, this, sensor);
12189                 mSensorStats.put(sensor, se);
12190             }
12191             DualTimer t = se.mTimer;
12192             if (t != null) {
12193                 return t;
12194             }
12195             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
12196             if (timers == null) {
12197                 timers = new ArrayList<StopwatchTimer>();
12198                 mBsi.mSensorTimers.put(sensor, timers);
12199             }
12200             t = new DualTimer(mBsi.mClock, this, BatteryStats.SENSOR, timers,
12201                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
12202             se.mTimer = t;
12203             return t;
12204         }
12205 
noteStartSyncLocked(String name, long elapsedRealtimeMs)12206         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
12207             DualTimer t = mSyncStats.startObject(name, elapsedRealtimeMs);
12208             if (t != null) {
12209                 t.startRunningLocked(elapsedRealtimeMs);
12210             }
12211         }
12212 
noteStopSyncLocked(String name, long elapsedRealtimeMs)12213         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
12214             DualTimer t = mSyncStats.stopObject(name, elapsedRealtimeMs);
12215             if (t != null) {
12216                 t.stopRunningLocked(elapsedRealtimeMs);
12217             }
12218         }
12219 
noteStartJobLocked(String name, long elapsedRealtimeMs)12220         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
12221             DualTimer t = mJobStats.startObject(name, elapsedRealtimeMs);
12222             if (t != null) {
12223                 t.startRunningLocked(elapsedRealtimeMs);
12224             }
12225         }
12226 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)12227         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
12228             DualTimer t = mJobStats.stopObject(name, elapsedRealtimeMs);
12229             if (t != null) {
12230                 t.stopRunningLocked(elapsedRealtimeMs);
12231             }
12232             if (mBsi.mOnBatteryTimeBase.isRunning()) {
12233                 SparseIntArray types = mJobCompletions.get(name);
12234                 if (types == null) {
12235                     types = new SparseIntArray();
12236                     mJobCompletions.put(name, types);
12237                 }
12238                 int last = types.get(stopReason, 0);
12239                 types.put(stopReason, last + 1);
12240             }
12241         }
12242 
getWakelockTimerLocked(Wakelock wl, int type)12243         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
12244             if (wl == null) {
12245                 return null;
12246             }
12247             switch (type) {
12248                 case WAKE_TYPE_PARTIAL: {
12249                     DualTimer t = wl.mTimerPartial;
12250                     if (t == null) {
12251                         t = new DualTimer(mBsi.mClock, this, WAKE_TYPE_PARTIAL,
12252                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
12253                                 mOnBatteryScreenOffBackgroundTimeBase);
12254                         wl.mTimerPartial = t;
12255                     }
12256                     return t;
12257                 }
12258                 case WAKE_TYPE_FULL: {
12259                     StopwatchTimer t = wl.mTimerFull;
12260                     if (t == null) {
12261                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_FULL,
12262                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
12263                         wl.mTimerFull = t;
12264                     }
12265                     return t;
12266                 }
12267                 case WAKE_TYPE_WINDOW: {
12268                     StopwatchTimer t = wl.mTimerWindow;
12269                     if (t == null) {
12270                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_WINDOW,
12271                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
12272                         wl.mTimerWindow = t;
12273                     }
12274                     return t;
12275                 }
12276                 case WAKE_TYPE_DRAW: {
12277                     StopwatchTimer t = wl.mTimerDraw;
12278                     if (t == null) {
12279                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_DRAW,
12280                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
12281                         wl.mTimerDraw = t;
12282                     }
12283                     return t;
12284                 }
12285                 default:
12286                     throw new IllegalArgumentException("type=" + type);
12287             }
12288         }
12289 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)12290         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
12291             Wakelock wl = mWakelockStats.startObject(name, elapsedRealtimeMs);
12292             if (wl != null) {
12293                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
12294             }
12295             if (type == WAKE_TYPE_PARTIAL) {
12296                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
12297                 if (pid >= 0) {
12298                     Pid p = getPidStatsLocked(pid);
12299                     if (p.mWakeNesting++ == 0) {
12300                         p.mWakeStartMs = elapsedRealtimeMs;
12301                     }
12302                 }
12303             }
12304         }
12305 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)12306         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
12307             Wakelock wl = mWakelockStats.stopObject(name, elapsedRealtimeMs);
12308             if (wl != null) {
12309                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
12310                 wlt.stopRunningLocked(elapsedRealtimeMs);
12311             }
12312             if (type == WAKE_TYPE_PARTIAL) {
12313                 if (mAggregatedPartialWakelockTimer != null) {
12314                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
12315                 }
12316                 if (pid >= 0) {
12317                     Pid p = mPids.get(pid);
12318                     if (p != null && p.mWakeNesting > 0) {
12319                         if (p.mWakeNesting-- == 1) {
12320                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
12321                             p.mWakeStartMs = 0;
12322                         }
12323                     }
12324                 }
12325             }
12326         }
12327 
reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs)12328         public void reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs) {
12329             Proc p = getProcessStatsLocked(proc);
12330             if (p != null) {
12331                 p.addExcessiveCpu(overTimeMs, usedTimeMs);
12332             }
12333         }
12334 
noteStartSensor(int sensor, long elapsedRealtimeMs)12335         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
12336             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
12337             t.startRunningLocked(elapsedRealtimeMs);
12338         }
12339 
noteStopSensor(int sensor, long elapsedRealtimeMs)12340         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
12341             // Don't create a timer if one doesn't already exist
12342             DualTimer t = getSensorTimerLocked(sensor, false);
12343             if (t != null) {
12344                 t.stopRunningLocked(elapsedRealtimeMs);
12345             }
12346         }
12347 
noteStartGps(long elapsedRealtimeMs)12348         public void noteStartGps(long elapsedRealtimeMs) {
12349             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
12350         }
12351 
noteStopGps(long elapsedRealtimeMs)12352         public void noteStopGps(long elapsedRealtimeMs) {
12353             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
12354         }
12355 
getBatteryStats()12356         public BatteryStatsImpl getBatteryStats() {
12357             return mBsi;
12358         }
12359     }
12360 
12361     @GuardedBy("this")
12362     @Override
getCpuFreqs()12363     public long[] getCpuFreqs() {
12364         if (!mCpuFreqsInitialized) {
12365             mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
12366             mCpuFreqsInitialized = true;
12367         }
12368         return mCpuFreqs;
12369     }
12370 
12371     @GuardedBy("this")
12372     @Override
getCpuFreqCount()12373     public int getCpuFreqCount() {
12374         final long[] cpuFreqs = getCpuFreqs();
12375         return cpuFreqs != null ? cpuFreqs.length : 0;
12376     }
12377 
12378     @GuardedBy("this")
getCpuTimeInFreqContainer()12379     private LongArrayMultiStateCounter.LongArrayContainer getCpuTimeInFreqContainer() {
12380         if (mTmpCpuTimeInFreq == null) {
12381             mTmpCpuTimeInFreq =
12382                     new LongArrayMultiStateCounter.LongArrayContainer(getCpuFreqCount());
12383         }
12384         return mTmpCpuTimeInFreq;
12385     }
12386 
BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider)12387     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
12388             MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider) {
12389         this(Clock.SYSTEM_CLOCK, systemDir, handler, cb, energyStatsCb, userInfoProvider);
12390     }
12391 
BatteryStatsImpl(Clock clock, File systemDir, Handler handler, PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider)12392     private BatteryStatsImpl(Clock clock, File systemDir, Handler handler,
12393             PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb,
12394             UserInfoProvider userInfoProvider) {
12395         init(clock);
12396 
12397         if (systemDir == null) {
12398             mStatsFile = null;
12399             mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
12400         } else {
12401             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
12402             mBatteryStatsHistory = new BatteryStatsHistory(this, systemDir, mHistoryBuffer);
12403         }
12404         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
12405         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
12406         mHandler = new MyHandler(handler.getLooper());
12407         mConstants = new Constants(mHandler);
12408         mStartCount++;
12409         initTimersAndCounters();
12410         mOnBattery = mOnBatteryInternal = false;
12411         long uptimeUs = mClock.uptimeMillis() * 1000;
12412         long realtimeUs = mClock.elapsedRealtime() * 1000;
12413         initTimes(uptimeUs, realtimeUs);
12414         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
12415         initDischarge(realtimeUs);
12416         clearHistoryLocked();
12417         updateDailyDeadlineLocked();
12418         mPlatformIdleStateCallback = cb;
12419         mMeasuredEnergyRetriever = energyStatsCb;
12420         mUserInfoProvider = userInfoProvider;
12421 
12422         // Notify statsd that the system is initially not in doze.
12423         mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
12424         FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
12425     }
12426 
12427     @VisibleForTesting
initTimersAndCounters()12428     protected void initTimersAndCounters() {
12429         mScreenOnTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
12430         mScreenDozeTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
12431         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
12432             mScreenBrightnessTimer[i] = new StopwatchTimer(mClock, null, -100 - i, null,
12433                     mOnBatteryTimeBase);
12434         }
12435 
12436         mPerDisplayBatteryStats = new DisplayBatteryStats[1];
12437         mPerDisplayBatteryStats[0] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
12438 
12439         mInteractiveTimer = new StopwatchTimer(mClock, null, -10, null, mOnBatteryTimeBase);
12440         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClock, null, -2, null,
12441                 mOnBatteryTimeBase);
12442         mDeviceIdleModeLightTimer = new StopwatchTimer(mClock, null, -11, null,
12443                 mOnBatteryTimeBase);
12444         mDeviceIdleModeFullTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase);
12445         mDeviceLightIdlingTimer = new StopwatchTimer(mClock, null, -15, null, mOnBatteryTimeBase);
12446         mDeviceIdlingTimer = new StopwatchTimer(mClock, null, -12, null, mOnBatteryTimeBase);
12447         mPhoneOnTimer = new StopwatchTimer(mClock, null, -3, null, mOnBatteryTimeBase);
12448         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
12449             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -200 - i, null,
12450                     mOnBatteryTimeBase);
12451         }
12452         mPhoneSignalScanningTimer = new StopwatchTimer(mClock, null, -200 + 1, null,
12453                 mOnBatteryTimeBase);
12454         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
12455             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClock, null, -300 - i, null,
12456                     mOnBatteryTimeBase);
12457         }
12458         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
12459             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
12460             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
12461         }
12462         mWifiActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
12463                 NUM_WIFI_TX_LEVELS);
12464         mBluetoothActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
12465                 NUM_BT_TX_LEVELS);
12466         mModemActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
12467                 ModemActivityInfo.getNumTxPowerLevels());
12468         mMobileRadioActiveTimer = new StopwatchTimer(mClock, null, -400, null, mOnBatteryTimeBase);
12469         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClock, null, -401, null,
12470                 mOnBatteryTimeBase);
12471         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
12472         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
12473         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
12474         mWifiMulticastWakelockTimer = new StopwatchTimer(mClock, null,
12475                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
12476         mWifiOnTimer = new StopwatchTimer(mClock, null, -4, null, mOnBatteryTimeBase);
12477         mGlobalWifiRunningTimer = new StopwatchTimer(mClock, null, -5, null, mOnBatteryTimeBase);
12478         for (int i=0; i<NUM_WIFI_STATES; i++) {
12479             mWifiStateTimer[i] = new StopwatchTimer(mClock, null, -600 - i, null,
12480                     mOnBatteryTimeBase);
12481         }
12482         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12483             mWifiSupplStateTimer[i] = new StopwatchTimer(mClock, null, -700 - i, null,
12484                     mOnBatteryTimeBase);
12485         }
12486         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12487             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -800 - i, null,
12488                     mOnBatteryTimeBase);
12489         }
12490         mWifiActiveTimer = new StopwatchTimer(mClock, null, -900, null, mOnBatteryTimeBase);
12491         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
12492             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClock, null, -1000 - i, null,
12493                     mOnBatteryTimeBase);
12494         }
12495         mAudioOnTimer = new StopwatchTimer(mClock, null, -7, null, mOnBatteryTimeBase);
12496         mVideoOnTimer = new StopwatchTimer(mClock, null, -8, null, mOnBatteryTimeBase);
12497         mFlashlightOnTimer = new StopwatchTimer(mClock, null, -9, null, mOnBatteryTimeBase);
12498         mCameraOnTimer = new StopwatchTimer(mClock, null, -13, null, mOnBatteryTimeBase);
12499         mBluetoothScanTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase);
12500         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
12501         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
12502         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
12503         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
12504         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
12505         mDischargeStartLevel = 0;
12506         mDischargeUnplugLevel = 0;
12507         mDischargePlugLevel = -1;
12508         mDischargeCurrentLevel = 0;
12509         mCurrentBatteryLevel = 0;
12510     }
12511 
12512     @UnsupportedAppUsage
BatteryStatsImpl(Parcel p)12513     public BatteryStatsImpl(Parcel p) {
12514         this(Clock.SYSTEM_CLOCK, p);
12515     }
12516 
BatteryStatsImpl(Clock clock, Parcel p)12517     public BatteryStatsImpl(Clock clock, Parcel p) {
12518         init(clock);
12519         mStatsFile = null;
12520         mCheckinFile = null;
12521         mDailyFile = null;
12522         mHandler = null;
12523         mExternalSync = null;
12524         mConstants = new Constants(mHandler);
12525         clearHistoryLocked();
12526         mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
12527         readFromParcel(p);
12528         mPlatformIdleStateCallback = null;
12529         mMeasuredEnergyRetriever = null;
12530     }
12531 
setPowerProfileLocked(PowerProfile profile)12532     public void setPowerProfileLocked(PowerProfile profile) {
12533         mPowerProfile = profile;
12534 
12535         // We need to initialize the KernelCpuSpeedReaders to read from
12536         // the first cpu of each core. Once we have the PowerProfile, we have access to this
12537         // information.
12538         final int numClusters = mPowerProfile.getNumCpuClusters();
12539         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
12540         int firstCpuOfCluster = 0;
12541         for (int i = 0; i < numClusters; i++) {
12542             final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
12543             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
12544                     numSpeedSteps);
12545             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
12546         }
12547 
12548         if (mEstimatedBatteryCapacityMah == -1) {
12549             // Initialize the estimated battery capacity to a known preset one.
12550             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
12551         }
12552 
12553         setDisplayCountLocked(mPowerProfile.getNumDisplays());
12554     }
12555 
getPowerProfile()12556     PowerProfile getPowerProfile() {
12557         return mPowerProfile;
12558     }
12559 
12560     /**
12561      * Starts tracking CPU time-in-state for threads of the system server process,
12562      * keeping a separate account of threads receiving incoming binder calls.
12563      */
startTrackingSystemServerCpuTime()12564     public void startTrackingSystemServerCpuTime() {
12565         mSystemServerCpuThreadReader.startTrackingThreadCpuTime();
12566     }
12567 
getSystemServiceCpuThreadTimes()12568     public SystemServiceCpuThreadTimes getSystemServiceCpuThreadTimes() {
12569         return mSystemServerCpuThreadReader.readAbsolute();
12570     }
12571 
setCallback(BatteryCallback cb)12572     public void setCallback(BatteryCallback cb) {
12573         mCallback = cb;
12574     }
12575 
setRadioScanningTimeoutLocked(long timeoutUs)12576     public void setRadioScanningTimeoutLocked(long timeoutUs) {
12577         if (mPhoneSignalScanningTimer != null) {
12578             mPhoneSignalScanningTimer.setTimeout(timeoutUs);
12579         }
12580     }
12581 
setExternalStatsSyncLocked(ExternalStatsSync sync)12582     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
12583         mExternalSync = sync;
12584     }
12585 
12586     /**
12587      * Initialize and set multi display timers and states.
12588      */
setDisplayCountLocked(int numDisplays)12589     public void setDisplayCountLocked(int numDisplays) {
12590         mPerDisplayBatteryStats = new DisplayBatteryStats[numDisplays];
12591         for (int i = 0; i < numDisplays; i++) {
12592             mPerDisplayBatteryStats[i] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
12593         }
12594     }
12595 
updateDailyDeadlineLocked()12596     public void updateDailyDeadlineLocked() {
12597         // Get the current time.
12598         long currentTimeMs = mDailyStartTimeMs = mClock.currentTimeMillis();
12599         Calendar calDeadline = Calendar.getInstance();
12600         calDeadline.setTimeInMillis(currentTimeMs);
12601 
12602         // Move time up to the next day, ranging from 1am to 3pm.
12603         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
12604         calDeadline.set(Calendar.MILLISECOND, 0);
12605         calDeadline.set(Calendar.SECOND, 0);
12606         calDeadline.set(Calendar.MINUTE, 0);
12607         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
12608         mNextMinDailyDeadlineMs = calDeadline.getTimeInMillis();
12609         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
12610         mNextMaxDailyDeadlineMs = calDeadline.getTimeInMillis();
12611     }
12612 
recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs)12613     public void recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs) {
12614         if (currentTimeMs >= mNextMaxDailyDeadlineMs) {
12615             recordDailyStatsLocked();
12616         } else if (settled && currentTimeMs >= mNextMinDailyDeadlineMs) {
12617             recordDailyStatsLocked();
12618         } else if (currentTimeMs < (mDailyStartTimeMs - (1000 * 60 * 60 * 24))) {
12619             recordDailyStatsLocked();
12620         }
12621     }
12622 
recordDailyStatsLocked()12623     public void recordDailyStatsLocked() {
12624         DailyItem item = new DailyItem();
12625         item.mStartTime = mDailyStartTimeMs;
12626         item.mEndTime = mClock.currentTimeMillis();
12627         boolean hasData = false;
12628         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
12629             hasData = true;
12630             item.mDischargeSteps = new LevelStepTracker(
12631                     mDailyDischargeStepTracker.mNumStepDurations,
12632                     mDailyDischargeStepTracker.mStepDurations);
12633         }
12634         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
12635             hasData = true;
12636             item.mChargeSteps = new LevelStepTracker(
12637                     mDailyChargeStepTracker.mNumStepDurations,
12638                     mDailyChargeStepTracker.mStepDurations);
12639         }
12640         if (mDailyPackageChanges != null) {
12641             hasData = true;
12642             item.mPackageChanges = mDailyPackageChanges;
12643             mDailyPackageChanges = null;
12644         }
12645         mDailyDischargeStepTracker.init();
12646         mDailyChargeStepTracker.init();
12647         updateDailyDeadlineLocked();
12648 
12649         if (hasData) {
12650             final long startTimeMs = SystemClock.uptimeMillis();
12651             mDailyItems.add(item);
12652             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
12653                 mDailyItems.remove(0);
12654             }
12655             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
12656             try {
12657                 TypedXmlSerializer out = Xml.resolveSerializer(memStream);
12658                 writeDailyItemsLocked(out);
12659                 final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
12660                 BackgroundThread.getHandler().post(new Runnable() {
12661                     @Override
12662                     public void run() {
12663                         synchronized (mCheckinFile) {
12664                             final long startTimeMs2 = SystemClock.uptimeMillis();
12665                             FileOutputStream stream = null;
12666                             try {
12667                                 stream = mDailyFile.startWrite();
12668                                 memStream.writeTo(stream);
12669                                 stream.flush();
12670                                 mDailyFile.finishWrite(stream);
12671                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
12672                                         "batterystats-daily",
12673                                         initialTimeMs + SystemClock.uptimeMillis() - startTimeMs2);
12674                             } catch (IOException e) {
12675                                 Slog.w("BatteryStats",
12676                                         "Error writing battery daily items", e);
12677                                 mDailyFile.failWrite(stream);
12678                             }
12679                         }
12680                     }
12681                 });
12682             } catch (IOException e) {
12683             }
12684         }
12685     }
12686 
writeDailyItemsLocked(TypedXmlSerializer out)12687     private void writeDailyItemsLocked(TypedXmlSerializer out) throws IOException {
12688         StringBuilder sb = new StringBuilder(64);
12689         out.startDocument(null, true);
12690         out.startTag(null, "daily-items");
12691         for (int i=0; i<mDailyItems.size(); i++) {
12692             final DailyItem dit = mDailyItems.get(i);
12693             out.startTag(null, "item");
12694             out.attributeLong(null, "start", dit.mStartTime);
12695             out.attributeLong(null, "end", dit.mEndTime);
12696             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
12697             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
12698             if (dit.mPackageChanges != null) {
12699                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
12700                     PackageChange pc = dit.mPackageChanges.get(j);
12701                     if (pc.mUpdate) {
12702                         out.startTag(null, "upd");
12703                         out.attribute(null, "pkg", pc.mPackageName);
12704                         out.attributeLong(null, "ver", pc.mVersionCode);
12705                         out.endTag(null, "upd");
12706                     } else {
12707                         out.startTag(null, "rem");
12708                         out.attribute(null, "pkg", pc.mPackageName);
12709                         out.endTag(null, "rem");
12710                     }
12711                 }
12712             }
12713             out.endTag(null, "item");
12714         }
12715         out.endTag(null, "daily-items");
12716         out.endDocument();
12717     }
12718 
writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)12719     private void writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps,
12720             StringBuilder tmpBuilder) throws IOException {
12721         if (steps != null) {
12722             out.startTag(null, tag);
12723             out.attributeInt(null, "n", steps.mNumStepDurations);
12724             for (int i=0; i<steps.mNumStepDurations; i++) {
12725                 out.startTag(null, "s");
12726                 tmpBuilder.setLength(0);
12727                 steps.encodeEntryAt(i, tmpBuilder);
12728                 out.attribute(null, "v", tmpBuilder.toString());
12729                 out.endTag(null, "s");
12730             }
12731             out.endTag(null, tag);
12732         }
12733     }
12734 
12735     @GuardedBy("this")
readDailyStatsLocked()12736     public void readDailyStatsLocked() {
12737         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
12738         mDailyItems.clear();
12739         FileInputStream stream;
12740         try {
12741             stream = mDailyFile.openRead();
12742         } catch (FileNotFoundException e) {
12743             return;
12744         }
12745         try {
12746             TypedXmlPullParser parser = Xml.resolvePullParser(stream);
12747             readDailyItemsLocked(parser);
12748         } catch (IOException e) {
12749         } finally {
12750             try {
12751                 stream.close();
12752             } catch (IOException e) {
12753             }
12754         }
12755     }
12756 
readDailyItemsLocked(TypedXmlPullParser parser)12757     private void readDailyItemsLocked(TypedXmlPullParser parser) {
12758         try {
12759             int type;
12760             while ((type = parser.next()) != XmlPullParser.START_TAG
12761                     && type != XmlPullParser.END_DOCUMENT) {
12762                 ;
12763             }
12764 
12765             if (type != XmlPullParser.START_TAG) {
12766                 throw new IllegalStateException("no start tag found");
12767             }
12768 
12769             int outerDepth = parser.getDepth();
12770             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
12771                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
12772                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
12773                     continue;
12774                 }
12775 
12776                 String tagName = parser.getName();
12777                 if (tagName.equals("item")) {
12778                     readDailyItemTagLocked(parser);
12779                 } else {
12780                     Slog.w(TAG, "Unknown element under <daily-items>: "
12781                             + parser.getName());
12782                     XmlUtils.skipCurrentTag(parser);
12783                 }
12784             }
12785 
12786         } catch (IllegalStateException e) {
12787             Slog.w(TAG, "Failed parsing daily " + e);
12788         } catch (NullPointerException e) {
12789             Slog.w(TAG, "Failed parsing daily " + e);
12790         } catch (NumberFormatException e) {
12791             Slog.w(TAG, "Failed parsing daily " + e);
12792         } catch (XmlPullParserException e) {
12793             Slog.w(TAG, "Failed parsing daily " + e);
12794         } catch (IOException e) {
12795             Slog.w(TAG, "Failed parsing daily " + e);
12796         } catch (IndexOutOfBoundsException e) {
12797             Slog.w(TAG, "Failed parsing daily " + e);
12798         }
12799     }
12800 
readDailyItemTagLocked(TypedXmlPullParser parser)12801     void readDailyItemTagLocked(TypedXmlPullParser parser) throws NumberFormatException,
12802             XmlPullParserException, IOException {
12803         DailyItem dit = new DailyItem();
12804         dit.mStartTime = parser.getAttributeLong(null, "start", 0);
12805         dit.mEndTime = parser.getAttributeLong(null, "end", 0);
12806         int outerDepth = parser.getDepth();
12807         int type;
12808         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
12809                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
12810             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
12811                 continue;
12812             }
12813 
12814             String tagName = parser.getName();
12815             if (tagName.equals("dis")) {
12816                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
12817             } else if (tagName.equals("chg")) {
12818                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
12819             } else if (tagName.equals("upd")) {
12820                 if (dit.mPackageChanges == null) {
12821                     dit.mPackageChanges = new ArrayList<>();
12822                 }
12823                 PackageChange pc = new PackageChange();
12824                 pc.mUpdate = true;
12825                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
12826                 pc.mVersionCode = parser.getAttributeLong(null, "ver", 0);
12827                 dit.mPackageChanges.add(pc);
12828                 XmlUtils.skipCurrentTag(parser);
12829             } else if (tagName.equals("rem")) {
12830                 if (dit.mPackageChanges == null) {
12831                     dit.mPackageChanges = new ArrayList<>();
12832                 }
12833                 PackageChange pc = new PackageChange();
12834                 pc.mUpdate = false;
12835                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
12836                 dit.mPackageChanges.add(pc);
12837                 XmlUtils.skipCurrentTag(parser);
12838             } else {
12839                 Slog.w(TAG, "Unknown element under <item>: "
12840                         + parser.getName());
12841                 XmlUtils.skipCurrentTag(parser);
12842             }
12843         }
12844         mDailyItems.add(dit);
12845     }
12846 
readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge, String tag)12847     void readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge,
12848             String tag)
12849             throws NumberFormatException, XmlPullParserException, IOException {
12850         final int num = parser.getAttributeInt(null, "n", -1);
12851         if (num == -1) {
12852             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
12853             XmlUtils.skipCurrentTag(parser);
12854             return;
12855         }
12856         LevelStepTracker steps = new LevelStepTracker(num);
12857         if (isCharge) {
12858             dit.mChargeSteps = steps;
12859         } else {
12860             dit.mDischargeSteps = steps;
12861         }
12862         int i = 0;
12863         int outerDepth = parser.getDepth();
12864         int type;
12865         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
12866                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
12867             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
12868                 continue;
12869             }
12870 
12871             String tagName = parser.getName();
12872             if ("s".equals(tagName)) {
12873                 if (i < num) {
12874                     String valueAttr = parser.getAttributeValue(null, "v");
12875                     if (valueAttr != null) {
12876                         steps.decodeEntryAt(i, valueAttr);
12877                         i++;
12878                     }
12879                 }
12880             } else {
12881                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
12882                         + parser.getName());
12883                 XmlUtils.skipCurrentTag(parser);
12884             }
12885         }
12886         steps.mNumStepDurations = i;
12887     }
12888 
12889     @Override
getDailyItemLocked(int daysAgo)12890     public DailyItem getDailyItemLocked(int daysAgo) {
12891         int index = mDailyItems.size()-1-daysAgo;
12892         return index >= 0 ? mDailyItems.get(index) : null;
12893     }
12894 
12895     @Override
getCurrentDailyStartTime()12896     public long getCurrentDailyStartTime() {
12897         return mDailyStartTimeMs;
12898     }
12899 
12900     @Override
getNextMinDailyDeadline()12901     public long getNextMinDailyDeadline() {
12902         return mNextMinDailyDeadlineMs;
12903     }
12904 
12905     @Override
getNextMaxDailyDeadline()12906     public long getNextMaxDailyDeadline() {
12907         return mNextMaxDailyDeadlineMs;
12908     }
12909 
12910     @GuardedBy("this")
getHistoryTotalSize()12911     public int getHistoryTotalSize() {
12912         return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
12913     }
12914 
getHistoryUsedSize()12915     public int getHistoryUsedSize() {
12916         return mBatteryStatsHistory.getHistoryUsedSize();
12917     }
12918 
12919     @Override
12920     @UnsupportedAppUsage
startIteratingHistoryLocked()12921     public boolean startIteratingHistoryLocked() {
12922         mBatteryStatsHistoryIterator = createBatteryStatsHistoryIterator();
12923         return true;
12924     }
12925 
12926     /**
12927      * Creates an iterator for battery stats history.
12928      */
12929     @VisibleForTesting
createBatteryStatsHistoryIterator()12930     public BatteryStatsHistoryIterator createBatteryStatsHistoryIterator() {
12931         return new BatteryStatsHistoryIterator(mBatteryStatsHistory);
12932     }
12933 
12934     @Override
getHistoryStringPoolSize()12935     public int getHistoryStringPoolSize() {
12936         return mHistoryTagPool.size();
12937     }
12938 
12939     @Override
getHistoryStringPoolBytes()12940     public int getHistoryStringPoolBytes() {
12941         return mNumHistoryTagChars;
12942     }
12943 
12944     @Override
getHistoryTagPoolString(int index)12945     public String getHistoryTagPoolString(int index) {
12946         ensureHistoryTagArray();
12947         HistoryTag historyTag = mHistoryTags.get(index);
12948         return historyTag != null ? historyTag.string : null;
12949     }
12950 
12951     @Override
getHistoryTagPoolUid(int index)12952     public int getHistoryTagPoolUid(int index) {
12953         ensureHistoryTagArray();
12954         HistoryTag historyTag = mHistoryTags.get(index);
12955         return historyTag != null ? historyTag.uid : Process.INVALID_UID;
12956     }
12957 
ensureHistoryTagArray()12958     private void ensureHistoryTagArray() {
12959         if (mHistoryTags != null) {
12960             return;
12961         }
12962 
12963         mHistoryTags = new SparseArray<>(mHistoryTagPool.size());
12964         for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
12965             mHistoryTags.put(entry.getValue() & ~TAG_FIRST_OCCURRENCE_FLAG, entry.getKey());
12966         }
12967     }
12968 
12969     @Override
12970     @UnsupportedAppUsage
getNextHistoryLocked(HistoryItem out)12971     public boolean getNextHistoryLocked(HistoryItem out) {
12972         return mBatteryStatsHistoryIterator.next(out);
12973     }
12974 
12975     @Override
finishIteratingHistoryLocked()12976     public void finishIteratingHistoryLocked() {
12977         mBatteryStatsHistoryIterator = null;
12978     }
12979 
12980     @Override
getHistoryBaseTime()12981     public long getHistoryBaseTime() {
12982         return mHistoryBaseTimeMs;
12983     }
12984 
12985     @Override
getStartCount()12986     public int getStartCount() {
12987         return mStartCount;
12988     }
12989 
12990     @UnsupportedAppUsage
isOnBattery()12991     public boolean isOnBattery() {
12992         return mOnBattery;
12993     }
12994 
isCharging()12995     public boolean isCharging() {
12996         return mCharging;
12997     }
12998 
initTimes(long uptimeUs, long realtimeUs)12999     void initTimes(long uptimeUs, long realtimeUs) {
13000         mStartClockTimeMs = mClock.currentTimeMillis();
13001         mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
13002         mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
13003         mRealtimeUs = 0;
13004         mUptimeUs = 0;
13005         mRealtimeStartUs = realtimeUs;
13006         mUptimeStartUs = uptimeUs;
13007     }
13008 
initDischarge(long elapsedRealtimeUs)13009     void initDischarge(long elapsedRealtimeUs) {
13010         mLowDischargeAmountSinceCharge = 0;
13011         mHighDischargeAmountSinceCharge = 0;
13012         mDischargeAmountScreenOn = 0;
13013         mDischargeAmountScreenOnSinceCharge = 0;
13014         mDischargeAmountScreenOff = 0;
13015         mDischargeAmountScreenOffSinceCharge = 0;
13016         mDischargeAmountScreenDoze = 0;
13017         mDischargeAmountScreenDozeSinceCharge = 0;
13018         mDischargeStepTracker.init();
13019         mChargeStepTracker.init();
13020         mDischargeScreenOffCounter.reset(false, elapsedRealtimeUs);
13021         mDischargeScreenDozeCounter.reset(false, elapsedRealtimeUs);
13022         mDischargeLightDozeCounter.reset(false, elapsedRealtimeUs);
13023         mDischargeDeepDozeCounter.reset(false, elapsedRealtimeUs);
13024         mDischargeCounter.reset(false, elapsedRealtimeUs);
13025     }
13026 
setBatteryResetListener(BatteryResetListener batteryResetListener)13027     public void setBatteryResetListener(BatteryResetListener batteryResetListener) {
13028         mBatteryResetListener = batteryResetListener;
13029     }
13030 
13031     @GuardedBy("this")
resetAllStatsCmdLocked()13032     public void resetAllStatsCmdLocked() {
13033         final long mSecUptime = mClock.uptimeMillis();
13034         long uptimeUs = mSecUptime * 1000;
13035         long mSecRealtime = mClock.elapsedRealtime();
13036         long realtimeUs = mSecRealtime * 1000;
13037         resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_ADB_COMMAND);
13038         mDischargeStartLevel = mHistoryCur.batteryLevel;
13039         pullPendingStateUpdatesLocked();
13040         addHistoryRecordLocked(mSecRealtime, mSecUptime);
13041         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
13042                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
13043         mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
13044         mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
13045         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
13046             if (Display.isOnState(mScreenState)) {
13047                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
13048                 mDischargeScreenDozeUnplugLevel = 0;
13049                 mDischargeScreenOffUnplugLevel = 0;
13050             } else if (Display.isDozeState(mScreenState)) {
13051                 mDischargeScreenOnUnplugLevel = 0;
13052                 mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
13053                 mDischargeScreenOffUnplugLevel = 0;
13054             } else {
13055                 mDischargeScreenOnUnplugLevel = 0;
13056                 mDischargeScreenDozeUnplugLevel = 0;
13057                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
13058             }
13059             mDischargeAmountScreenOn = 0;
13060             mDischargeAmountScreenOff = 0;
13061             mDischargeAmountScreenDoze = 0;
13062         }
13063         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
13064     }
13065 
13066     @GuardedBy("this")
resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis, int resetReason)13067     private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis,
13068             int resetReason) {
13069         if (mBatteryResetListener != null) {
13070             mBatteryResetListener.prepareForBatteryStatsReset(resetReason);
13071         }
13072 
13073         final long uptimeUs = uptimeMillis * 1000;
13074         final long elapsedRealtimeUs = elapsedRealtimeMillis * 1000;
13075         mStartCount = 0;
13076         initTimes(uptimeUs, elapsedRealtimeUs);
13077         mScreenOnTimer.reset(false, elapsedRealtimeUs);
13078         mScreenDozeTimer.reset(false, elapsedRealtimeUs);
13079         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
13080             mScreenBrightnessTimer[i].reset(false, elapsedRealtimeUs);
13081         }
13082 
13083         final int numDisplays = mPerDisplayBatteryStats.length;
13084         for (int i = 0; i < numDisplays; i++) {
13085             mPerDisplayBatteryStats[i].reset(elapsedRealtimeUs);
13086         }
13087 
13088         if (mPowerProfile != null) {
13089             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
13090         } else {
13091             mEstimatedBatteryCapacityMah = -1;
13092         }
13093         mLastLearnedBatteryCapacityUah = -1;
13094         mMinLearnedBatteryCapacityUah = -1;
13095         mMaxLearnedBatteryCapacityUah = -1;
13096         mInteractiveTimer.reset(false, elapsedRealtimeUs);
13097         mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs);
13098         mLastIdleTimeStartMs = elapsedRealtimeMillis;
13099         mLongestLightIdleTimeMs = 0;
13100         mLongestFullIdleTimeMs = 0;
13101         mDeviceIdleModeLightTimer.reset(false, elapsedRealtimeUs);
13102         mDeviceIdleModeFullTimer.reset(false, elapsedRealtimeUs);
13103         mDeviceLightIdlingTimer.reset(false, elapsedRealtimeUs);
13104         mDeviceIdlingTimer.reset(false, elapsedRealtimeUs);
13105         mPhoneOnTimer.reset(false, elapsedRealtimeUs);
13106         mAudioOnTimer.reset(false, elapsedRealtimeUs);
13107         mVideoOnTimer.reset(false, elapsedRealtimeUs);
13108         mFlashlightOnTimer.reset(false, elapsedRealtimeUs);
13109         mCameraOnTimer.reset(false, elapsedRealtimeUs);
13110         mBluetoothScanTimer.reset(false, elapsedRealtimeUs);
13111         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
13112             mPhoneSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
13113         }
13114         mPhoneSignalScanningTimer.reset(false, elapsedRealtimeUs);
13115         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
13116             mPhoneDataConnectionsTimer[i].reset(false, elapsedRealtimeUs);
13117         }
13118         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13119             mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs);
13120             mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs);
13121         }
13122         for (int i = 0; i < RADIO_ACCESS_TECHNOLOGY_COUNT; i++) {
13123             final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[i];
13124             if (stats == null) continue;
13125             stats.reset(elapsedRealtimeUs);
13126         }
13127         mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs);
13128         mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs);
13129         mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs);
13130         mMobileRadioActiveUnknownTime.reset(false, elapsedRealtimeUs);
13131         mMobileRadioActiveUnknownCount.reset(false, elapsedRealtimeUs);
13132         mWifiOnTimer.reset(false, elapsedRealtimeUs);
13133         mGlobalWifiRunningTimer.reset(false, elapsedRealtimeUs);
13134         for (int i=0; i<NUM_WIFI_STATES; i++) {
13135             mWifiStateTimer[i].reset(false, elapsedRealtimeUs);
13136         }
13137         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
13138             mWifiSupplStateTimer[i].reset(false, elapsedRealtimeUs);
13139         }
13140         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
13141             mWifiSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
13142         }
13143         mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs);
13144         mWifiActiveTimer.reset(false, elapsedRealtimeUs);
13145         mWifiActivity.reset(false, elapsedRealtimeUs);
13146         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
13147             mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs);
13148         }
13149         mBluetoothActivity.reset(false, elapsedRealtimeUs);
13150         mModemActivity.reset(false, elapsedRealtimeUs);
13151         mNumConnectivityChange = 0;
13152 
13153         for (int i=0; i<mUidStats.size(); i++) {
13154             if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs, resetReason)) {
13155                 mUidStats.valueAt(i).detachFromTimeBase();
13156                 mUidStats.remove(mUidStats.keyAt(i));
13157                 i--;
13158             }
13159         }
13160 
13161         if (mRpmStats.size() > 0) {
13162             for (SamplingTimer timer : mRpmStats.values()) {
13163                 mOnBatteryTimeBase.remove(timer);
13164             }
13165             mRpmStats.clear();
13166         }
13167         if (mScreenOffRpmStats.size() > 0) {
13168             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
13169                 mOnBatteryScreenOffTimeBase.remove(timer);
13170             }
13171             mScreenOffRpmStats.clear();
13172         }
13173 
13174         if (mKernelWakelockStats.size() > 0) {
13175             for (SamplingTimer timer : mKernelWakelockStats.values()) {
13176                 mOnBatteryScreenOffTimeBase.remove(timer);
13177             }
13178             mKernelWakelockStats.clear();
13179         }
13180 
13181         if (mKernelMemoryStats.size() > 0) {
13182             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
13183                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
13184             }
13185             mKernelMemoryStats.clear();
13186         }
13187 
13188         if (mWakeupReasonStats.size() > 0) {
13189             for (SamplingTimer timer : mWakeupReasonStats.values()) {
13190                 mOnBatteryTimeBase.remove(timer);
13191             }
13192             mWakeupReasonStats.clear();
13193         }
13194 
13195         mTmpRailStats.reset();
13196 
13197         MeasuredEnergyStats.resetIfNotNull(mGlobalMeasuredEnergyStats);
13198 
13199         resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
13200 
13201         mLastHistoryStepDetails = null;
13202         mLastStepCpuUserTimeMs = mLastStepCpuSystemTimeMs = 0;
13203         mCurStepCpuUserTimeMs = mCurStepCpuSystemTimeMs = 0;
13204         mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
13205         mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
13206         mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
13207         mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
13208         mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
13209         mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
13210         mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
13211         mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
13212 
13213         mNumAllUidCpuTimeReads = 0;
13214         mNumUidsRemoved = 0;
13215 
13216         initDischarge(elapsedRealtimeUs);
13217 
13218         clearHistoryLocked();
13219         if (mBatteryStatsHistory != null) {
13220             mBatteryStatsHistory.resetAllFiles();
13221         }
13222 
13223         // Flush external data, gathering snapshots, but don't process it since it is pre-reset data
13224         mIgnoreNextExternalStats = true;
13225         mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ON_RESET);
13226 
13227         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
13228     }
13229 
13230     @GuardedBy("this")
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)13231     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
13232         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
13233             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
13234                 // Not recording process starts/stops.
13235                 continue;
13236             }
13237             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
13238             if (active == null) {
13239                 continue;
13240             }
13241             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
13242                 SparseIntArray uids = ent.getValue();
13243                 for (int j=0; j<uids.size(); j++) {
13244                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
13245                             uids.keyAt(j));
13246                 }
13247             }
13248         }
13249     }
13250 
13251     @GuardedBy("this")
updateDischargeScreenLevelsLocked(int oldState, int newState)13252     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
13253         updateOldDischargeScreenLevelLocked(oldState);
13254         updateNewDischargeScreenLevelLocked(newState);
13255     }
13256 
13257     @GuardedBy("this")
updateOldDischargeScreenLevelLocked(int state)13258     private void updateOldDischargeScreenLevelLocked(int state) {
13259         if (Display.isOnState(state)) {
13260             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
13261             if (diff > 0) {
13262                 mDischargeAmountScreenOn += diff;
13263                 mDischargeAmountScreenOnSinceCharge += diff;
13264             }
13265         } else if (Display.isDozeState(state)) {
13266             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
13267             if (diff > 0) {
13268                 mDischargeAmountScreenDoze += diff;
13269                 mDischargeAmountScreenDozeSinceCharge += diff;
13270             }
13271         } else if (Display.isOffState(state)) {
13272             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
13273             if (diff > 0) {
13274                 mDischargeAmountScreenOff += diff;
13275                 mDischargeAmountScreenOffSinceCharge += diff;
13276             }
13277         }
13278     }
13279 
13280     @GuardedBy("this")
updateNewDischargeScreenLevelLocked(int state)13281     private void updateNewDischargeScreenLevelLocked(int state) {
13282         if (Display.isOnState(state)) {
13283             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
13284             mDischargeScreenOffUnplugLevel = 0;
13285             mDischargeScreenDozeUnplugLevel = 0;
13286         } else if (Display.isDozeState(state)) {
13287             mDischargeScreenOnUnplugLevel = 0;
13288             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
13289             mDischargeScreenOffUnplugLevel = 0;
13290         } else if (Display.isOffState(state)) {
13291             mDischargeScreenOnUnplugLevel = 0;
13292             mDischargeScreenDozeUnplugLevel = 0;
13293             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
13294         }
13295     }
13296 
13297     @GuardedBy("this")
pullPendingStateUpdatesLocked()13298     public void pullPendingStateUpdatesLocked() {
13299         if (mOnBatteryInternal) {
13300             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
13301         }
13302     }
13303 
13304     private final Object mWifiNetworkLock = new Object();
13305 
13306     @GuardedBy("mWifiNetworkLock")
13307     private String[] mWifiIfaces = EmptyArray.STRING;
13308 
13309     @GuardedBy("mWifiNetworkLock")
13310     private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
13311 
13312     private final Object mModemNetworkLock = new Object();
13313 
13314     @GuardedBy("mModemNetworkLock")
13315     private String[] mModemIfaces = EmptyArray.STRING;
13316 
13317     @GuardedBy("mModemNetworkLock")
13318     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
13319 
13320     @VisibleForTesting
readMobileNetworkStatsLocked( @onNull NetworkStatsManager networkStatsManager)13321     protected NetworkStats readMobileNetworkStatsLocked(
13322             @NonNull NetworkStatsManager networkStatsManager) {
13323         return networkStatsManager.getMobileUidStats();
13324     }
13325 
13326     @VisibleForTesting
readWifiNetworkStatsLocked( @onNull NetworkStatsManager networkStatsManager)13327     protected NetworkStats readWifiNetworkStatsLocked(
13328             @NonNull NetworkStatsManager networkStatsManager) {
13329         return networkStatsManager.getWifiUidStats();
13330     }
13331 
13332     /**
13333      * Distribute WiFi energy info and network traffic to apps.
13334      * @param info The energy information from the WiFi controller.
13335      */
13336     @GuardedBy("this")
updateWifiState(@ullable final WifiActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager)13337     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
13338             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
13339             @NonNull NetworkStatsManager networkStatsManager) {
13340         if (DEBUG_ENERGY) {
13341             synchronized (mWifiNetworkLock) {
13342                 Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
13343             }
13344         }
13345 
13346         // Grab a separate lock to acquire the network stats, which may do I/O.
13347         NetworkStats delta = null;
13348         synchronized (mWifiNetworkLock) {
13349             final NetworkStats latestStats = readWifiNetworkStatsLocked(networkStatsManager);
13350             if (latestStats != null) {
13351                 delta = latestStats.subtract(mLastWifiNetworkStats);
13352                 mLastWifiNetworkStats = latestStats;
13353             }
13354         }
13355 
13356         synchronized (this) {
13357             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
13358                 if (mIgnoreNextExternalStats) {
13359                     // TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
13360                     //  global one) here like we do for display. But I'm not sure it's worth the
13361                     //  complicated code for a codepath that shouldn't ever actually happen in real
13362                     //  life.
13363                 }
13364                 return;
13365             }
13366 
13367             final SparseDoubleArray uidEstimatedConsumptionMah =
13368                     (mGlobalMeasuredEnergyStats != null
13369                             && mWifiPowerCalculator != null && consumedChargeUC > 0) ?
13370                             new SparseDoubleArray() : null;
13371             double totalEstimatedConsumptionMah = 0;
13372 
13373             SparseLongArray rxPackets = new SparseLongArray();
13374             SparseLongArray txPackets = new SparseLongArray();
13375             SparseLongArray rxTimesMs = new SparseLongArray();
13376             SparseLongArray txTimesMs = new SparseLongArray();
13377             long totalTxPackets = 0;
13378             long totalRxPackets = 0;
13379             if (delta != null) {
13380                 for (NetworkStats.Entry entry : delta) {
13381                     if (DEBUG_ENERGY) {
13382                         Slog.d(TAG, "Wifi uid " + entry.getUid()
13383                                 + ": delta rx=" + entry.getRxBytes()
13384                                 + " tx=" + entry.getTxBytes()
13385                                 + " rxPackets=" + entry.getRxPackets()
13386                                 + " txPackets=" + entry.getTxPackets());
13387                     }
13388 
13389                     if (entry.getRxBytes() == 0 && entry.getTxBytes() == 0) {
13390                         // Skip the lookup below since there is no work to do.
13391                         continue;
13392                     }
13393 
13394                     final int uid = mapUid(entry.getUid());
13395                     final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
13396                     if (entry.getRxBytes() != 0) {
13397                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.getRxBytes(),
13398                                 entry.getRxPackets());
13399                         if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
13400                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.getRxBytes(),
13401                                     entry.getRxPackets());
13402                         }
13403                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
13404                                 entry.getRxBytes());
13405                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
13406                                 entry.getRxPackets());
13407 
13408                         rxPackets.incrementValue(uid, entry.getRxPackets());
13409 
13410                         // Sum the total number of packets so that the Rx Power can
13411                         // be evenly distributed amongst the apps.
13412                         totalRxPackets += entry.getRxPackets();
13413                     }
13414 
13415                     if (entry.getTxBytes() != 0) {
13416                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.getTxBytes(),
13417                                 entry.getTxPackets());
13418                         if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
13419                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.getTxBytes(),
13420                                     entry.getTxPackets());
13421                         }
13422                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
13423                                 entry.getTxBytes());
13424                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
13425                                 entry.getTxPackets());
13426 
13427                         txPackets.incrementValue(uid, entry.getTxPackets());
13428 
13429                         // Sum the total number of packets so that the Tx Power can
13430                         // be evenly distributed amongst the apps.
13431                         totalTxPackets += entry.getTxPackets();
13432                     }
13433 
13434                     // Calculate consumed energy for this uid. Only do so if WifiReporting isn't
13435                     // enabled (if it is, we'll do it later instead using info).
13436                     if (uidEstimatedConsumptionMah != null && info == null && !mHasWifiReporting) {
13437                         final long uidRunningMs = u.mWifiRunningTimer
13438                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
13439                         if (uidRunningMs > 0) u.mWifiRunningTimer.setMark(elapsedRealtimeMs);
13440 
13441                         final long uidScanMs = u.mWifiScanTimer
13442                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
13443                         if (uidScanMs > 0) u.mWifiScanTimer.setMark(elapsedRealtimeMs);
13444 
13445                         long uidBatchScanMs = 0;
13446                         for (int bn = 0; bn < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bn++) {
13447                             if (u.mWifiBatchedScanTimer[bn] != null) {
13448                                 long bnMs = u.mWifiBatchedScanTimer[bn]
13449                                         .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
13450                                 if (bnMs > 0) {
13451                                     u.mWifiBatchedScanTimer[bn].setMark(elapsedRealtimeMs);
13452                                 }
13453                                 uidBatchScanMs += bnMs;
13454                             }
13455                         }
13456 
13457                         uidEstimatedConsumptionMah.incrementValue(u.getUid(),
13458                                 mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
13459                                         entry.getRxPackets(), entry.getTxPackets(),
13460                                         uidRunningMs, uidScanMs, uidBatchScanMs));
13461                     }
13462                 }
13463                 delta = null;
13464             }
13465 
13466             if (info != null) {
13467                 mHasWifiReporting = true;
13468 
13469                 // Measured in mAms
13470                 final long txTimeMs = info.getControllerTxDurationMillis();
13471                 final long rxTimeMs = info.getControllerRxDurationMillis();
13472                 final long scanTimeMs = info.getControllerScanDurationMillis();
13473                 final long idleTimeMs = info.getControllerIdleDurationMillis();
13474                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
13475 
13476                 long leftOverRxTimeMs = rxTimeMs;
13477                 long leftOverTxTimeMs = txTimeMs;
13478 
13479                 if (DEBUG_ENERGY) {
13480                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
13481                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
13482                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
13483                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
13484                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
13485                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
13486                 }
13487 
13488                 long totalWifiLockTimeMs = 0;
13489                 long totalScanTimeMs = 0;
13490 
13491                 // On the first pass, collect some totals so that we can normalize power
13492                 // calculations if we need to.
13493                 final int uidStatsSize = mUidStats.size();
13494                 for (int i = 0; i < uidStatsSize; i++) {
13495                     final Uid uid = mUidStats.valueAt(i);
13496 
13497                     // Sum the total scan power for all apps.
13498                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
13499                             elapsedRealtimeMs * 1000) / 1000;
13500 
13501                     // Sum the total time holding wifi lock for all apps.
13502                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
13503                             elapsedRealtimeMs * 1000) / 1000;
13504                 }
13505 
13506                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
13507                     Slog.d(TAG,
13508                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
13509                                     + rxTimeMs + " ms). Normalizing scan time.");
13510                 }
13511                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
13512                     Slog.d(TAG,
13513                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
13514                                     + txTimeMs + " ms). Normalizing scan time.");
13515                 }
13516 
13517                 // Actually assign and distribute power usage to apps.
13518                 for (int i = 0; i < uidStatsSize; i++) {
13519                     final Uid uid = mUidStats.valueAt(i);
13520 
13521                     final long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
13522                             elapsedRealtimeMs * 1000) / 1000;
13523                     long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
13524                     long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
13525                     if (scanTimeSinceMarkMs > 0) {
13526                         // Set the new mark so that next time we get new data since this point.
13527                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
13528 
13529                         // Our total scan time is more than the reported Tx/Rx time.
13530                         // This is possible because the cost of a scan is approximate.
13531                         // Let's normalize the result so that we evenly blame each app
13532                         // scanning.
13533                         //
13534                         // This means that we may have apps that transmitted/received packets not be
13535                         // blamed for this, but this is fine as scans are relatively more expensive.
13536                         if (totalScanTimeMs > rxTimeMs) {
13537                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
13538                                     totalScanTimeMs;
13539                         }
13540                         if (totalScanTimeMs > txTimeMs) {
13541                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
13542                                     totalScanTimeMs;
13543                         }
13544 
13545                         if (DEBUG_ENERGY) {
13546                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
13547                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
13548                                     + scanTxTimeSinceMarkMs + " ms)");
13549                         }
13550 
13551                         rxTimesMs.incrementValue(uid.getUid(), scanRxTimeSinceMarkMs);
13552                         txTimesMs.incrementValue(uid.getUid(), scanTxTimeSinceMarkMs);
13553 
13554                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
13555                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
13556                     }
13557 
13558                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
13559                     // lock.
13560                     long myIdleTimeMs = 0;
13561                     final long wifiLockTimeSinceMarkMs =
13562                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
13563                                     elapsedRealtimeMs * 1000) / 1000;
13564                     if (wifiLockTimeSinceMarkMs > 0) {
13565                         // Set the new mark so that next time we get new data since this point.
13566                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
13567 
13568                         myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) / totalWifiLockTimeMs;
13569                         if (DEBUG_ENERGY) {
13570                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
13571                                     + myIdleTimeMs + " ms");
13572                         }
13573                         uid.getOrCreateWifiControllerActivityLocked().getOrCreateIdleTimeCounter()
13574                                 .increment(myIdleTimeMs, elapsedRealtimeMs);
13575                     }
13576 
13577                     if (uidEstimatedConsumptionMah != null) {
13578                         double uidEstMah = mWifiPowerCalculator.calcPowerFromControllerDataMah(
13579                                 scanRxTimeSinceMarkMs, scanTxTimeSinceMarkMs, myIdleTimeMs);
13580                         uidEstimatedConsumptionMah.incrementValue(uid.getUid(), uidEstMah);
13581                     }
13582                 }
13583 
13584                 if (DEBUG_ENERGY) {
13585                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
13586                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
13587                 }
13588 
13589                 // Distribute the remaining Tx power appropriately between all apps that transmitted
13590                 // packets.
13591                 for (int i = 0; i < txPackets.size(); i++) {
13592                     final int uid = txPackets.keyAt(i);
13593                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
13594                             / totalTxPackets;
13595                     txTimesMs.incrementValue(uid, myTxTimeMs);
13596                 }
13597 
13598                 // Distribute the remaining Rx power appropriately between all apps that received
13599                 // packets.
13600                 for (int i = 0; i < rxPackets.size(); i++) {
13601                     final int uid = rxPackets.keyAt(i);
13602                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
13603                             / totalRxPackets;
13604                     rxTimesMs.incrementValue(uid, myRxTimeMs);
13605                 }
13606 
13607                 for (int i = 0; i < txTimesMs.size(); i++) {
13608                     final int uid = txTimesMs.keyAt(i);
13609                     final long myTxTimeMs = txTimesMs.valueAt(i);
13610                     if (DEBUG_ENERGY) {
13611                         Slog.d(TAG, "  TxTime for UID " + uid + ": " + myTxTimeMs + " ms");
13612                     }
13613                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
13614                             .getOrCreateWifiControllerActivityLocked()
13615                             .getOrCreateTxTimeCounters()[0]
13616                             .increment(myTxTimeMs, elapsedRealtimeMs);
13617                     if (uidEstimatedConsumptionMah != null) {
13618                         uidEstimatedConsumptionMah.incrementValue(uid,
13619                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
13620                                         0, myTxTimeMs, 0));
13621                     }
13622                 }
13623 
13624                 for (int i = 0; i < rxTimesMs.size(); i++) {
13625                     final int uid = rxTimesMs.keyAt(i);
13626                     final long myRxTimeMs = rxTimesMs.valueAt(i);
13627                     if (DEBUG_ENERGY) {
13628                         Slog.d(TAG, "  RxTime for UID " + uid + ": " + myRxTimeMs + " ms");
13629                     }
13630 
13631                     getUidStatsLocked(rxTimesMs.keyAt(i), elapsedRealtimeMs, uptimeMs)
13632                             .getOrCreateWifiControllerActivityLocked()
13633                             .getOrCreateRxTimeCounter()
13634                             .increment(myRxTimeMs, elapsedRealtimeMs);
13635                     if (uidEstimatedConsumptionMah != null) {
13636                         uidEstimatedConsumptionMah.incrementValue(uid,
13637                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
13638                                         myRxTimeMs, 0, 0));
13639                     }
13640                 }
13641 
13642                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
13643 
13644                 // Update WiFi controller stats.
13645                 mWifiActivity.getOrCreateRxTimeCounter().increment(
13646                         info.getControllerRxDurationMillis(), elapsedRealtimeMs);
13647                 mWifiActivity.getOrCreateTxTimeCounters()[0].increment(
13648                         info.getControllerTxDurationMillis(), elapsedRealtimeMs);
13649                 mWifiActivity.getScanTimeCounter().addCountLocked(
13650                         info.getControllerScanDurationMillis());
13651                 mWifiActivity.getOrCreateIdleTimeCounter().increment(
13652                         info.getControllerIdleDurationMillis(), elapsedRealtimeMs);
13653 
13654                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
13655                 final double opVolt = mPowerProfile.getAveragePower(
13656                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
13657                 double controllerMaMs = 0;
13658                 if (opVolt != 0) {
13659                     // We store the power drain as mAms.
13660                     controllerMaMs = info.getControllerEnergyUsedMicroJoules() / opVolt;
13661                     mWifiActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
13662                 }
13663                 // Converting uWs to mAms.
13664                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
13665                 long monitoredRailChargeConsumedMaMs =
13666                         (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt);
13667                 mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
13668                         monitoredRailChargeConsumedMaMs);
13669                 mHistoryCur.wifiRailChargeMah +=
13670                         (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
13671                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
13672                 mTmpRailStats.resetWifiTotalEnergyUsed();
13673 
13674                 if (uidEstimatedConsumptionMah != null) {
13675                     totalEstimatedConsumptionMah = Math.max(controllerMaMs / MILLISECONDS_IN_HOUR,
13676                             mWifiPowerCalculator.calcPowerFromControllerDataMah(
13677                                     rxTimeMs, txTimeMs, idleTimeMs));
13678                 }
13679             }
13680 
13681             // Update the MeasuredEnergyStats information.
13682             if (uidEstimatedConsumptionMah != null) {
13683                 mGlobalMeasuredEnergyStats.updateStandardBucket(
13684                         MeasuredEnergyStats.POWER_BUCKET_WIFI, consumedChargeUC);
13685 
13686                 // Now calculate the consumption for each uid, according to its proportional usage.
13687                 if (!mHasWifiReporting) {
13688                     final long globalTimeMs = mGlobalWifiRunningTimer
13689                             .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
13690                     mGlobalWifiRunningTimer.setMark(elapsedRealtimeMs);
13691                     totalEstimatedConsumptionMah = mWifiPowerCalculator
13692                             .calcGlobalPowerWithoutControllerDataMah(globalTimeMs);
13693                 }
13694                 distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_WIFI,
13695                         consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah,
13696                         elapsedRealtimeMs);
13697             }
13698         }
13699     }
13700 
13701     private ModemActivityInfo mLastModemActivityInfo = null;
13702 
13703     /**
13704      * Distribute Cell radio energy info and network traffic to apps.
13705      */
noteModemControllerActivity(@ullable final ModemActivityInfo activityInfo, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager)13706     public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo,
13707             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
13708             @NonNull NetworkStatsManager networkStatsManager) {
13709         if (DEBUG_ENERGY) {
13710             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
13711         }
13712         ModemActivityInfo deltaInfo = mLastModemActivityInfo == null ? activityInfo
13713                 : mLastModemActivityInfo.getDelta(activityInfo);
13714         mLastModemActivityInfo = activityInfo;
13715 
13716         // Add modem tx power to history.
13717         addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs);
13718 
13719         // Grab a separate lock to acquire the network stats, which may do I/O.
13720         NetworkStats delta = null;
13721         synchronized (mModemNetworkLock) {
13722             final NetworkStats latestStats = readMobileNetworkStatsLocked(networkStatsManager);
13723             if (latestStats != null) {
13724                 delta = latestStats.subtract(mLastModemNetworkStats);
13725                 mLastModemNetworkStats = latestStats;
13726             }
13727         }
13728 
13729         synchronized (this) {
13730             final long totalRadioDurationMs =
13731                     mMobileRadioActiveTimer.getTimeSinceMarkLocked(
13732                             elapsedRealtimeMs * 1000) / 1000;
13733             mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
13734             final long phoneOnDurationMs = Math.min(totalRadioDurationMs,
13735                     mPhoneOnTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000);
13736             mPhoneOnTimer.setMark(elapsedRealtimeMs);
13737 
13738             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
13739                 return;
13740             }
13741 
13742             final SparseDoubleArray uidEstimatedConsumptionMah;
13743             final long dataConsumedChargeUC;
13744             if (consumedChargeUC > 0 && mMobileRadioPowerCalculator != null
13745                     && mGlobalMeasuredEnergyStats != null) {
13746                 // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the
13747                 // numerator for long rounding.
13748                 final long phoneConsumedChargeUC =
13749                         (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2)
13750                                 / totalRadioDurationMs;
13751                 dataConsumedChargeUC = consumedChargeUC - phoneConsumedChargeUC;
13752                 mGlobalMeasuredEnergyStats.updateStandardBucket(
13753                         MeasuredEnergyStats.POWER_BUCKET_PHONE, phoneConsumedChargeUC);
13754                 mGlobalMeasuredEnergyStats.updateStandardBucket(
13755                         MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO, dataConsumedChargeUC);
13756                 uidEstimatedConsumptionMah = new SparseDoubleArray();
13757             } else {
13758                 uidEstimatedConsumptionMah = null;
13759                 dataConsumedChargeUC = POWER_DATA_UNAVAILABLE;
13760             }
13761 
13762             if (deltaInfo != null) {
13763                 mHasModemReporting = true;
13764                 mModemActivity.getOrCreateIdleTimeCounter()
13765                         .increment(deltaInfo.getIdleTimeMillis(), elapsedRealtimeMs);
13766                 mModemActivity.getSleepTimeCounter().addCountLocked(
13767                         deltaInfo.getSleepTimeMillis());
13768                 mModemActivity.getOrCreateRxTimeCounter()
13769                         .increment(deltaInfo.getReceiveTimeMillis(), elapsedRealtimeMs);
13770                 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels(); lvl++) {
13771                     mModemActivity.getOrCreateTxTimeCounters()[lvl]
13772                             .increment(deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl),
13773                                     elapsedRealtimeMs);
13774                 }
13775 
13776                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
13777                 final double opVolt = mPowerProfile.getAveragePower(
13778                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
13779                 if (opVolt != 0) {
13780                     double energyUsed =
13781                             deltaInfo.getSleepTimeMillis() *
13782                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
13783                             + deltaInfo.getIdleTimeMillis() *
13784                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
13785                             + deltaInfo.getReceiveTimeMillis() *
13786                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
13787                     for (int i = 0; i < Math.min(ModemActivityInfo.getNumTxPowerLevels(),
13788                             CellSignalStrength.getNumSignalStrengthLevels()); i++) {
13789                         energyUsed += deltaInfo.getTransmitDurationMillisAtPowerLevel(i)
13790                                 * mPowerProfile.getAveragePower(
13791                                         PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
13792                     }
13793 
13794                     // We store the power drain as mAms.
13795                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
13796                     // Converting uWs to mAms.
13797                     // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
13798                     long monitoredRailChargeConsumedMaMs =
13799                             (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
13800                     mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
13801                             monitoredRailChargeConsumedMaMs);
13802                     mHistoryCur.modemRailChargeMah +=
13803                             (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
13804                     addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
13805                     mTmpRailStats.resetCellularTotalEnergyUsed();
13806                 }
13807 
13808                 incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs);
13809             }
13810             long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
13811                     elapsedRealtimeMs * 1000);
13812             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
13813 
13814             long totalRxPackets = 0;
13815             long totalTxPackets = 0;
13816             if (delta != null) {
13817                 for (NetworkStats.Entry entry : delta) {
13818                     if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
13819                         continue;
13820                     }
13821 
13822                     if (DEBUG_ENERGY) {
13823                         Slog.d(TAG, "Mobile uid " + entry.getUid() + ": delta rx="
13824                                 + entry.getRxBytes() + " tx=" + entry.getTxBytes()
13825                                 + " rxPackets=" + entry.getRxPackets()
13826                                 + " txPackets=" + entry.getTxPackets());
13827                     }
13828 
13829                     totalRxPackets += entry.getRxPackets();
13830                     totalTxPackets += entry.getTxPackets();
13831 
13832                     final Uid u = getUidStatsLocked(
13833                             mapUid(entry.getUid()), elapsedRealtimeMs, uptimeMs);
13834                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.getRxBytes(),
13835                             entry.getRxPackets());
13836                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.getTxBytes(),
13837                             entry.getTxPackets());
13838                     if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
13839                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
13840                                 entry.getRxBytes(), entry.getRxPackets());
13841                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
13842                                 entry.getTxBytes(), entry.getTxPackets());
13843                     }
13844 
13845                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
13846                             entry.getRxBytes());
13847                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
13848                             entry.getTxBytes());
13849                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
13850                             entry.getRxPackets());
13851                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
13852                             entry.getTxPackets());
13853                 }
13854 
13855                 // Now distribute proportional blame to the apps that did networking.
13856                 long totalPackets = totalRxPackets + totalTxPackets;
13857                 if (totalPackets > 0) {
13858                     for (NetworkStats.Entry entry : delta) {
13859                         if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
13860                             continue;
13861                         }
13862 
13863                         final Uid u = getUidStatsLocked(mapUid(entry.getUid()),
13864                                 elapsedRealtimeMs, uptimeMs);
13865 
13866                         // Distribute total radio active time in to this app.
13867                         final long appPackets = entry.getRxPackets() + entry.getTxPackets();
13868                         final long appRadioTimeUs =
13869                                 (totalAppRadioTimeUs * appPackets) / totalPackets;
13870                         u.noteMobileRadioActiveTimeLocked(appRadioTimeUs, elapsedRealtimeMs);
13871 
13872                         // Distribute measured mobile radio charge consumption based on app radio
13873                         // active time
13874                         if (uidEstimatedConsumptionMah != null) {
13875                             uidEstimatedConsumptionMah.incrementValue(u.getUid(),
13876                                     mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
13877                                             appRadioTimeUs / 1000));
13878                         }
13879 
13880                         // Remove this app from the totals, so that we don't lose any time
13881                         // due to rounding.
13882                         totalAppRadioTimeUs -= appRadioTimeUs;
13883                         totalPackets -= appPackets;
13884 
13885                         if (deltaInfo != null) {
13886                             ControllerActivityCounterImpl activityCounter =
13887                                     u.getOrCreateModemControllerActivityLocked();
13888                             if (totalRxPackets > 0 && entry.getRxPackets() > 0) {
13889                                 final long rxMs = (entry.getRxPackets()
13890                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
13891                                 activityCounter.getOrCreateRxTimeCounter()
13892                                         .increment(rxMs, elapsedRealtimeMs);
13893                             }
13894 
13895                             if (totalTxPackets > 0 && entry.getTxPackets() > 0) {
13896                                 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels();
13897                                         lvl++) {
13898                                     long txMs = entry.getTxPackets()
13899                                             * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
13900                                     txMs /= totalTxPackets;
13901                                     activityCounter.getOrCreateTxTimeCounters()[lvl]
13902                                             .increment(txMs, elapsedRealtimeMs);
13903                                 }
13904                             }
13905                         }
13906                     }
13907                 }
13908 
13909                 if (totalAppRadioTimeUs > 0) {
13910                     // Whoops, there is some radio time we can't blame on an app!
13911                     mMobileRadioActiveUnknownTime.addCountLocked(totalAppRadioTimeUs);
13912                     mMobileRadioActiveUnknownCount.addCountLocked(1);
13913                 }
13914 
13915 
13916                 // Update the MeasuredEnergyStats information.
13917                 if (uidEstimatedConsumptionMah != null) {
13918                     double totalEstimatedConsumptionMah = 0.0;
13919                     totalEstimatedConsumptionMah +=
13920                             mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
13921                                     totalRadioDurationMs);
13922 
13923                     // Estimate idle power consumption at each signal strength level
13924                     final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
13925                     for (int strengthLevel = 0; strengthLevel < numSignalStrengthLevels;
13926                             strengthLevel++) {
13927                         final long strengthLevelDurationMs =
13928                                 mPhoneSignalStrengthsTimer[strengthLevel].getTimeSinceMarkLocked(
13929                                         elapsedRealtimeMs * 1000) / 1000;
13930                         mPhoneSignalStrengthsTimer[strengthLevel].setMark(elapsedRealtimeMs);
13931 
13932                         totalEstimatedConsumptionMah +=
13933                                 mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
13934                                         strengthLevelDurationMs, strengthLevel);
13935                     }
13936 
13937                     // Estimate total active radio power consumption since last mark.
13938                     final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
13939                             elapsedRealtimeMs * 1000) / 1000;
13940                     mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs);
13941                     totalEstimatedConsumptionMah +=
13942                             mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
13943 
13944                     distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO,
13945                             dataConsumedChargeUC, uidEstimatedConsumptionMah,
13946                             totalEstimatedConsumptionMah, elapsedRealtimeMs);
13947                 }
13948 
13949                 delta = null;
13950             }
13951         }
13952     }
13953 
13954     @GuardedBy("this")
incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs)13955     private void incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs) {
13956         final int infoSize = deltaInfo.getSpecificInfoLength();
13957         if (infoSize == 1 && deltaInfo.getSpecificInfoRat(0)
13958                 == AccessNetworkConstants.AccessNetworkType.UNKNOWN
13959                 && deltaInfo.getSpecificInfoFrequencyRange(0)
13960                 == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
13961             // Specific info data unavailable. Proportionally smear Rx and Tx times across each RAT.
13962             final int levelCount = CellSignalStrength.getNumSignalStrengthLevels();
13963             long[] perSignalStrengthActiveTimeMs = new long[levelCount];
13964             long totalActiveTimeMs = 0;
13965 
13966             for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13967                 final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13968                 if (ratStats == null) continue;
13969 
13970                 final int freqCount = ratStats.getFrequencyRangeCount();
13971                 for (int freq = 0; freq < freqCount; freq++) {
13972                     for (int level = 0; level < levelCount; level++) {
13973                         final long durationMs = ratStats.getTimeSinceMark(freq, level,
13974                                 elapsedRealtimeMs);
13975                         perSignalStrengthActiveTimeMs[level] += durationMs;
13976                         totalActiveTimeMs += durationMs;
13977                     }
13978                 }
13979             }
13980             if (totalActiveTimeMs != 0) {
13981                 // Smear the provided Tx/Rx durations across each RAT, frequency, and signal
13982                 // strength.
13983                 for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13984                     final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13985                     if (ratStats == null) continue;
13986 
13987                     final int freqCount = ratStats.getFrequencyRangeCount();
13988                     for (int freq = 0; freq < freqCount; freq++) {
13989                         long frequencyDurationMs = 0;
13990                         for (int level = 0; level < levelCount; level++) {
13991                             final long durationMs = ratStats.getTimeSinceMark(freq, level,
13992                                     elapsedRealtimeMs);
13993                             final long totalLvlDurationMs =
13994                                     perSignalStrengthActiveTimeMs[level];
13995                             if (totalLvlDurationMs == 0) continue;
13996                             final long totalTxLvlDurations =
13997                                     deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
13998                             // Smear HAL provided Tx power level duration based on active modem
13999                             // duration in a given state. (Add totalLvlDurationMs / 2 before
14000                             // the integer division with totalLvlDurationMs for rounding.)
14001                             final long proportionalTxDurationMs =
14002                                     (durationMs * totalTxLvlDurations
14003                                             + (totalLvlDurationMs / 2)) / totalLvlDurationMs;
14004                             ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
14005                             frequencyDurationMs += durationMs;
14006                         }
14007                         final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
14008                         // Smear HAL provided Rx power duration based on active modem
14009                         // duration in a given state.  (Add totalActiveTimeMs / 2 before the
14010                         // integer division with totalActiveTimeMs for rounding.)
14011                         final long proportionalRxDurationMs =
14012                                 (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
14013                                         / 2)) / totalActiveTimeMs;
14014                         ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
14015                     }
14016 
14017                 }
14018             }
14019         } else {
14020             // Specific data available.
14021             for (int index = 0; index < infoSize; index++) {
14022                 final int rat = deltaInfo.getSpecificInfoRat(index);
14023                 final int freq = deltaInfo.getSpecificInfoFrequencyRange(index);
14024 
14025                 // Map RadioAccessNetworkType to course grain RadioAccessTechnology.
14026                 final int ratBucket = mapRadioAccessNetworkTypeToRadioAccessTechnology(rat);
14027                 final RadioAccessTechnologyBatteryStats ratStats = getRatBatteryStatsLocked(
14028                         ratBucket);
14029 
14030                 final long rxTimeMs = deltaInfo.getReceiveTimeMillis(rat, freq);
14031                 final int[] txTimesMs = deltaInfo.getTransmitTimeMillis(rat, freq);
14032 
14033                 ratStats.incrementRxDuration(freq, rxTimeMs);
14034                 final int numTxLvl = txTimesMs.length;
14035                 for (int lvl = 0; lvl < numTxLvl; lvl++) {
14036                     ratStats.incrementTxDuration(freq, lvl, txTimesMs[lvl]);
14037                 }
14038             }
14039         }
14040 
14041         for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
14042             final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
14043             if (ratStats == null) continue;
14044             ratStats.setMark(elapsedRealtimeMs);
14045         }
14046     }
14047 
14048     /**
14049      * Add modem tx power to history
14050      * Device is said to be in high cellular transmit power when it has spent most of the transmit
14051      * time at the highest power level.
14052      * @param activityInfo
14053      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo, long elapsedRealtimeMs, long uptimeMs)14054     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo,
14055             long elapsedRealtimeMs, long uptimeMs) {
14056         if (activityInfo == null) {
14057             return;
14058         }
14059         int levelMaxTimeSpent = 0;
14060         for (int i = 1; i < ModemActivityInfo.getNumTxPowerLevels(); i++) {
14061             if (activityInfo.getTransmitDurationMillisAtPowerLevel(i)
14062                     > activityInfo.getTransmitDurationMillisAtPowerLevel(levelMaxTimeSpent)) {
14063                 levelMaxTimeSpent = i;
14064             }
14065         }
14066         if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) {
14067             mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
14068             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
14069         }
14070     }
14071 
14072     private final class BluetoothActivityInfoCache {
14073         long idleTimeMs;
14074         long rxTimeMs;
14075         long txTimeMs;
14076         long energy;
14077 
14078         SparseLongArray uidRxBytes = new SparseLongArray();
14079         SparseLongArray uidTxBytes = new SparseLongArray();
14080 
set(BluetoothActivityEnergyInfo info)14081         void set(BluetoothActivityEnergyInfo info) {
14082             idleTimeMs = info.getControllerIdleTimeMillis();
14083             rxTimeMs = info.getControllerRxTimeMillis();
14084             txTimeMs = info.getControllerTxTimeMillis();
14085             energy = info.getControllerEnergyUsed();
14086             if (!info.getUidTraffic().isEmpty()) {
14087                 for (UidTraffic traffic : info.getUidTraffic()) {
14088                     uidRxBytes.incrementValue(traffic.getUid(), traffic.getRxBytes());
14089                     uidTxBytes.incrementValue(traffic.getUid(), traffic.getTxBytes());
14090                 }
14091             }
14092         }
14093 
reset()14094         void reset() {
14095             idleTimeMs = 0;
14096             rxTimeMs = 0;
14097             txTimeMs = 0;
14098             energy = 0;
14099             uidRxBytes.clear();
14100             uidTxBytes.clear();
14101         }
14102     }
14103 
14104     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
14105             = new BluetoothActivityInfoCache();
14106 
14107     /**
14108      * Distribute Bluetooth energy info and network traffic to apps.
14109      *
14110      * @param info The accumulated energy information from the bluetooth controller.
14111      */
14112     @GuardedBy("this")
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)14113     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
14114             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
14115         if (DEBUG_ENERGY) {
14116             Slog.d(TAG, "Updating bluetooth stats: " + info);
14117         }
14118 
14119         if (info == null) {
14120             return;
14121         }
14122         if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
14123             mLastBluetoothActivityInfo.set(info);
14124             return;
14125         }
14126 
14127         mHasBluetoothReporting = true;
14128 
14129         if (info.getControllerRxTimeMillis() < mLastBluetoothActivityInfo.rxTimeMs
14130                 || info.getControllerTxTimeMillis() < mLastBluetoothActivityInfo.txTimeMs
14131                 || info.getControllerIdleTimeMillis() < mLastBluetoothActivityInfo.idleTimeMs
14132                 || info.getControllerEnergyUsed() < mLastBluetoothActivityInfo.energy) {
14133             // A drop in accumulated Bluetooth stats is a sign of a Bluetooth crash.
14134             // Reset the preserved previous snapshot in order to restart accumulating deltas.
14135             mLastBluetoothActivityInfo.reset();
14136         }
14137 
14138         final long rxTimeMs =
14139                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
14140         final long txTimeMs =
14141                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
14142         final long idleTimeMs =
14143                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
14144 
14145         if (DEBUG_ENERGY) {
14146             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
14147             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
14148             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
14149             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
14150         }
14151 
14152         final SparseDoubleArray uidEstimatedConsumptionMah =
14153                 (mGlobalMeasuredEnergyStats != null
14154                         && mBluetoothPowerCalculator != null && consumedChargeUC > 0) ?
14155                         new SparseDoubleArray() : null;
14156 
14157         long totalScanTimeMs = 0;
14158 
14159         final int uidCount = mUidStats.size();
14160         for (int i = 0; i < uidCount; i++) {
14161             final Uid u = mUidStats.valueAt(i);
14162             if (u.mBluetoothScanTimer == null) {
14163                 continue;
14164             }
14165 
14166             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
14167                     elapsedRealtimeMs * 1000) / 1000;
14168         }
14169 
14170         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
14171         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
14172 
14173         if (DEBUG_ENERGY) {
14174             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
14175                     + " TX=" + normalizeScanTxTime);
14176         }
14177 
14178         long leftOverRxTimeMs = rxTimeMs;
14179         long leftOverTxTimeMs = txTimeMs;
14180 
14181         final SparseLongArray rxTimesMs = new SparseLongArray(uidCount);
14182         final SparseLongArray txTimesMs = new SparseLongArray(uidCount);
14183 
14184         for (int i = 0; i < uidCount; i++) {
14185             final Uid u = mUidStats.valueAt(i);
14186             if (u.mBluetoothScanTimer == null) {
14187                 continue;
14188             }
14189 
14190             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
14191                     elapsedRealtimeMs * 1000) / 1000;
14192             if (scanTimeSinceMarkMs > 0) {
14193                 // Set the new mark so that next time we get new data since this point.
14194                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
14195 
14196                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
14197                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
14198 
14199                 if (normalizeScanRxTime) {
14200                     // Scan time is longer than the total rx time in the controller,
14201                     // so distribute the scan time proportionately. This means regular traffic
14202                     // will not blamed, but scans are more expensive anyways.
14203                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
14204                 }
14205 
14206                 if (normalizeScanTxTime) {
14207                     // Scan time is longer than the total tx time in the controller,
14208                     // so distribute the scan time proportionately. This means regular traffic
14209                     // will not blamed, but scans are more expensive anyways.
14210                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
14211                 }
14212 
14213                 rxTimesMs.incrementValue(u.getUid(), scanTimeRxSinceMarkMs);
14214                 txTimesMs.incrementValue(u.getUid(), scanTimeTxSinceMarkMs);
14215 
14216                 if (uidEstimatedConsumptionMah != null) {
14217                     uidEstimatedConsumptionMah.incrementValue(u.getUid(),
14218                             mBluetoothPowerCalculator.calculatePowerMah(
14219                                     scanTimeRxSinceMarkMs, scanTimeTxSinceMarkMs, 0));
14220                 }
14221 
14222                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
14223                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
14224             }
14225         }
14226 
14227         if (DEBUG_ENERGY) {
14228             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
14229                     + leftOverTxTimeMs);
14230         }
14231 
14232         //
14233         // Now distribute blame to apps that did bluetooth traffic.
14234         //
14235 
14236         long totalTxBytes = 0;
14237         long totalRxBytes = 0;
14238 
14239         final List<UidTraffic> uidTraffic = info.getUidTraffic();
14240         final int numUids = uidTraffic.size();
14241         for (int i = 0; i < numUids; i++) {
14242             final UidTraffic traffic = uidTraffic.get(i);
14243             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
14244                     traffic.getUid());
14245             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
14246                     traffic.getUid());
14247 
14248             // Add to the global counters.
14249             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
14250             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
14251 
14252             // Add to the UID counters.
14253             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()), elapsedRealtimeMs, uptimeMs);
14254             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
14255             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
14256 
14257             // Calculate the total traffic.
14258             totalRxBytes += rxBytes;
14259             totalTxBytes += txBytes;
14260         }
14261 
14262         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
14263                 || leftOverTxTimeMs != 0)) {
14264             for (int i = 0; i < numUids; i++) {
14265                 final UidTraffic traffic = uidTraffic.get(i);
14266                 final int uid = traffic.getUid();
14267                 final long rxBytes =
14268                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
14269                 final long txBytes =
14270                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
14271 
14272                 final Uid u = getUidStatsLocked(mapUid(uid), elapsedRealtimeMs, uptimeMs);
14273                 final ControllerActivityCounterImpl counter =
14274                         u.getOrCreateBluetoothControllerActivityLocked();
14275 
14276                 if (totalRxBytes > 0 && rxBytes > 0) {
14277                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
14278                     rxTimesMs.incrementValue(uid, timeRxMs);
14279                 }
14280 
14281                 if (totalTxBytes > 0 && txBytes > 0) {
14282                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
14283                     txTimesMs.incrementValue(uid, timeTxMs);
14284                 }
14285             }
14286 
14287             for (int i = 0; i < txTimesMs.size(); i++) {
14288                 final int uid = txTimesMs.keyAt(i);
14289                 final long myTxTimeMs = txTimesMs.valueAt(i);
14290                 if (DEBUG_ENERGY) {
14291                     Slog.d(TAG, "  TxTime for UID " + uid + ": " + myTxTimeMs + " ms");
14292                 }
14293                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
14294                         .getOrCreateBluetoothControllerActivityLocked()
14295                         .getOrCreateTxTimeCounters()[0]
14296                         .increment(myTxTimeMs, elapsedRealtimeMs);
14297                 if (uidEstimatedConsumptionMah != null) {
14298                     uidEstimatedConsumptionMah.incrementValue(uid,
14299                             mBluetoothPowerCalculator.calculatePowerMah(0, myTxTimeMs, 0));
14300                 }
14301             }
14302 
14303             for (int i = 0; i < rxTimesMs.size(); i++) {
14304                 final int uid = rxTimesMs.keyAt(i);
14305                 final long myRxTimeMs = rxTimesMs.valueAt(i);
14306                 if (DEBUG_ENERGY) {
14307                     Slog.d(TAG, "  RxTime for UID " + uid + ": " + myRxTimeMs + " ms");
14308                 }
14309 
14310                 getUidStatsLocked(rxTimesMs.keyAt(i), elapsedRealtimeMs, uptimeMs)
14311                         .getOrCreateBluetoothControllerActivityLocked()
14312                         .getOrCreateRxTimeCounter()
14313                         .increment(myRxTimeMs, elapsedRealtimeMs);
14314                 if (uidEstimatedConsumptionMah != null) {
14315                     uidEstimatedConsumptionMah.incrementValue(uid,
14316                             mBluetoothPowerCalculator.calculatePowerMah(myRxTimeMs, 0, 0));
14317                 }
14318             }
14319         }
14320 
14321         mBluetoothActivity.getOrCreateRxTimeCounter().increment(rxTimeMs, elapsedRealtimeMs);
14322         mBluetoothActivity.getOrCreateTxTimeCounters()[0].increment(txTimeMs, elapsedRealtimeMs);
14323         mBluetoothActivity.getOrCreateIdleTimeCounter().increment(idleTimeMs, elapsedRealtimeMs);
14324 
14325         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
14326         final double opVolt = mPowerProfile.getAveragePower(
14327                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
14328         double controllerMaMs = 0;
14329         if (opVolt != 0) {
14330             controllerMaMs = (info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
14331                     / opVolt;
14332             // We store the power drain as mAms.
14333             mBluetoothActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
14334         }
14335 
14336         // Update the MeasuredEnergyStats information.
14337         if (uidEstimatedConsumptionMah != null) {
14338             mGlobalMeasuredEnergyStats.updateStandardBucket(
14339                     MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH, consumedChargeUC);
14340 
14341             double totalEstimatedMah
14342                     = mBluetoothPowerCalculator.calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
14343             totalEstimatedMah = Math.max(totalEstimatedMah, controllerMaMs / MILLISECONDS_IN_HOUR);
14344             distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH,
14345                     consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedMah,
14346                     elapsedRealtimeMs);
14347         }
14348 
14349         mLastBluetoothActivityInfo.set(info);
14350     }
14351     /**
14352      * Read Resource Power Manager (RPM) state and voter times.
14353      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
14354      * instead of fetching it anew.
14355      *
14356      * Note: This should be called without synchronizing this BatteryStatsImpl object
14357      */
fillLowPowerStats()14358     public void fillLowPowerStats() {
14359         if (mPlatformIdleStateCallback == null) return;
14360 
14361         RpmStats rpmStats = new RpmStats();
14362         long now = SystemClock.elapsedRealtime();
14363         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
14364             mPlatformIdleStateCallback.fillLowPowerStats(rpmStats);
14365             synchronized (this) {
14366                 mTmpRpmStats = rpmStats;
14367                 mLastRpmStatsUpdateTimeMs = now;
14368             }
14369         }
14370     }
14371 
14372     /**
14373      * Record Resource Power Manager (RPM) state and voter times.
14374      * TODO(b/185252376): Remove this logging. PowerStatsService logs the same data more
14375      * efficiently.
14376      */
updateRpmStatsLocked(long elapsedRealtimeUs)14377     public void updateRpmStatsLocked(long elapsedRealtimeUs) {
14378         if (mTmpRpmStats == null) return;
14379 
14380         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
14381                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
14382 
14383             // Update values for this platform state.
14384             final String pName = pstate.getKey();
14385             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
14386             final int pCount = pstate.getValue().mCount;
14387             getRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
14388             if (SCREEN_OFF_RPM_STATS_ENABLED) {
14389                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
14390             }
14391 
14392             // Update values for each voter of this platform state.
14393             for (Map.Entry<String, RpmStats.PowerStateElement> voter
14394                     : pstate.getValue().mVoters.entrySet()) {
14395                 final String vName = pName + "." + voter.getKey();
14396                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
14397                 final int vCount = voter.getValue().mCount;
14398                 getRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
14399                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
14400                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
14401                 }
14402             }
14403         }
14404 
14405         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
14406                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
14407 
14408             final String subsysName = subsys.getKey();
14409             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
14410                     : subsys.getValue().mStates.entrySet()) {
14411                 final String name = subsysName + "." + sstate.getKey();
14412                 final long timeUs = sstate.getValue().mTimeMs * 1000;
14413                 final int count = sstate.getValue().mCount;
14414                 getRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
14415                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
14416                     getScreenOffRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
14417                 }
14418             }
14419         }
14420     }
14421 
14422     /**
14423      * Accumulate Cpu charge consumption and distribute it to the correct state and the apps.
14424      * Only call if device is on battery.
14425      *
14426      * @param clusterChargeUC amount of charge (microcoulombs) consumed by each Cpu Cluster
14427      * @param accumulator collection of calculated uid cpu power consumption to smear
14428      *                    clusterChargeUC against.
14429      */
14430     @GuardedBy("this")
14431     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
updateCpuMeasuredEnergyStatsLocked(@onNull long[] clusterChargeUC, @NonNull CpuDeltaPowerAccumulator accumulator)14432     private void updateCpuMeasuredEnergyStatsLocked(@NonNull long[] clusterChargeUC,
14433             @NonNull CpuDeltaPowerAccumulator accumulator) {
14434         if (DEBUG_ENERGY) {
14435             Slog.d(TAG,
14436                     "Updating cpu cluster stats: " + clusterChargeUC.toString());
14437         }
14438         if (mGlobalMeasuredEnergyStats == null) {
14439             return;
14440         }
14441 
14442         final int numClusters = clusterChargeUC.length;
14443         long totalCpuChargeUC = 0;
14444         for (int i = 0; i < numClusters; i++) {
14445             totalCpuChargeUC += clusterChargeUC[i];
14446         }
14447         if (totalCpuChargeUC <= 0) return;
14448 
14449         final long timestampMs = mClock.elapsedRealtime();
14450 
14451         mGlobalMeasuredEnergyStats.updateStandardBucket(MeasuredEnergyStats.POWER_BUCKET_CPU,
14452                 totalCpuChargeUC, timestampMs);
14453 
14454         // Calculate the measured microcoulombs/calculated milliamp-hour charge ratio for each
14455         // cluster to normalize  each uid's estimated power usage against actual power usage for
14456         // a given cluster.
14457         final double[] clusterChargeRatio = new double[numClusters];
14458         for (int cluster = 0; cluster < numClusters; cluster++) {
14459 
14460             final double totalClusterChargeMah = accumulator.totalClusterChargesMah[cluster];
14461             if (totalClusterChargeMah <= 0.0) {
14462                 // This cluster did not have any work on it, since last update.
14463                 // Avoid dividing by zero.
14464                 clusterChargeRatio[cluster] = 0.0;
14465             } else {
14466                 clusterChargeRatio[cluster] =
14467                         clusterChargeUC[cluster] / accumulator.totalClusterChargesMah[cluster];
14468             }
14469         }
14470 
14471         // Assign and distribute power usage to apps based on their calculated cpu cluster charge.
14472         final long uidChargeArraySize = accumulator.perUidCpuClusterChargesMah.size();
14473         for (int i = 0; i < uidChargeArraySize; i++) {
14474             final Uid uid = accumulator.perUidCpuClusterChargesMah.keyAt(i);
14475             final double[] uidClusterChargesMah = accumulator.perUidCpuClusterChargesMah.valueAt(i);
14476 
14477             // Iterate each cpu cluster and sum the proportional measured cpu cluster charge to
14478             // get the total cpu charge consumed by a uid.
14479             long uidCpuChargeUC = 0;
14480             for (int cluster = 0; cluster < numClusters; cluster++) {
14481                 final double uidClusterChargeMah = uidClusterChargesMah[cluster];
14482 
14483                 // Proportionally allocate the measured cpu cluster charge to a uid using the
14484                 // measured charge/calculated charge ratio. Add 0.5 to round the proportional
14485                 // charge double to the nearest long value.
14486                 final long uidClusterChargeUC =
14487                         (long) (uidClusterChargeMah * clusterChargeRatio[cluster]
14488                                 + 0.5);
14489 
14490                 uidCpuChargeUC += uidClusterChargeUC;
14491             }
14492 
14493             if (uidCpuChargeUC < 0) {
14494                 Slog.wtf(TAG,
14495                         "Unexpected proportional measured charge (" + uidCpuChargeUC + ") for uid "
14496                                 + uid.mUid);
14497                 continue;
14498             }
14499 
14500             uid.addChargeToStandardBucketLocked(uidCpuChargeUC,
14501                     MeasuredEnergyStats.POWER_BUCKET_CPU, timestampMs);
14502         }
14503     }
14504 
14505     /**
14506      * Accumulate Display charge consumption and distribute it to the correct state and the apps.
14507      *
14508      * NOTE: The algorithm used makes the strong assumption that app foreground activity time
14509      * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported).
14510      * To the extent that those assumptions are violated, the algorithm will err.
14511      *
14512      * @param chargesUC amount of charge (microcoulombs) used by each Display since this was last
14513      *                 called.
14514      * @param screenStates each screen state at the time this data collection was scheduled
14515      */
14516     @GuardedBy("this")
updateDisplayMeasuredEnergyStatsLocked(long[] chargesUC, int[] screenStates, long elapsedRealtimeMs)14517     public void updateDisplayMeasuredEnergyStatsLocked(long[] chargesUC, int[] screenStates,
14518             long elapsedRealtimeMs) {
14519         if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + Arrays.toString(chargesUC));
14520         if (mGlobalMeasuredEnergyStats == null) {
14521             return;
14522         }
14523 
14524         final int numDisplays;
14525         if (mPerDisplayBatteryStats.length == screenStates.length) {
14526             numDisplays = screenStates.length;
14527         } else {
14528             // if this point is reached, it will be reached every display state change.
14529             // Rate limit the wtf logging to once every 100 display updates.
14530             if (mDisplayMismatchWtfCount++ % 100 == 0) {
14531                 Slog.wtf(TAG, "Mismatch between PowerProfile reported display count ("
14532                         + mPerDisplayBatteryStats.length
14533                         + ") and PowerStatsHal reported display count (" + screenStates.length
14534                         + ")");
14535             }
14536             // Keep the show going, use the shorter of the two.
14537             numDisplays = mPerDisplayBatteryStats.length < screenStates.length
14538                     ? mPerDisplayBatteryStats.length : screenStates.length;
14539         }
14540 
14541         final int[] oldScreenStates = new int[numDisplays];
14542         for (int i = 0; i < numDisplays; i++) {
14543             final int screenState = screenStates[i];
14544             oldScreenStates[i] = mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement;
14545             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
14546         }
14547 
14548         if (!mOnBatteryInternal) {
14549             // There's nothing further to update.
14550             return;
14551         }
14552         if (mIgnoreNextExternalStats) {
14553             // Although under ordinary resets we won't get here, and typically a new sync will
14554             // happen right after the reset, strictly speaking we need to set all mark times to now.
14555             final int uidStatsSize = mUidStats.size();
14556             for (int i = 0; i < uidStatsSize; i++) {
14557                 final Uid uid = mUidStats.valueAt(i);
14558                 uid.markProcessForegroundTimeUs(elapsedRealtimeMs, false);
14559             }
14560             return;
14561         }
14562 
14563         long totalScreenOnChargeUC = 0;
14564         for (int i = 0; i < numDisplays; i++) {
14565             final long chargeUC = chargesUC[i];
14566             if (chargeUC <= 0) {
14567                 // There's nothing further to update.
14568                 continue;
14569             }
14570 
14571             final @StandardPowerBucket int powerBucket =
14572                     MeasuredEnergyStats.getDisplayPowerBucket(oldScreenStates[i]);
14573             mGlobalMeasuredEnergyStats.updateStandardBucket(powerBucket, chargeUC);
14574             if (powerBucket == MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON) {
14575                 totalScreenOnChargeUC += chargeUC;
14576             }
14577         }
14578 
14579         // Now we blame individual apps, but only if the display was ON.
14580         if (totalScreenOnChargeUC <= 0) {
14581             return;
14582         }
14583         // TODO(b/175726779): Consider unifying the code with the non-rail display power blaming.
14584 
14585         // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is
14586         // 'double counted' and will simply exceed the realtime that elapsed.
14587         // TODO(b/175726779): collect per display uid visibility for display power attribution.
14588 
14589         // Collect total time since mark so that we can normalize power.
14590         final SparseDoubleArray fgTimeUsArray = new SparseDoubleArray();
14591         final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
14592         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
14593         final int uidStatsSize = mUidStats.size();
14594         for (int i = 0; i < uidStatsSize; i++) {
14595             final Uid uid = mUidStats.valueAt(i);
14596             final long fgTimeUs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true);
14597             if (fgTimeUs == 0) continue;
14598             fgTimeUsArray.put(uid.getUid(), (double) fgTimeUs);
14599         }
14600         distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON,
14601                 totalScreenOnChargeUC, fgTimeUsArray, 0, elapsedRealtimeMs);
14602     }
14603 
14604     /**
14605      * Accumulate GNSS charge consumption and distribute it to the correct state and the apps.
14606      *
14607      * @param chargeUC amount of charge (microcoulombs) used by GNSS since this was last called.
14608      */
14609     @GuardedBy("this")
14610     public void updateGnssMeasuredEnergyStatsLocked(long chargeUC, long elapsedRealtimeMs) {
14611         if (DEBUG_ENERGY) Slog.d(TAG, "Updating gnss stats: " + chargeUC);
14612         if (mGlobalMeasuredEnergyStats == null) {
14613             return;
14614         }
14615 
14616         if (!mOnBatteryInternal || chargeUC <= 0) {
14617             // There's nothing further to update.
14618             return;
14619         }
14620         if (mIgnoreNextExternalStats) {
14621             // Although under ordinary resets we won't get here, and typically a new sync will
14622             // happen right after the reset, strictly speaking we need to set all mark times to now.
14623             final int uidStatsSize = mUidStats.size();
14624             for (int i = 0; i < uidStatsSize; i++) {
14625                 final Uid uid = mUidStats.valueAt(i);
14626                 uid.markGnssTimeUs(elapsedRealtimeMs);
14627             }
14628             return;
14629         }
14630 
14631         mGlobalMeasuredEnergyStats.updateStandardBucket(MeasuredEnergyStats.POWER_BUCKET_GNSS,
14632                 chargeUC);
14633 
14634         // Collect the per uid time since mark so that we can normalize power.
14635         final SparseDoubleArray gnssTimeUsArray = new SparseDoubleArray();
14636         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
14637         final int uidStatsSize = mUidStats.size();
14638         for (int i = 0; i < uidStatsSize; i++) {
14639             final Uid uid = mUidStats.valueAt(i);
14640             final long gnssTimeUs = uid.markGnssTimeUs(elapsedRealtimeMs);
14641             if (gnssTimeUs == 0) continue;
14642             gnssTimeUsArray.put(uid.getUid(), (double) gnssTimeUs);
14643         }
14644         distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_GNSS, chargeUC,
14645                 gnssTimeUsArray, 0, elapsedRealtimeMs);
14646     }
14647 
14648     /**
14649      * Accumulate Custom power bucket charge, globally and for each app.
14650      *
14651      * @param totalChargeUC charge (microcoulombs) used for this bucket since this was last called.
14652      * @param uidCharges map of uid->charge (microcoulombs) for this bucket since last called.
14653      *                    Data inside uidCharges will not be modified (treated immutable).
14654      *                    Uids not already known to BatteryStats will be ignored.
14655      */
14656     @GuardedBy("this")
14657     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToCustomBucketLocked
14658     public void updateCustomMeasuredEnergyStatsLocked(int customPowerBucket,
14659             long totalChargeUC, @Nullable SparseLongArray uidCharges) {
14660         if (DEBUG_ENERGY) {
14661             Slog.d(TAG, "Updating attributed measured charge stats for custom bucket "
14662                     + customPowerBucket
14663                     + " with total charge " + totalChargeUC
14664                     + " and uid charges " + String.valueOf(uidCharges));
14665         }
14666         if (mGlobalMeasuredEnergyStats == null) return;
14667         if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalChargeUC <= 0) return;
14668 
14669         mGlobalMeasuredEnergyStats.updateCustomBucket(customPowerBucket, totalChargeUC,
14670                 mClock.elapsedRealtime());
14671 
14672         if (uidCharges == null) return;
14673         final int numUids = uidCharges.size();
14674         for (int i = 0; i < numUids; i++) {
14675             final int uidInt = mapUid(uidCharges.keyAt(i));
14676             final long uidChargeUC = uidCharges.valueAt(i);
14677             if (uidChargeUC == 0) continue;
14678 
14679             final Uid uidObj = getAvailableUidStatsLocked(uidInt);
14680             if (uidObj != null) {
14681                 uidObj.addChargeToCustomBucketLocked(uidChargeUC, customPowerBucket);
14682             } else {
14683                 // Ignore any uid not already known to BatteryStats, rather than creating a new Uid.
14684                 // Otherwise we could end up reviving dead Uids. Note that the CPU data is updated
14685                 // first, so any uid that has used any CPU should already be known to BatteryStats.
14686                 // Recently removed uids (especially common for isolated uids) can reach this path
14687                 // and are ignored.
14688                 if (!Process.isIsolated(uidInt)) {
14689                     Slog.w(TAG, "Received measured charge " + totalChargeUC + " for custom bucket "
14690                             + customPowerBucket + " for non-existent uid " + uidInt);
14691                 }
14692             }
14693         }
14694     }
14695 
14696     /**
14697      * Attributes energy (for the given bucket) to each uid according to the following formula:
14698      *     blamedEnergy[uid] = totalEnergy * ratioNumerators[uid] / ratioDenominator;
14699      * <p>Does nothing if ratioDenominator is 0.
14700      *
14701      * <p>Here, ratioDenominator = max(sumOfAllRatioNumerators, minRatioDenominator),
14702      * so if given minRatioDenominator <= 0, then sumOfAllRatioNumerators will be used implicitly.
14703      *
14704      * <p>Note that ratioNumerators and minRatioDenominator must use the same units, but need not
14705      * use the same units as totalConsumedChargeUC (which must be in microcoulombs).
14706      *
14707      * <p>A consequence of minRatioDenominator is that the sum over all uids might be less than
14708      * totalConsumedChargeUC. This is intentional; the remainder is purposefully unnaccounted rather
14709      * than incorrectly blamed on uids, and implies unknown (non-uid) sources of drain.
14710      *
14711      * <p>All uids in ratioNumerators must exist in mUidStats already.
14712      */
14713     @GuardedBy("this")
14714     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
14715     private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket,
14716             long totalConsumedChargeUC, SparseDoubleArray ratioNumerators,
14717             double minRatioDenominator, long timestampMs) {
14718 
14719         // If the sum of all app usage was greater than the total, use that instead:
14720         double sumRatioNumerators = 0;
14721         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
14722             sumRatioNumerators += ratioNumerators.valueAt(i);
14723         }
14724         final double ratioDenominator = Math.max(sumRatioNumerators, minRatioDenominator);
14725         if (ratioDenominator <= 0) return;
14726 
14727         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
14728             final Uid uid = getAvailableUidStatsLocked(ratioNumerators.keyAt(i));
14729             final double ratioNumerator = ratioNumerators.valueAt(i);
14730             final long uidActualUC
14731                     = (long) (totalConsumedChargeUC * ratioNumerator / ratioDenominator + 0.5);
14732             uid.addChargeToStandardBucketLocked(uidActualUC, bucket, timestampMs);
14733         }
14734     }
14735 
14736     /**
14737      * Read and record Rail Energy data.
14738      */
14739     public void updateRailStatsLocked() {
14740         if (mMeasuredEnergyRetriever == null || !mTmpRailStats.isRailStatsAvailable()) {
14741             return;
14742         }
14743         mMeasuredEnergyRetriever.fillRailDataStats(mTmpRailStats);
14744     }
14745 
14746     /** Informs that external stats data has been completely flushed. */
14747     public void informThatAllExternalStatsAreFlushed() {
14748         synchronized (this) {
14749             // Any data from the pre-reset era is flushed, so we can henceforth process future data.
14750             mIgnoreNextExternalStats = false;
14751         }
14752     }
14753 
14754     /**
14755      * Read and distribute kernel wake lock use across apps.
14756      */
14757     public void updateKernelWakelocksLocked() {
14758         updateKernelWakelocksLocked(mClock.elapsedRealtime() * 1000);
14759     }
14760 
14761     /**
14762      * @see #updateKernelWakelocksLocked()
14763      */
14764     public void updateKernelWakelocksLocked(long elapsedRealtimeUs) {
14765         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
14766                 mTmpWakelockStats);
14767         if (wakelockStats == null) {
14768             // Not crashing might make board bringup easier.
14769             Slog.w(TAG, "Couldn't get kernel wake lock stats");
14770             return;
14771         }
14772 
14773         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
14774             String name = ent.getKey();
14775             KernelWakelockStats.Entry kws = ent.getValue();
14776 
14777             SamplingTimer kwlt = mKernelWakelockStats.get(name);
14778             if (kwlt == null) {
14779                 kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
14780                 mKernelWakelockStats.put(name, kwlt);
14781             }
14782 
14783             kwlt.update(kws.mTotalTime, kws.mCount, elapsedRealtimeUs);
14784             kwlt.setUpdateVersion(kws.mVersion);
14785         }
14786 
14787         int numWakelocksSetStale = 0;
14788         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
14789         // this time.
14790         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14791             SamplingTimer st = ent.getValue();
14792             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
14793                 st.endSample(elapsedRealtimeUs);
14794                 numWakelocksSetStale++;
14795             }
14796         }
14797 
14798         // Record whether we've seen a non-zero time (for debugging b/22716723).
14799         if (wakelockStats.isEmpty()) {
14800             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
14801         }
14802 
14803         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
14804             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
14805                     wakelockStats.kernelWakelockVersion);
14806         }
14807     }
14808 
14809     // We use an anonymous class to access these variables,
14810     // so they can't live on the stack or they'd have to be
14811     // final MutableLong objects (more allocations).
14812     // Used in updateCpuTimeLocked().
14813     long mTempTotalCpuUserTimeUs;
14814     long mTempTotalCpuSystemTimeUs;
14815     long[][] mWakeLockAllocationsUs;
14816 
14817     /**
14818      * Reads the newest memory stats from the kernel.
14819      */
14820     public void updateKernelMemoryBandwidthLocked() {
14821         updateKernelMemoryBandwidthLocked(mClock.elapsedRealtime() * 1000);
14822     }
14823 
14824     public void updateKernelMemoryBandwidthLocked(long elapsedRealtimeUs) {
14825         mKernelMemoryBandwidthStats.updateStats();
14826         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
14827         final int bandwidthEntryCount = bandwidthEntries.size();
14828         int index;
14829         for (int i = 0; i < bandwidthEntryCount; i++) {
14830             SamplingTimer timer;
14831             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
14832                 timer = mKernelMemoryStats.valueAt(index);
14833             } else {
14834                 timer = new SamplingTimer(mClock, mOnBatteryTimeBase);
14835                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
14836             }
14837             timer.update(bandwidthEntries.valueAt(i), 1, elapsedRealtimeUs);
14838             if (DEBUG_MEMORY) {
14839                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
14840                         + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i),
14841                         mKernelMemoryStats.get(
14842                                 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTimeUs,
14843                         mKernelMemoryStats.size()));
14844             }
14845         }
14846     }
14847 
14848     public boolean isOnBatteryLocked() {
14849         return mOnBatteryTimeBase.isRunning();
14850     }
14851 
14852     public boolean isOnBatteryScreenOffLocked() {
14853         return mOnBatteryScreenOffTimeBase.isRunning();
14854     }
14855 
14856     /**
14857      * Object for calculating and accumulating the estimated cpu power used while reading the
14858      * various cpu kernel files.
14859      */
14860     @VisibleForTesting
14861     public static class CpuDeltaPowerAccumulator {
14862         // Keeps track of total charge used per cluster.
14863         public final double[] totalClusterChargesMah;
14864         // Keeps track of charge used per cluster per uid.
14865         public final ArrayMap<Uid, double[]> perUidCpuClusterChargesMah;
14866 
14867         private final CpuPowerCalculator mCalculator;
14868         private Uid mCachedUid = null;
14869         private double[] mUidClusterCache = null;
14870 
14871         CpuDeltaPowerAccumulator(CpuPowerCalculator calculator, int nClusters) {
14872             mCalculator = calculator;
14873             totalClusterChargesMah = new double[nClusters];
14874             perUidCpuClusterChargesMah = new ArrayMap<>();
14875         }
14876 
14877         /** Add per cpu cluster durations to the currently cached uid. */
14878         public void addCpuClusterDurationsMs(Uid uid, long[] durationsMs) {
14879             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
14880             for (int cluster = 0; cluster < durationsMs.length; cluster++) {
14881                 final double estimatedDeltaMah = mCalculator.calculatePerCpuClusterPowerMah(cluster,
14882                         durationsMs[cluster]);
14883                 uidChargesMah[cluster] += estimatedDeltaMah;
14884                 totalClusterChargesMah[cluster] += estimatedDeltaMah;
14885             }
14886         }
14887 
14888         /** Add per speed per cpu cluster durations to the currently cached uid. */
14889         public void addCpuClusterSpeedDurationsMs(Uid uid, int cluster, int speed,
14890                 long durationsMs) {
14891             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
14892             final double estimatedDeltaMah = mCalculator.calculatePerCpuFreqPowerMah(cluster, speed,
14893                     durationsMs);
14894             uidChargesMah[cluster] += estimatedDeltaMah;
14895             totalClusterChargesMah[cluster] += estimatedDeltaMah;
14896         }
14897 
14898         private double[] getOrCreateUidCpuClusterCharges(Uid uid) {
14899             // Repeated additions on the same uid is very likely.
14900             // Skip a lookup if getting the same uid as the last get.
14901             if (uid == mCachedUid) return mUidClusterCache;
14902 
14903             double[] uidChargesMah = perUidCpuClusterChargesMah.get(uid);
14904             if (uidChargesMah == null) {
14905                 uidChargesMah = new double[totalClusterChargesMah.length];
14906                 perUidCpuClusterChargesMah.put(uid, uidChargesMah);
14907             }
14908             mCachedUid = uid;
14909             mUidClusterCache = uidChargesMah;
14910             return uidChargesMah;
14911         }
14912     }
14913 
14914     /**
14915      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
14916      * and we are on battery with screen off, we give more of the cpu time to those apps holding
14917      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
14918      * It's possible this will be invoked after the internal battery/screen states are updated, so
14919      * passing the appropriate battery/screen states to try attribute the cpu times to correct
14920      * buckets.
14921      */
14922     @GuardedBy("this")
14923     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff,
14924             long[] measuredCpuClusterChargeUC) {
14925         if (mPowerProfile == null) {
14926             return;
14927         }
14928 
14929         if (DEBUG_ENERGY_CPU) {
14930             Slog.d(TAG, "!Cpu updating!");
14931         }
14932 
14933         if (mCpuFreqs == null) {
14934             mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
14935         }
14936 
14937         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
14938         // usually holding the wakelock on behalf of an app.
14939         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
14940         ArrayList<StopwatchTimer> partialTimersToConsider = null;
14941         if (onBatteryScreenOff) {
14942             partialTimersToConsider = new ArrayList<>();
14943             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
14944                 final StopwatchTimer timer = mPartialTimers.get(i);
14945                 // Since the collection and blaming of wakelocks can be scheduled to run after
14946                 // some delay, the mPartialTimers list may have new entries. We can't blame
14947                 // the newly added timer for past cpu time, so we only consider timers that
14948                 // were present for one round of collection. Once a timer has gone through
14949                 // a round of collection, its mInList field is set to true.
14950                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
14951                     partialTimersToConsider.add(timer);
14952                 }
14953             }
14954         }
14955         markPartialTimersAsEligible();
14956 
14957         // When the battery is not on, we don't attribute the cpu times to any timers but we still
14958         // need to take the snapshots.
14959         if (!onBattery) {
14960             mCpuUidUserSysTimeReader.readDelta(false, null);
14961             mCpuUidFreqTimeReader.readDelta(false, null);
14962             mNumAllUidCpuTimeReads += 2;
14963             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
14964                 mCpuUidActiveTimeReader.readDelta(false, null);
14965                 mCpuUidClusterTimeReader.readDelta(false, null);
14966                 mNumAllUidCpuTimeReads += 2;
14967             }
14968             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
14969                 mKernelCpuSpeedReaders[cluster].readDelta();
14970             }
14971             mSystemServerCpuThreadReader.readDelta();
14972             return;
14973         }
14974 
14975         mUserInfoProvider.refreshUserIds();
14976         final SparseLongArray updatedUids = mCpuUidFreqTimeReader.perClusterTimesAvailable()
14977                 ? null : new SparseLongArray();
14978 
14979         final CpuDeltaPowerAccumulator powerAccumulator;
14980         if (mGlobalMeasuredEnergyStats != null
14981                 && mGlobalMeasuredEnergyStats.isStandardBucketSupported(
14982                 MeasuredEnergyStats.POWER_BUCKET_CPU) && mCpuPowerCalculator != null) {
14983             if (measuredCpuClusterChargeUC == null) {
14984                 Slog.wtf(TAG,
14985                         "POWER_BUCKET_CPU supported but no measured Cpu Cluster charge reported "
14986                                 + "on updateCpuTimeLocked!");
14987                 powerAccumulator = null;
14988             } else {
14989                 // Cpu Measured Energy is supported, create an object to accumulate the estimated
14990                 // charge consumption since the last cpu update
14991                 final int numClusters = mPowerProfile.getNumCpuClusters();
14992                 powerAccumulator = new CpuDeltaPowerAccumulator(mCpuPowerCalculator, numClusters);
14993             }
14994         } else {
14995             powerAccumulator = null;
14996         }
14997 
14998         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
14999         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
15000         // freqs, so no need to approximate these values.
15001         if (updatedUids != null) {
15002             updateClusterSpeedTimes(updatedUids, onBattery, powerAccumulator);
15003         }
15004         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff,
15005                 powerAccumulator);
15006         mNumAllUidCpuTimeReads += 2;
15007         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
15008             // Cpu Active times do not get any info ony how to attribute measured Cpu Cluster
15009             // charge, so not need to provide the powerAccumulator
15010             readKernelUidCpuActiveTimesLocked(onBattery);
15011             readKernelUidCpuClusterTimesLocked(onBattery, powerAccumulator);
15012             mNumAllUidCpuTimeReads += 2;
15013         }
15014 
15015         updateSystemServerThreadStats();
15016 
15017         if (powerAccumulator != null) {
15018             updateCpuMeasuredEnergyStatsLocked(measuredCpuClusterChargeUC, powerAccumulator);
15019         }
15020     }
15021 
15022     /**
15023      * Estimates the proportion of the System Server CPU activity (per cluster per speed)
15024      * spent on handling incoming binder calls.
15025      */
15026     @VisibleForTesting
15027     public void updateSystemServerThreadStats() {
15028         // There are some simplifying assumptions made in this algorithm
15029         // 1) We assume that if a thread handles incoming binder calls, all of its activity
15030         //    is spent doing that.  Most incoming calls are handled by threads allocated
15031         //    by the native layer in the binder thread pool, so this assumption is reasonable.
15032         // 2) We use the aggregate CPU time spent in different threads as a proxy for the CPU
15033         //    cost. In reality, in multi-core CPUs, the CPU cost may not be linearly
15034         //    affected by additional threads.
15035 
15036         SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes =
15037                     mSystemServerCpuThreadReader.readDelta();
15038         if (systemServiceCpuThreadTimes == null) {
15039             return;
15040         }
15041 
15042         if (mBinderThreadCpuTimesUs == null) {
15043             mBinderThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
15044         }
15045         mBinderThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
15046 
15047         if (DEBUG_BINDER_STATS) {
15048             Slog.d(TAG, "System server threads per CPU cluster (incoming binder threads)");
15049             long binderThreadTimeMs = 0;
15050             int cpuIndex = 0;
15051             final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked(
15052                     BatteryStats.STATS_SINCE_CHARGED);
15053             int index = 0;
15054             int numCpuClusters = mPowerProfile.getNumCpuClusters();
15055             for (int cluster = 0; cluster < numCpuClusters; cluster++) {
15056                 StringBuilder sb = new StringBuilder();
15057                 sb.append("cpu").append(cpuIndex).append(": [");
15058                 int numSpeeds = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
15059                 for (int speed = 0; speed < numSpeeds; speed++) {
15060                     if (speed != 0) {
15061                         sb.append(", ");
15062                     }
15063                     long binderCountMs = binderThreadCpuTimesUs[index] / 1000;
15064                     sb.append(TextUtils.formatSimple("%10d", binderCountMs));
15065 
15066                     binderThreadTimeMs += binderCountMs;
15067                     index++;
15068                 }
15069                 cpuIndex += mPowerProfile.getNumCoresInCpuCluster(cluster);
15070                 Slog.d(TAG, sb.toString());
15071             }
15072         }
15073     }
15074 
15075     /**
15076      * Mark the current partial timers as gone through a collection so that they will be
15077      * considered in the next cpu times distribution to wakelock holders.
15078      */
15079     @VisibleForTesting
15080     public void markPartialTimersAsEligible() {
15081         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
15082             // No difference, so each timer is now considered for the next collection.
15083             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
15084                 mPartialTimers.get(i).mInList = true;
15085             }
15086         } else {
15087             // The lists are different, meaning we added (or removed a timer) since the last
15088             // collection.
15089             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
15090                 mLastPartialTimers.get(i).mInList = false;
15091             }
15092             mLastPartialTimers.clear();
15093 
15094             // Mark the current timers as gone through a collection.
15095             final int numPartialTimers = mPartialTimers.size();
15096             for (int i = 0; i < numPartialTimers; ++i) {
15097                 final StopwatchTimer timer = mPartialTimers.get(i);
15098                 timer.mInList = true;
15099                 mLastPartialTimers.add(timer);
15100             }
15101         }
15102     }
15103 
15104     /**
15105      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
15106      * calculate cpu times spent by each uid at different frequencies. Will also add estimated
15107      * power consumptions, if powerAccumulator data structure is provided.
15108      *
15109      * @param updatedUids  The uids for which times spent at different frequencies are calculated.
15110      * @param onBattery whether or not this is onBattery
15111      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
15112      */
15113     @VisibleForTesting
15114     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery,
15115             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
15116         long totalCpuClustersTimeMs = 0;
15117         // Read the time spent for each cluster at various cpu frequencies.
15118         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
15119         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
15120             clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
15121             if (clusterSpeedTimesMs[cluster] != null) {
15122                 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
15123                     totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
15124                 }
15125             }
15126         }
15127         if (totalCpuClustersTimeMs != 0) {
15128             // We have cpu times per freq aggregated over all uids but we need the times per uid.
15129             // So, we distribute total time spent by an uid to different cpu freqs based on the
15130             // amount of time cpu was running at that freq.
15131             final int updatedUidsCount = updatedUids.size();
15132             final long elapsedRealtimeMs = mClock.elapsedRealtime();
15133             final long uptimeMs = mClock.uptimeMillis();
15134             for (int i = 0; i < updatedUidsCount; ++i) {
15135                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i), elapsedRealtimeMs, uptimeMs);
15136                 final long appCpuTimeUs = updatedUids.valueAt(i);
15137                 // Add the cpu speeds to this UID.
15138                 final int numClusters = mPowerProfile.getNumCpuClusters();
15139                 if (u.mCpuClusterSpeedTimesUs == null ||
15140                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
15141                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
15142                 }
15143 
15144                 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
15145                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
15146                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
15147                             u.mCpuClusterSpeedTimesUs[cluster].length) {
15148                         u.mCpuClusterSpeedTimesUs[cluster]
15149                                 = new LongSamplingCounter[speedsInCluster];
15150                     }
15151 
15152                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
15153                     for (int speed = 0; speed < speedsInCluster; speed++) {
15154                         if (cpuSpeeds[speed] == null) {
15155                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
15156                         }
15157                         final long deltaSpeedCount = appCpuTimeUs
15158                                 * clusterSpeedTimesMs[cluster][speed]
15159                                 / totalCpuClustersTimeMs;
15160                         cpuSpeeds[speed].addCountLocked(deltaSpeedCount, onBattery);
15161 
15162                         if (powerAccumulator != null) {
15163                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
15164                                     speed, deltaSpeedCount);
15165                         }
15166                     }
15167                 }
15168             }
15169         }
15170     }
15171 
15172     /**
15173      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
15174      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
15175      * wakelock holders.
15176      *
15177      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
15178      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
15179      */
15180     @VisibleForTesting
15181     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
15182             @Nullable SparseLongArray updatedUids, boolean onBattery) {
15183         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
15184         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
15185         final long startTimeMs = mClock.uptimeMillis();
15186         final long elapsedRealtimeMs = mClock.elapsedRealtime();
15187 
15188         mCpuUidUserSysTimeReader.readDelta(false, (uid, timesUs) -> {
15189             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
15190 
15191             uid = mapUid(uid);
15192             if (Process.isIsolated(uid)) {
15193                 // This could happen if the isolated uid mapping was removed before that process
15194                 // was actually killed.
15195                 if (DEBUG) Slog.d(TAG, "Got readings for an isolated uid: " + uid);
15196                 return;
15197             }
15198             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
15199                 if (DEBUG) Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
15200                 return;
15201             }
15202             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
15203 
15204             // Accumulate the total system and user time.
15205             mTempTotalCpuUserTimeUs += userTimeUs;
15206             mTempTotalCpuSystemTimeUs += systemTimeUs;
15207 
15208             StringBuilder sb = null;
15209             if (DEBUG_ENERGY_CPU) {
15210                 sb = new StringBuilder();
15211                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
15212                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
15213                 sb.append(" s=");
15214                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
15215                 sb.append("\n");
15216             }
15217 
15218             if (numWakelocks > 0) {
15219                 // We have wakelocks being held, so only give a portion of the
15220                 // time to the process. The rest will be distributed among wakelock
15221                 // holders.
15222                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
15223                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
15224             }
15225 
15226             if (sb != null) {
15227                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
15228                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
15229                 sb.append(" s=");
15230                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
15231                 Slog.d(TAG, sb.toString());
15232             }
15233 
15234             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
15235             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
15236             if (updatedUids != null) {
15237                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
15238             }
15239         });
15240 
15241         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
15242         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
15243             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
15244         }
15245 
15246         if (numWakelocks > 0) {
15247             // Distribute a portion of the total cpu time to wakelock holders.
15248             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
15249             mTempTotalCpuSystemTimeUs =
15250                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
15251 
15252             for (int i = 0; i < numWakelocks; ++i) {
15253                 final StopwatchTimer timer = partialTimers.get(i);
15254                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
15255                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
15256 
15257                 if (DEBUG_ENERGY_CPU) {
15258                     final StringBuilder sb = new StringBuilder();
15259                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
15260                             .append(": u=");
15261                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
15262                     sb.append(" s=");
15263                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
15264                     Slog.d(TAG, sb.toString());
15265                 }
15266 
15267                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
15268                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
15269                 if (updatedUids != null) {
15270                     final int uid = timer.mUid.getUid();
15271                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
15272                 }
15273 
15274                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
15275                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
15276 
15277                 mTempTotalCpuUserTimeUs -= userTimeUs;
15278                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
15279             }
15280         }
15281     }
15282 
15283     /**
15284      * Take a snapshot of the cpu times spent by each uid in each freq and update the
15285      * corresponding counters.  Will also add estimated power consumptions, if powerAccumulator
15286      * data structure is provided.
15287      *
15288      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
15289      * @param onBattery whether or not this is onBattery
15290      * @param onBatteryScreenOff whether or not this is onBattery with the screen off.
15291      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
15292      */
15293     @VisibleForTesting
15294     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
15295             boolean onBattery, boolean onBatteryScreenOff,
15296             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
15297         final boolean perClusterTimesAvailable =
15298                 mCpuUidFreqTimeReader.perClusterTimesAvailable();
15299         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
15300         final int numClusters = mPowerProfile.getNumCpuClusters();
15301         mWakeLockAllocationsUs = null;
15302         final long startTimeMs = mClock.uptimeMillis();
15303         final long elapsedRealtimeMs = mClock.elapsedRealtime();
15304         // If power is being accumulated for attribution, data needs to be read immediately.
15305         final boolean forceRead = powerAccumulator != null;
15306         mCpuUidFreqTimeReader.readDelta(forceRead, (uid, cpuFreqTimeMs) -> {
15307             uid = mapUid(uid);
15308             if (Process.isIsolated(uid)) {
15309                 if (DEBUG) Slog.d(TAG, "Got freq readings for an isolated uid: " + uid);
15310                 return;
15311             }
15312             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
15313                 if (DEBUG) Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
15314                 return;
15315             }
15316             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
15317             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
15318                 detachIfNotNull(u.mCpuFreqTimeMs);
15319                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
15320             }
15321             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
15322             if (u.mScreenOffCpuFreqTimeMs == null ||
15323                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
15324                 detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
15325                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
15326                         mOnBatteryScreenOffTimeBase);
15327             }
15328             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
15329 
15330             if (perClusterTimesAvailable) {
15331                 if (u.mCpuClusterSpeedTimesUs == null ||
15332                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
15333                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
15334                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
15335                 }
15336                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
15337                     mWakeLockAllocationsUs = new long[numClusters][];
15338                 }
15339 
15340                 int freqIndex = 0;
15341                 for (int cluster = 0; cluster < numClusters; ++cluster) {
15342                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
15343                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
15344                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
15345                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
15346                         u.mCpuClusterSpeedTimesUs[cluster]
15347                                 = new LongSamplingCounter[speedsInCluster];
15348                     }
15349                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
15350                         mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
15351                     }
15352                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
15353                     for (int speed = 0; speed < speedsInCluster; ++speed) {
15354                         if (cpuTimesUs[speed] == null) {
15355                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
15356                         }
15357                         final long appAllocationUs;
15358                         if (mWakeLockAllocationsUs != null) {
15359                             appAllocationUs =
15360                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
15361                             mWakeLockAllocationsUs[cluster][speed] +=
15362                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
15363                         } else {
15364                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
15365                         }
15366                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
15367 
15368                         if (powerAccumulator != null) {
15369                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
15370                                     speed, appAllocationUs / 1000);
15371                         }
15372                         freqIndex++;
15373                     }
15374                 }
15375             }
15376         });
15377 
15378         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
15379         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
15380             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
15381         }
15382 
15383         if (mWakeLockAllocationsUs != null) {
15384             for (int i = 0; i < numWakelocks; ++i) {
15385                 final Uid u = partialTimers.get(i).mUid;
15386                 if (u.mCpuClusterSpeedTimesUs == null ||
15387                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
15388                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
15389                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
15390                 }
15391 
15392                 for (int cluster = 0; cluster < numClusters; ++cluster) {
15393                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
15394                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
15395                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
15396                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
15397                         u.mCpuClusterSpeedTimesUs[cluster]
15398                                 = new LongSamplingCounter[speedsInCluster];
15399                     }
15400                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
15401                     for (int speed = 0; speed < speedsInCluster; ++speed) {
15402                         if (cpuTimeUs[speed] == null) {
15403                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
15404                         }
15405                         final long allocationUs =
15406                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
15407                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
15408                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
15409 
15410                         if (powerAccumulator != null) {
15411                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
15412                                     speed, allocationUs / 1000);
15413                         }
15414                     }
15415                 }
15416             }
15417         }
15418     }
15419 
15420     /**
15421      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
15422      * counters.
15423      */
15424     @VisibleForTesting
15425     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
15426         final long startTimeMs = mClock.uptimeMillis();
15427         final long elapsedRealtimeMs = mClock.elapsedRealtime();
15428         mCpuUidActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
15429             final int parentUid = mapUid(uid);
15430             if (Process.isIsolated(parentUid)) {
15431                 if (DEBUG) Slog.w(TAG, "Got active times for an isolated uid: " + uid);
15432                 return;
15433             }
15434             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
15435                 if (DEBUG) Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
15436                 return;
15437             }
15438             final Uid u = getUidStatsLocked(parentUid, elapsedRealtimeMs, startTimeMs);
15439             if (parentUid == uid) {
15440                 u.getCpuActiveTimeCounter().update(cpuActiveTimesMs, elapsedRealtimeMs);
15441             } else {
15442                 final SparseArray<Uid.ChildUid> childUids = u.mChildUids;
15443                 if (childUids == null) {
15444                     return;
15445                 }
15446 
15447                 Uid.ChildUid childUid = childUids.get(uid);
15448                 if (childUid != null) {
15449                     final long delta =
15450                             childUid.cpuActiveCounter.update(cpuActiveTimesMs, elapsedRealtimeMs);
15451                     u.getCpuActiveTimeCounter().increment(delta, elapsedRealtimeMs);
15452                 }
15453             }
15454         });
15455 
15456         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
15457         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
15458             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
15459         }
15460     }
15461 
15462     /**
15463      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
15464      * counters. Will also add estimated power consumptions, if powerAccumulator data structure
15465      * is provided.
15466      *
15467      * @param onBattery whether or not this is onBattery
15468      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
15469      */
15470     @VisibleForTesting
15471     public void readKernelUidCpuClusterTimesLocked(boolean onBattery,
15472             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
15473         final long startTimeMs = mClock.uptimeMillis();
15474         final long elapsedRealtimeMs = mClock.elapsedRealtime();
15475         // If power is being accumulated for attribution, data needs to be read immediately.
15476         final boolean forceRead = powerAccumulator != null;
15477         mCpuUidClusterTimeReader.readDelta(forceRead, (uid, cpuClusterTimesMs) -> {
15478             uid = mapUid(uid);
15479             if (Process.isIsolated(uid)) {
15480                 if (DEBUG) Slog.w(TAG, "Got cluster times for an isolated uid: " + uid);
15481                 return;
15482             }
15483             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
15484                 if (DEBUG) Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
15485                 return;
15486             }
15487             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
15488             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
15489 
15490             if (powerAccumulator != null) {
15491                 powerAccumulator.addCpuClusterDurationsMs(u, cpuClusterTimesMs);
15492             }
15493         });
15494 
15495         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
15496         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
15497             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
15498         }
15499     }
15500 
15501     boolean setChargingLocked(boolean charging) {
15502         // if the device is no longer charging, remove the callback
15503         // if the device is now charging, it means that this is either called
15504         // 1. directly when level >= 90
15505         // 2. or from within the runnable that we deferred
15506         // For 1. if we have an existing callback, remove it, since we will immediately send a
15507         // ACTION_CHARGING
15508         // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
15509         mHandler.removeCallbacks(mDeferSetCharging);
15510         if (mCharging != charging) {
15511             mCharging = charging;
15512             if (charging) {
15513                 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
15514             } else {
15515                 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
15516             }
15517             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
15518             return true;
15519         }
15520         return false;
15521     }
15522 
15523     /**
15524      * Notifies BatteryStatsImpl that the system server is ready.
15525      */
15526     public void onSystemReady() {
15527         mSystemReady = true;
15528     }
15529 
15530     @GuardedBy("this")
15531     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
15532             final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
15533         boolean doWrite = false;
15534         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
15535         m.arg1 = onBattery ? 1 : 0;
15536         mHandler.sendMessage(m);
15537 
15538         final long uptimeUs = mSecUptime * 1000;
15539         final long realtimeUs = mSecRealtime * 1000;
15540         final int screenState = mScreenState;
15541         if (onBattery) {
15542             // We will reset our status if we are unplugging after the
15543             // battery was last full, or the level is at 100, or
15544             // we have gone through a significant charge (from a very low
15545             // level to a now very high level).
15546             // Also, we will reset the stats if battery got partially charged
15547             // and discharged repeatedly without ever reaching the full charge.
15548             // This reset is done in order to prevent stats sessions from going on forever.
15549             // Exceedingly long battery sessions would lead to an overflow of
15550             // data structures such as mWakeupReasonStats.
15551             boolean reset = false;
15552             if (!mNoAutoReset && mSystemReady
15553                     && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
15554                     || level >= 90
15555                     || (mDischargeCurrentLevel < 20 && level >= 80)
15556                     || getHighDischargeAmountSinceCharge() >= 200)) {
15557                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
15558                         + " dischargeLevel=" + mDischargeCurrentLevel
15559                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
15560                         + " highAmount=" + getHighDischargeAmountSinceCharge());
15561                 // Before we write, collect a snapshot of the final aggregated
15562                 // stats to be reported in the next checkin.  Only do this if we have
15563                 // a sufficient amount of data to make it interesting.
15564                 if (getLowDischargeAmountSinceCharge() >= 20) {
15565                     final long startTimeMs = SystemClock.uptimeMillis();
15566                     final Parcel parcel = Parcel.obtain();
15567                     writeSummaryToParcel(parcel, true);
15568                     final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
15569                     BackgroundThread.getHandler().post(new Runnable() {
15570                         @Override public void run() {
15571                             synchronized (mCheckinFile) {
15572                                 final long startTimeMs2 = SystemClock.uptimeMillis();
15573                                 FileOutputStream stream = null;
15574                                 try {
15575                                     stream = mCheckinFile.startWrite();
15576                                     stream.write(parcel.marshall());
15577                                     stream.flush();
15578                                     mCheckinFile.finishWrite(stream);
15579                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
15580                                             "batterystats-checkin", initialTimeMs
15581                                             + SystemClock.uptimeMillis() - startTimeMs2);
15582                                 } catch (IOException e) {
15583                                     Slog.w("BatteryStats",
15584                                             "Error writing checkin battery statistics", e);
15585                                     mCheckinFile.failWrite(stream);
15586                                 } finally {
15587                                     parcel.recycle();
15588                                 }
15589                             }
15590                         }
15591                     });
15592                 }
15593                 doWrite = true;
15594                 resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_FULL_CHARGE);
15595                 if (chargeUah > 0 && level > 0) {
15596                     // Only use the reported coulomb charge value if it is supported and reported.
15597                     mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
15598                 }
15599                 mDischargeStartLevel = level;
15600                 reset = true;
15601                 mDischargeStepTracker.init();
15602             }
15603             if (mCharging) {
15604                 setChargingLocked(false);
15605             }
15606             mLastChargingStateLevel = level;
15607             mOnBattery = mOnBatteryInternal = true;
15608             mLastDischargeStepLevel = level;
15609             mMinDischargeStepLevel = level;
15610             mDischargeStepTracker.clearTime();
15611             mDailyDischargeStepTracker.clearTime();
15612             mInitStepMode = mCurStepMode;
15613             mModStepMode = 0;
15614             pullPendingStateUpdatesLocked();
15615             mHistoryCur.batteryLevel = (byte)level;
15616             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
15617             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
15618                     + Integer.toHexString(mHistoryCur.states));
15619             if (reset) {
15620                 mRecordingHistory = true;
15621                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
15622             }
15623             addHistoryRecordLocked(mSecRealtime, mSecUptime);
15624             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
15625             if (Display.isOnState(screenState)) {
15626                 mDischargeScreenOnUnplugLevel = level;
15627                 mDischargeScreenDozeUnplugLevel = 0;
15628                 mDischargeScreenOffUnplugLevel = 0;
15629             } else if (Display.isDozeState(screenState)) {
15630                 mDischargeScreenOnUnplugLevel = 0;
15631                 mDischargeScreenDozeUnplugLevel = level;
15632                 mDischargeScreenOffUnplugLevel = 0;
15633             } else {
15634                 mDischargeScreenOnUnplugLevel = 0;
15635                 mDischargeScreenDozeUnplugLevel = 0;
15636                 mDischargeScreenOffUnplugLevel = level;
15637             }
15638             mDischargeAmountScreenOn = 0;
15639             mDischargeAmountScreenDoze = 0;
15640             mDischargeAmountScreenOff = 0;
15641             updateTimeBasesLocked(true, screenState, uptimeUs, realtimeUs);
15642         } else {
15643             mLastChargingStateLevel = level;
15644             mOnBattery = mOnBatteryInternal = false;
15645             pullPendingStateUpdatesLocked();
15646             mHistoryCur.batteryLevel = (byte)level;
15647             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
15648             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
15649                     + Integer.toHexString(mHistoryCur.states));
15650             addHistoryRecordLocked(mSecRealtime, mSecUptime);
15651             mDischargeCurrentLevel = mDischargePlugLevel = level;
15652             if (level < mDischargeUnplugLevel) {
15653                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
15654                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
15655             }
15656             updateDischargeScreenLevelsLocked(screenState, screenState);
15657             updateTimeBasesLocked(false, screenState, uptimeUs, realtimeUs);
15658             mChargeStepTracker.init();
15659             mLastChargeStepLevel = level;
15660             mMaxChargeStepLevel = level;
15661             mInitStepMode = mCurStepMode;
15662             mModStepMode = 0;
15663         }
15664         if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
15665             if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
15666                 writeAsyncLocked();
15667             }
15668         }
15669     }
15670 
15671     @GuardedBy("this")
15672     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
15673             boolean reset) {
15674         mRecordingHistory = true;
15675         mHistoryCur.currentTime = mClock.currentTimeMillis();
15676         addHistoryBufferLocked(elapsedRealtimeMs,
15677                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
15678                 mHistoryCur);
15679         mHistoryCur.currentTime = 0;
15680         if (reset) {
15681             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
15682         }
15683     }
15684 
15685     @GuardedBy("this")
15686     private void recordCurrentTimeChangeLocked(final long currentTimeMs,
15687             final long elapsedRealtimeMs, final long uptimeMs) {
15688         if (mRecordingHistory) {
15689             mHistoryCur.currentTime = currentTimeMs;
15690             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
15691             mHistoryCur.currentTime = 0;
15692         }
15693     }
15694 
15695     @GuardedBy("this")
15696     private void recordShutdownLocked(final long currentTimeMs, final long elapsedRealtimeMs) {
15697         if (mRecordingHistory) {
15698             mHistoryCur.currentTime = currentTimeMs;
15699             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
15700             mHistoryCur.currentTime = 0;
15701         }
15702     }
15703 
15704     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
15705         if (mExternalSync != null) {
15706             mExternalSync.scheduleSync(reason, updateFlags);
15707         }
15708     }
15709 
15710     // This should probably be exposed in the API, though it's not critical
15711     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
15712 
15713     @GuardedBy("this")
15714     public void setBatteryStateLocked(final int status, final int health, final int plugType,
15715             final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
15716             final int chargeFullUah, final long chargeTimeToFullSeconds) {
15717         setBatteryStateLocked(status, health, plugType, level, temp, voltageMv, chargeUah,
15718                 chargeFullUah, chargeTimeToFullSeconds,
15719                 mClock.elapsedRealtime(), mClock.uptimeMillis(), mClock.currentTimeMillis());
15720     }
15721 
15722     @GuardedBy("this")
15723     public void setBatteryStateLocked(final int status, final int health, final int plugType,
15724             final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
15725             final int chargeFullUah, final long chargeTimeToFullSeconds,
15726             final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) {
15727         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
15728         temp = Math.max(0, temp);
15729 
15730         reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
15731                 status, plugType, level);
15732 
15733         final boolean onBattery = isOnBattery(plugType, status);
15734         if (!mHaveBatteryLevel) {
15735             mHaveBatteryLevel = true;
15736             // We start out assuming that the device is plugged in (not
15737             // on battery).  If our first report is now that we are indeed
15738             // plugged in, then twiddle our state to correctly reflect that
15739             // since we won't be going through the full setOnBattery().
15740             if (onBattery == mOnBattery) {
15741                 if (onBattery) {
15742                     mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
15743                 } else {
15744                     mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
15745                 }
15746             }
15747             // Always start out assuming charging, that will be updated later.
15748             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
15749             mHistoryCur.batteryStatus = (byte)status;
15750             mHistoryCur.batteryLevel = (byte)level;
15751             mHistoryCur.batteryChargeUah = chargeUah;
15752             mMaxChargeStepLevel = mMinDischargeStepLevel =
15753                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
15754             mLastChargingStateLevel = level;
15755         } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
15756             recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
15757         }
15758         int oldStatus = mHistoryCur.batteryStatus;
15759         if (onBattery) {
15760             mDischargeCurrentLevel = level;
15761             if (!mRecordingHistory) {
15762                 mRecordingHistory = true;
15763                 startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
15764             }
15765         } else if (level < 96 &&
15766                 status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
15767             if (!mRecordingHistory) {
15768                 mRecordingHistory = true;
15769                 startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
15770             }
15771         }
15772         mBatteryVoltageMv = voltageMv;
15773         mCurrentBatteryLevel = level;
15774         if (mDischargePlugLevel < 0) {
15775             mDischargePlugLevel = level;
15776         }
15777 
15778         if (onBattery != mOnBattery) {
15779             mHistoryCur.batteryLevel = (byte)level;
15780             mHistoryCur.batteryStatus = (byte)status;
15781             mHistoryCur.batteryHealth = (byte)health;
15782             mHistoryCur.batteryPlugType = (byte)plugType;
15783             mHistoryCur.batteryTemperature = (short)temp;
15784             mHistoryCur.batteryVoltage = (char) voltageMv;
15785             if (chargeUah < mHistoryCur.batteryChargeUah) {
15786                 // Only record discharges
15787                 final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
15788                 mDischargeCounter.addCountLocked(chargeDiff);
15789                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
15790                 if (Display.isDozeState(mScreenState)) {
15791                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
15792                 }
15793                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
15794                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
15795                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
15796                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
15797                 }
15798             }
15799             mHistoryCur.batteryChargeUah = chargeUah;
15800             setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
15801         } else {
15802             boolean changed = false;
15803             if (mHistoryCur.batteryLevel != level) {
15804                 mHistoryCur.batteryLevel = (byte)level;
15805                 changed = true;
15806 
15807                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
15808                 // which will pull external stats.
15809                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
15810                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
15811             }
15812             if (mHistoryCur.batteryStatus != status) {
15813                 mHistoryCur.batteryStatus = (byte)status;
15814                 changed = true;
15815             }
15816             if (mHistoryCur.batteryHealth != health) {
15817                 mHistoryCur.batteryHealth = (byte)health;
15818                 changed = true;
15819             }
15820             if (mHistoryCur.batteryPlugType != plugType) {
15821                 mHistoryCur.batteryPlugType = (byte)plugType;
15822                 changed = true;
15823             }
15824             if (temp >= (mHistoryCur.batteryTemperature+10)
15825                     || temp <= (mHistoryCur.batteryTemperature-10)) {
15826                 mHistoryCur.batteryTemperature = (short)temp;
15827                 changed = true;
15828             }
15829             if (voltageMv > (mHistoryCur.batteryVoltage + 20)
15830                     || voltageMv < (mHistoryCur.batteryVoltage - 20)) {
15831                 mHistoryCur.batteryVoltage = (char) voltageMv;
15832                 changed = true;
15833             }
15834             if (chargeUah >= (mHistoryCur.batteryChargeUah + 10)
15835                     || chargeUah <= (mHistoryCur.batteryChargeUah - 10)) {
15836                 if (chargeUah < mHistoryCur.batteryChargeUah) {
15837                     // Only record discharges
15838                     final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
15839                     mDischargeCounter.addCountLocked(chargeDiff);
15840                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
15841                     if (Display.isDozeState(mScreenState)) {
15842                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
15843                     }
15844                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
15845                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
15846                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
15847                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
15848                     }
15849                 }
15850                 mHistoryCur.batteryChargeUah = chargeUah;
15851                 changed = true;
15852             }
15853             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
15854                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
15855                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
15856             if (onBattery) {
15857                 changed |= setChargingLocked(false);
15858                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
15859                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
15860                             modeBits, elapsedRealtimeMs);
15861                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
15862                             modeBits, elapsedRealtimeMs);
15863                     mLastDischargeStepLevel = level;
15864                     mMinDischargeStepLevel = level;
15865                     mInitStepMode = mCurStepMode;
15866                     mModStepMode = 0;
15867                 }
15868             } else {
15869                 if (level >= 90) {
15870                     // If the battery level is at least 90%, always consider the device to be
15871                     // charging even if it happens to go down a level.
15872                     changed |= setChargingLocked(true);
15873                 } else if (!mCharging) {
15874                     if (mLastChargeStepLevel < level) {
15875                         // We have not reported that we are charging, but the level has gone up,
15876                         // but we would like to not have tons of activity from charging-constraint
15877                         // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
15878                         if (!mHandler.hasCallbacks(mDeferSetCharging)) {
15879                             mHandler.postDelayed(
15880                                     mDeferSetCharging,
15881                                     mConstants.BATTERY_CHARGED_DELAY_MS);
15882                         }
15883                     } else if (mLastChargeStepLevel > level) {
15884                         // if we had deferred a runnable due to charge level increasing, but then
15885                         // later the charge level drops (could be due to thermal issues), we don't
15886                         // want to trigger the deferred runnable, so remove it here
15887                         mHandler.removeCallbacks(mDeferSetCharging);
15888                     }
15889                 } else {
15890                     if (mLastChargeStepLevel > level) {
15891                         // We had reported that the device was charging, but here we are with
15892                         // power connected and the level going down.  Looks like the current
15893                         // power supplied isn't enough, so consider the device to now be
15894                         // discharging.
15895                         changed |= setChargingLocked(false);
15896                     }
15897                 }
15898                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
15899                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
15900                             modeBits, elapsedRealtimeMs);
15901                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
15902                             modeBits, elapsedRealtimeMs);
15903                     mMaxChargeStepLevel = level;
15904                     mInitStepMode = mCurStepMode;
15905                     mModStepMode = 0;
15906                 }
15907                 mLastChargeStepLevel = level;
15908             }
15909             if (changed) {
15910                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
15911             }
15912         }
15913         if (!onBattery &&
15914                 (status == BatteryManager.BATTERY_STATUS_FULL ||
15915                         status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
15916             // We don't record history while we are plugged in and fully charged
15917             // (or when battery is not present).  The next time we are
15918             // unplugged, history will be cleared.
15919             mRecordingHistory = DEBUG;
15920         }
15921 
15922         mLastLearnedBatteryCapacityUah = chargeFullUah;
15923         if (mMinLearnedBatteryCapacityUah == -1) {
15924             mMinLearnedBatteryCapacityUah = chargeFullUah;
15925         } else {
15926             mMinLearnedBatteryCapacityUah = Math.min(mMinLearnedBatteryCapacityUah, chargeFullUah);
15927         }
15928         mMaxLearnedBatteryCapacityUah = Math.max(mMaxLearnedBatteryCapacityUah, chargeFullUah);
15929 
15930         mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
15931     }
15932 
15933     public static boolean isOnBattery(int plugType, int status) {
15934         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
15935     }
15936 
15937     // Inform StatsLog of setBatteryState changes.
15938     // If this is the first reporting, pass in recentPast == null.
15939     private void reportChangesToStatsLog(HistoryItem recentPast,
15940             final int status, final int plugType, final int level) {
15941 
15942         if (recentPast == null || recentPast.batteryStatus != status) {
15943             FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
15944         }
15945         if (recentPast == null || recentPast.batteryPlugType != plugType) {
15946             FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
15947         }
15948         if (recentPast == null || recentPast.batteryLevel != level) {
15949             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
15950         }
15951     }
15952 
15953     @UnsupportedAppUsage
15954     public long getAwakeTimeBattery() {
15955         // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
15956         // for over a decade, but surely that was a mistake.
15957         return getBatteryUptimeLocked(mClock.uptimeMillis());
15958     }
15959 
15960     @UnsupportedAppUsage
15961     public long getAwakeTimePlugged() {
15962         return (mClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
15963     }
15964 
15965     @Override
15966     public long computeUptime(long curTimeUs, int which) {
15967         return mUptimeUs + (curTimeUs - mUptimeStartUs);
15968     }
15969 
15970     @Override
15971     public long computeRealtime(long curTimeUs, int which) {
15972         return mRealtimeUs + (curTimeUs - mRealtimeStartUs);
15973     }
15974 
15975     @Override
15976     @UnsupportedAppUsage
15977     public long computeBatteryUptime(long curTimeUs, int which) {
15978         return mOnBatteryTimeBase.computeUptime(curTimeUs, which);
15979     }
15980 
15981     @Override
15982     @UnsupportedAppUsage
15983     public long computeBatteryRealtime(long curTimeUs, int which) {
15984         return mOnBatteryTimeBase.computeRealtime(curTimeUs, which);
15985     }
15986 
15987     @Override
15988     public long computeBatteryScreenOffUptime(long curTimeUs, int which) {
15989         return mOnBatteryScreenOffTimeBase.computeUptime(curTimeUs, which);
15990     }
15991 
15992     @Override
15993     public long computeBatteryScreenOffRealtime(long curTimeUs, int which) {
15994         return mOnBatteryScreenOffTimeBase.computeRealtime(curTimeUs, which);
15995     }
15996 
15997     private long computeTimePerLevel(long[] steps, int numSteps) {
15998         // For now we'll do a simple average across all steps.
15999         if (numSteps <= 0) {
16000             return -1;
16001         }
16002         long total = 0;
16003         for (int i=0; i<numSteps; i++) {
16004             total += steps[i] & STEP_LEVEL_TIME_MASK;
16005         }
16006         return total / numSteps;
16007         /*
16008         long[] buckets = new long[numSteps];
16009         int numBuckets = 0;
16010         int numToAverage = 4;
16011         int i = 0;
16012         while (i < numSteps) {
16013             long totalTime = 0;
16014             int num = 0;
16015             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
16016                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
16017                 num++;
16018             }
16019             buckets[numBuckets] = totalTime / num;
16020             numBuckets++;
16021             numToAverage *= 2;
16022             i += num;
16023         }
16024         if (numBuckets < 1) {
16025             return -1;
16026         }
16027         long averageTime = buckets[numBuckets-1];
16028         for (i=numBuckets-2; i>=0; i--) {
16029             averageTime = (averageTime + buckets[i]) / 2;
16030         }
16031         return averageTime;
16032         */
16033     }
16034 
16035     @Override
16036     @UnsupportedAppUsage
16037     public long computeBatteryTimeRemaining(long curTime) {
16038         if (!mOnBattery) {
16039             return -1;
16040         }
16041         /* Simple implementation just looks at the average discharge per level across the
16042            entire sample period.
16043         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
16044         if (discharge < 2) {
16045             return -1;
16046         }
16047         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
16048         if (duration < 1000*1000) {
16049             return -1;
16050         }
16051         long usPerLevel = duration/discharge;
16052         return usPerLevel * mCurrentBatteryLevel;
16053         */
16054         if (mDischargeStepTracker.mNumStepDurations < 1) {
16055             return -1;
16056         }
16057         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
16058         if (msPerLevel <= 0) {
16059             return -1;
16060         }
16061         return (msPerLevel * mCurrentBatteryLevel) * 1000;
16062     }
16063 
16064     @Override
16065     public LevelStepTracker getDischargeLevelStepTracker() {
16066         return mDischargeStepTracker;
16067     }
16068 
16069     @Override
16070     public LevelStepTracker getDailyDischargeLevelStepTracker() {
16071         return mDailyDischargeStepTracker;
16072     }
16073 
16074     @Override
16075     public long computeChargeTimeRemaining(long curTime) {
16076         if (mOnBattery) {
16077             // Not yet working.
16078             return -1;
16079         }
16080         if (mBatteryTimeToFullSeconds >= 0) {
16081             return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us
16082         }
16083         // Else use algorithmic approach
16084         if (mChargeStepTracker.mNumStepDurations < 1) {
16085             return -1;
16086         }
16087         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
16088         if (msPerLevel <= 0) {
16089             return -1;
16090         }
16091         return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;
16092     }
16093 
16094     /*@hide */
16095     public CellularBatteryStats getCellularBatteryStats() {
16096         final int which = STATS_SINCE_CHARGED;
16097         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
16098         final ControllerActivityCounter counter = getModemControllerActivity();
16099         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
16100         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
16101         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
16102         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
16103         final long monitoredRailChargeConsumedMaMs =
16104                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
16105         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
16106         for (int i = 0; i < timeInRatMs.length; i++) {
16107             timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTimeUs, which) / 1000;
16108         }
16109         long[] timeInRxSignalStrengthLevelMs =
16110                 new long[CellSignalStrength.getNumSignalStrengthLevels()];
16111         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
16112             timeInRxSignalStrengthLevelMs[i] =
16113                 getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
16114         }
16115         long[] txTimeMs = new long[Math.min(ModemActivityInfo.getNumTxPowerLevels(),
16116             counter.getTxTimeCounters().length)];
16117         long totalTxTimeMs = 0;
16118         for (int i = 0; i < txTimeMs.length; i++) {
16119             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
16120             totalTxTimeMs += txTimeMs[i];
16121         }
16122 
16123         return new CellularBatteryStats(computeBatteryRealtime(rawRealTimeUs, which) / 1000,
16124                 getMobileRadioActiveTime(rawRealTimeUs, which) / 1000,
16125                 getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which),
16126                 getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which),
16127                 getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which),
16128                 getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which),
16129                 sleepTimeMs, idleTimeMs, rxTimeMs, energyConsumedMaMs, timeInRatMs,
16130                 timeInRxSignalStrengthLevelMs, txTimeMs,
16131                 monitoredRailChargeConsumedMaMs);
16132     }
16133 
16134     /*@hide */
16135     public WifiBatteryStats getWifiBatteryStats() {
16136         final int which = STATS_SINCE_CHARGED;
16137         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
16138         final ControllerActivityCounter counter = getWifiControllerActivity();
16139         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
16140         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
16141         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
16142         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
16143         final long totalControllerActivityTimeMs
16144                 = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
16145         final long sleepTimeMs
16146                 = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
16147         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
16148         final long monitoredRailChargeConsumedMaMs =
16149                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
16150         long numAppScanRequest = 0;
16151         for (int i = 0; i < mUidStats.size(); i++) {
16152             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
16153         }
16154         long[] timeInStateMs = new long[NUM_WIFI_STATES];
16155         for (int i=0; i<NUM_WIFI_STATES; i++) {
16156             timeInStateMs[i] = getWifiStateTime(i, rawRealTimeUs, which) / 1000;
16157         }
16158         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
16159         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
16160             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTimeUs, which) / 1000;
16161         }
16162         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
16163         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16164             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
16165         }
16166         return new WifiBatteryStats(
16167                 computeBatteryRealtime(rawRealTimeUs, which) / 1000,
16168                 getWifiActiveTime(rawRealTimeUs, which) / 1000,
16169                 getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which),
16170                 getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which),
16171                 getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which),
16172                 getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which),
16173                 sleepTimeMs, scanTimeMs, idleTimeMs, rxTimeMs, txTimeMs, energyConsumedMaMs,
16174                 numAppScanRequest, timeInStateMs, timeSignalStrengthTimeMs, timeInSupplStateMs,
16175                 monitoredRailChargeConsumedMaMs);
16176     }
16177 
16178     /*@hide */
16179     public GpsBatteryStats getGpsBatteryStats() {
16180         GpsBatteryStats s = new GpsBatteryStats();
16181         final int which = STATS_SINCE_CHARGED;
16182         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
16183         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000);
16184         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
16185         long[] time = new long[mGpsSignalQualityTimer.length];
16186         for (int i=0; i<time.length; i++) {
16187             time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000;
16188         }
16189         s.setTimeInGpsSignalQualityLevel(time);
16190         return s;
16191     }
16192 
16193     @Override
16194     public LevelStepTracker getChargeLevelStepTracker() {
16195         return mChargeStepTracker;
16196     }
16197 
16198     @Override
16199     public LevelStepTracker getDailyChargeLevelStepTracker() {
16200         return mDailyChargeStepTracker;
16201     }
16202 
16203     @Override
16204     public ArrayList<PackageChange> getDailyPackageChanges() {
16205         return mDailyPackageChanges;
16206     }
16207 
16208     /**
16209      * @return battery uptime in microseconds
16210      */
16211     protected long getBatteryUptimeLocked() {
16212         return getBatteryUptimeLocked(mClock.uptimeMillis());
16213     }
16214 
16215     /**
16216      * @return battery uptime in microseconds
16217      */
16218     protected long getBatteryUptimeLocked(long uptimeMs) {
16219         return mOnBatteryTimeBase.getUptime(uptimeMs * 1000);
16220     }
16221 
16222     @Override
16223     public long getBatteryUptime(long curTimeUs) {
16224         return mOnBatteryTimeBase.getUptime(curTimeUs);
16225     }
16226 
16227     @Override
16228     @UnsupportedAppUsage
16229     public long getBatteryRealtime(long curTimeUs) {
16230         return mOnBatteryTimeBase.getRealtime(curTimeUs);
16231     }
16232 
16233     @Override
16234     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
16235     public int getDischargeStartLevel() {
16236         synchronized(this) {
16237             return getDischargeStartLevelLocked();
16238         }
16239     }
16240 
16241     public int getDischargeStartLevelLocked() {
16242             return mDischargeUnplugLevel;
16243     }
16244 
16245     @Override
16246     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
16247     public int getDischargeCurrentLevel() {
16248         synchronized(this) {
16249             return getDischargeCurrentLevelLocked();
16250         }
16251     }
16252 
16253     public int getDischargeCurrentLevelLocked() {
16254         return mDischargeCurrentLevel;
16255     }
16256 
16257     @Override
16258     public int getLowDischargeAmountSinceCharge() {
16259         synchronized(this) {
16260             int val = mLowDischargeAmountSinceCharge;
16261             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
16262                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
16263             }
16264             return val;
16265         }
16266     }
16267 
16268     @Override
16269     public int getHighDischargeAmountSinceCharge() {
16270         synchronized(this) {
16271             int val = mHighDischargeAmountSinceCharge;
16272             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
16273                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
16274             }
16275             return val;
16276         }
16277     }
16278 
16279     @Override
16280     @UnsupportedAppUsage
16281     public int getDischargeAmount(int which) {
16282         int dischargeAmount = which == STATS_SINCE_CHARGED
16283                 ? getHighDischargeAmountSinceCharge()
16284                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
16285         if (dischargeAmount < 0) {
16286             dischargeAmount = 0;
16287         }
16288         return dischargeAmount;
16289     }
16290 
16291     @Override
16292     @UnsupportedAppUsage
16293     public int getDischargeAmountScreenOn() {
16294         synchronized(this) {
16295             int val = mDischargeAmountScreenOn;
16296             if (mOnBattery && Display.isOnState(mScreenState)
16297                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
16298                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
16299             }
16300             return val;
16301         }
16302     }
16303 
16304     @Override
16305     public int getDischargeAmountScreenOnSinceCharge() {
16306         synchronized(this) {
16307             int val = mDischargeAmountScreenOnSinceCharge;
16308             if (mOnBattery && Display.isOnState(mScreenState)
16309                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
16310                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
16311             }
16312             return val;
16313         }
16314     }
16315 
16316     @Override
16317     @UnsupportedAppUsage
16318     public int getDischargeAmountScreenOff() {
16319         synchronized(this) {
16320             int val = mDischargeAmountScreenOff;
16321             if (mOnBattery && Display.isOffState(mScreenState)
16322                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
16323                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
16324             }
16325             // For backward compatibility, doze discharge is counted into screen off.
16326             return val + getDischargeAmountScreenDoze();
16327         }
16328     }
16329 
16330     @Override
16331     public int getDischargeAmountScreenOffSinceCharge() {
16332         synchronized(this) {
16333             int val = mDischargeAmountScreenOffSinceCharge;
16334             if (mOnBattery && Display.isOffState(mScreenState)
16335                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
16336                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
16337             }
16338             // For backward compatibility, doze discharge is counted into screen off.
16339             return val + getDischargeAmountScreenDozeSinceCharge();
16340         }
16341     }
16342 
16343     @Override
16344     public int getDischargeAmountScreenDoze() {
16345         synchronized(this) {
16346             int val = mDischargeAmountScreenDoze;
16347             if (mOnBattery && Display.isDozeState(mScreenState)
16348                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
16349                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
16350             }
16351             return val;
16352         }
16353     }
16354 
16355     @Override
16356     public int getDischargeAmountScreenDozeSinceCharge() {
16357         synchronized(this) {
16358             int val = mDischargeAmountScreenDozeSinceCharge;
16359             if (mOnBattery && Display.isDozeState(mScreenState)
16360                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
16361                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
16362             }
16363             return val;
16364         }
16365     }
16366 
16367 
16368     /**
16369      * Estimates the time spent by the system server handling incoming binder requests.
16370      */
16371     @Override
16372     public long[] getSystemServiceTimeAtCpuSpeeds() {
16373         if (mBinderThreadCpuTimesUs == null) {
16374             return null;
16375         }
16376 
16377         return mBinderThreadCpuTimesUs.getCountsLocked(BatteryStats.STATS_SINCE_CHARGED);
16378     }
16379 
16380     /**
16381      * Retrieve the statistics object for a particular uid, creating if needed.
16382      */
16383     @UnsupportedAppUsage
16384     public Uid getUidStatsLocked(int uid) {
16385         return getUidStatsLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
16386     }
16387 
16388     public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
16389         Uid u = mUidStats.get(uid);
16390         if (u == null) {
16391             if (Process.isSdkSandboxUid(uid)) {
16392                 Log.wtf(TAG, "Tracking an SDK Sandbox UID");
16393             }
16394             u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
16395             mUidStats.put(uid, u);
16396         }
16397         return u;
16398     }
16399 
16400     /**
16401      * Retrieve the statistics object for a particular uid. Returns null if the object is not
16402      * available.
16403      */
16404     public Uid getAvailableUidStatsLocked(int uid) {
16405         Uid u = mUidStats.get(uid);
16406         return u;
16407     }
16408 
16409     @GuardedBy("this")
16410     public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) {
16411         final int firstUidForUser = UserHandle.getUid(userId, 0);
16412         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
16413         mPendingRemovedUids.add(
16414                 new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs));
16415     }
16416 
16417     @GuardedBy("this")
16418     public void onUserRemovedLocked(int userId) {
16419         if (mExternalSync != null) {
16420             // Clear out the removed user's UIDs after a short delay. The delay is needed
16421             // because at the point that this method is called, some activities are still
16422             // being wrapped up by those UIDs
16423             mExternalSync.scheduleCleanupDueToRemovedUser(userId);
16424         }
16425     }
16426 
16427     /**
16428      * Removes battery stats for UIDs corresponding to a removed user.
16429      */
16430     @GuardedBy("this")
16431     public void clearRemovedUserUidsLocked(int userId) {
16432         final int firstUidForUser = UserHandle.getUid(userId, 0);
16433         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
16434         mUidStats.put(firstUidForUser, null);
16435         mUidStats.put(lastUidForUser, null);
16436         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
16437         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
16438         for (int i = firstIndex; i <= lastIndex; i++) {
16439             final Uid uid = mUidStats.valueAt(i);
16440             if (uid != null) {
16441                 uid.detachFromTimeBase();
16442             }
16443         }
16444         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
16445         removeCpuStatsForUidRangeLocked(firstUidForUser, lastUidForUser);
16446     }
16447 
16448     /**
16449      * Remove the statistics object for a particular uid.
16450      */
16451     @UnsupportedAppUsage
16452     @GuardedBy("this")
16453     public void removeUidStatsLocked(int uid) {
16454         removeUidStatsLocked(uid, mClock.elapsedRealtime());
16455     }
16456 
16457     /**
16458      * @see #removeUidStatsLocked(int)
16459      */
16460     @GuardedBy("this")
16461     public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) {
16462         final Uid u = mUidStats.get(uid);
16463         if (u != null) {
16464             u.detachFromTimeBase();
16465         }
16466         mUidStats.remove(uid);
16467         mPendingRemovedUids.add(new UidToRemove(uid, elapsedRealtimeMs));
16468     }
16469 
16470     /**
16471      * Removes the data for the deleted UIDs from the underlying kernel eBPF tables.
16472      */
16473     @GuardedBy("this")
16474     private void removeCpuStatsForUidRangeLocked(int startUid, int endUid) {
16475         if (startUid == endUid) {
16476             mCpuUidUserSysTimeReader.removeUid(startUid);
16477             mCpuUidFreqTimeReader.removeUid(startUid);
16478             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
16479                 mCpuUidActiveTimeReader.removeUid(startUid);
16480                 mCpuUidClusterTimeReader.removeUid(startUid);
16481             }
16482             if (mKernelSingleUidTimeReader != null) {
16483                 mKernelSingleUidTimeReader.removeUid(startUid);
16484             }
16485             mNumUidsRemoved++;
16486         } else if (startUid < endUid) {
16487             mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
16488             mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
16489             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
16490                 mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
16491                 mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
16492             }
16493             if (mKernelSingleUidTimeReader != null) {
16494                 mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
16495             }
16496             // Treat as one. We don't know how many uids there are in between.
16497             mNumUidsRemoved++;
16498         } else {
16499             Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
16500         }
16501     }
16502 
16503     /**
16504      * Retrieve the statistics object for a particular process, creating
16505      * if needed.
16506      */
16507     @UnsupportedAppUsage
16508     public Uid.Proc getProcessStatsLocked(int uid, String name) {
16509         return getProcessStatsLocked(uid, name, mClock.elapsedRealtime(), mClock.uptimeMillis());
16510     }
16511 
16512     /**
16513      * @see #getProcessStatsLocked(int, String)
16514      */
16515     public Uid.Proc getProcessStatsLocked(int uid, String name,
16516             long elapsedRealtimeMs, long uptimeMs) {
16517         uid = mapUid(uid);
16518         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
16519         return u.getProcessStatsLocked(name);
16520     }
16521 
16522     /**
16523      * Retrieve the statistics object for a particular process, creating
16524      * if needed.
16525      */
16526     @UnsupportedAppUsage
16527     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
16528         return getPackageStatsLocked(uid, pkg, mClock.elapsedRealtime(), mClock.uptimeMillis());
16529     }
16530 
16531     /**
16532      * @see getPackageStatsLocked(int, String)
16533      */
16534     public Uid.Pkg getPackageStatsLocked(int uid, String pkg,
16535             long elapsedRealtimeMs, long uptimeMs) {
16536         uid = mapUid(uid);
16537         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
16538         return u.getPackageStatsLocked(pkg);
16539     }
16540 
16541     /**
16542      * Retrieve the statistics object for a particular service, creating
16543      * if needed.
16544      */
16545     @UnsupportedAppUsage
16546     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
16547         return getServiceStatsLocked(uid, pkg, name,
16548                 mClock.elapsedRealtime(), mClock.uptimeMillis());
16549     }
16550 
16551     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name,
16552             long elapsedRealtimeMs, long uptimeMs) {
16553         uid = mapUid(uid);
16554         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
16555         return u.getServiceStatsLocked(pkg, name);
16556     }
16557 
16558     @GuardedBy("this")
16559     public void shutdownLocked() {
16560         recordShutdownLocked(mClock.currentTimeMillis(), mClock.elapsedRealtime());
16561         writeSyncLocked();
16562         mShuttingDown = true;
16563     }
16564 
16565     @GuardedBy("this")
16566     @Override
16567     public boolean isProcessStateDataAvailable() {
16568         return trackPerProcStateCpuTimes();
16569     }
16570 
16571     @GuardedBy("this")
16572     public boolean trackPerProcStateCpuTimes() {
16573         return mCpuUidFreqTimeReader.isFastCpuTimesReader();
16574     }
16575 
16576     @GuardedBy("this")
16577     public void systemServicesReady(Context context) {
16578         mConstants.startObserving(context.getContentResolver());
16579         registerUsbStateReceiver(context);
16580     }
16581 
16582     /**
16583      * Initialize the measured charge stats data structures.
16584      *
16585      * @param supportedStandardBuckets boolean array indicating which {@link StandardPowerBucket}s
16586      *                                 are currently supported. If null, none are supported
16587      *                                 (regardless of customBucketNames).
16588      * @param customBucketNames        names of custom (OTHER) EnergyConsumers on this device
16589      */
16590     @GuardedBy("this")
16591     public void initMeasuredEnergyStatsLocked(@Nullable boolean[] supportedStandardBuckets,
16592             String[] customBucketNames) {
16593         final int numDisplays = mPerDisplayBatteryStats.length;
16594         for (int i = 0; i < numDisplays; i++) {
16595             final int screenState = mPerDisplayBatteryStats[i].screenState;
16596             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
16597         }
16598 
16599         final boolean compatibleConfig;
16600         if (supportedStandardBuckets != null) {
16601             final MeasuredEnergyStats.Config config = new MeasuredEnergyStats.Config(
16602                     supportedStandardBuckets, customBucketNames,
16603                     SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS,
16604                     getBatteryConsumerProcessStateNames());
16605 
16606             if (mMeasuredEnergyStatsConfig == null) {
16607                 compatibleConfig = true;
16608             } else {
16609                 compatibleConfig = mMeasuredEnergyStatsConfig.isCompatible(config);
16610             }
16611 
16612             mMeasuredEnergyStatsConfig = config;
16613             mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(config);
16614 
16615             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH]) {
16616                 mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
16617             }
16618             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_CPU]) {
16619                 mCpuPowerCalculator = new CpuPowerCalculator(mPowerProfile);
16620             }
16621             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO]) {
16622                 mMobileRadioPowerCalculator = new MobileRadioPowerCalculator(mPowerProfile);
16623             }
16624             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_WIFI]) {
16625                 mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
16626             }
16627         } else {
16628             compatibleConfig = (mMeasuredEnergyStatsConfig == null);
16629             // Measured energy no longer supported, wipe out the existing data.
16630             mMeasuredEnergyStatsConfig = null;
16631             mGlobalMeasuredEnergyStats = null;
16632         }
16633 
16634         if (!compatibleConfig) {
16635             // Supported power buckets changed since last boot.
16636             // Existing data is no longer reliable.
16637             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
16638                     RESET_REASON_MEASURED_ENERGY_BUCKETS_CHANGE);
16639         }
16640     }
16641 
16642     @NonNull
16643     private static String[] getBatteryConsumerProcessStateNames() {
16644         String[] procStateNames = new String[BatteryConsumer.PROCESS_STATE_COUNT];
16645         for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
16646             procStateNames[procState] = BatteryConsumer.processStateToString(procState);
16647         }
16648         return procStateNames;
16649     }
16650 
16651     /** Get the last known Battery voltage (in millivolts), returns -1 if unknown */
16652     @GuardedBy("this")
16653     public int getBatteryVoltageMvLocked() {
16654         return mBatteryVoltageMv;
16655     }
16656 
16657     @VisibleForTesting
16658     public final class Constants extends ContentObserver {
16659         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
16660                 = "track_cpu_active_cluster_time";
16661         public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
16662                 = "proc_state_cpu_times_read_delay_ms";
16663         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
16664                 = "kernel_uid_readers_throttle_time";
16665         public static final String KEY_UID_REMOVE_DELAY_MS
16666                 = "uid_remove_delay_ms";
16667         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
16668                 = "external_stats_collection_rate_limit_ms";
16669         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
16670                 = "battery_level_collection_delay_ms";
16671         public static final String KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS =
16672                 "procstate_change_collection_delay_ms";
16673         public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
16674         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
16675         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
16676                 "battery_charged_delay_ms";
16677         public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
16678                 "phone_on_external_stats_collection";
16679 
16680         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
16681         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
16682         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
16683         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
16684         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
16685         private static final long DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS = 60_000;
16686         private static final int DEFAULT_MAX_HISTORY_FILES = 32;
16687         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
16688         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
16689         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
16690         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
16691         private static final boolean DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION = true;
16692 
16693         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
16694         /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
16695          * update when startObserving. */
16696         public long KERNEL_UID_READERS_THROTTLE_TIME;
16697         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
16698         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
16699                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
16700         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
16701                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
16702         public long PROC_STATE_CHANGE_COLLECTION_DELAY_MS =
16703                 DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS;
16704         public int MAX_HISTORY_FILES;
16705         public int MAX_HISTORY_BUFFER; /*Bytes*/
16706         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
16707         public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
16708                 DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
16709 
16710         private ContentResolver mResolver;
16711         private final KeyValueListParser mParser = new KeyValueListParser(',');
16712 
16713         public Constants(Handler handler) {
16714             super(handler);
16715             if (ActivityManager.isLowRamDeviceStatic()) {
16716                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE;
16717                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
16718             } else {
16719                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES;
16720                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
16721             }
16722         }
16723 
16724         public void startObserving(ContentResolver resolver) {
16725             mResolver = resolver;
16726             mResolver.registerContentObserver(
16727                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
16728                     false /* notifyForDescendants */, this);
16729             mResolver.registerContentObserver(
16730                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
16731                     false /* notifyForDescendants */, this);
16732             updateConstants();
16733         }
16734 
16735         @Override
16736         public void onChange(boolean selfChange, Uri uri) {
16737             if (uri.equals(
16738                     Settings.Global.getUriFor(
16739                             Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY))) {
16740                 synchronized (BatteryStatsImpl.this) {
16741                     updateBatteryChargedDelayMsLocked();
16742                 }
16743                 return;
16744             }
16745             updateConstants();
16746         }
16747 
16748         private void updateConstants() {
16749             synchronized (BatteryStatsImpl.this) {
16750                 try {
16751                     mParser.setString(Settings.Global.getString(mResolver,
16752                             Settings.Global.BATTERY_STATS_CONSTANTS));
16753                 } catch (IllegalArgumentException e) {
16754                     // Failed to parse the settings string, log this and move on
16755                     // with defaults.
16756                     Slog.e(TAG, "Bad batterystats settings", e);
16757                 }
16758 
16759                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
16760                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
16761                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
16762                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
16763                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
16764                 updateUidRemoveDelay(
16765                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
16766                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
16767                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
16768                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
16769                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
16770                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
16771                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
16772                 PROC_STATE_CHANGE_COLLECTION_DELAY_MS = mParser.getLong(
16773                         KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS,
16774                         DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
16775 
16776                 MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
16777                         ActivityManager.isLowRamDeviceStatic() ?
16778                                 DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
16779                         : DEFAULT_MAX_HISTORY_FILES);
16780                 MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
16781                         ActivityManager.isLowRamDeviceStatic() ?
16782                                 DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
16783                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
16784                         * 1024;
16785 
16786                 PHONE_ON_EXTERNAL_STATS_COLLECTION = mParser.getBoolean(
16787                         KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION,
16788                         DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION);
16789 
16790                 updateBatteryChargedDelayMsLocked();
16791             }
16792         }
16793 
16794         private void updateBatteryChargedDelayMsLocked() {
16795             // a negative value indicates that we should ignore this override
16796             final int delay = Settings.Global.getInt(mResolver,
16797                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
16798                     -1);
16799 
16800             BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
16801                     KEY_BATTERY_CHARGED_DELAY_MS,
16802                     DEFAULT_BATTERY_CHARGED_DELAY_MS);
16803 
16804             if (mHandler.hasCallbacks(mDeferSetCharging)) {
16805                 mHandler.removeCallbacks(mDeferSetCharging);
16806                 mHandler.postDelayed(mDeferSetCharging, BATTERY_CHARGED_DELAY_MS);
16807             }
16808         }
16809 
16810         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
16811             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
16812             if (oldTimeMs != newTimeMs) {
16813                 mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16814                 mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16815                 mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16816                 mCpuUidClusterTimeReader
16817                         .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16818             }
16819         }
16820 
16821         @GuardedBy("BatteryStatsImpl.this")
16822         private void updateUidRemoveDelay(long newTimeMs) {
16823             UID_REMOVE_DELAY_MS = newTimeMs;
16824             clearPendingRemovedUidsLocked();
16825         }
16826 
16827         public void dumpLocked(PrintWriter pw) {
16828             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
16829             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
16830             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
16831             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
16832             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
16833             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
16834             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
16835             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
16836             pw.print(KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS); pw.print("=");
16837             pw.println(PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
16838             pw.print(KEY_MAX_HISTORY_FILES); pw.print("=");
16839             pw.println(MAX_HISTORY_FILES);
16840             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
16841             pw.println(MAX_HISTORY_BUFFER/1024);
16842             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
16843             pw.println(BATTERY_CHARGED_DELAY_MS);
16844             pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");
16845             pw.println(PHONE_ON_EXTERNAL_STATS_COLLECTION);
16846         }
16847     }
16848 
16849     public long getExternalStatsCollectionRateLimitMs() {
16850         synchronized (this) {
16851             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
16852         }
16853     }
16854 
16855     @GuardedBy("this")
16856     public void dumpConstantsLocked(PrintWriter pw) {
16857         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16858         iPw.println("BatteryStats constants:");
16859         iPw.increaseIndent();
16860         mConstants.dumpLocked(iPw);
16861         iPw.decreaseIndent();
16862     }
16863 
16864     @GuardedBy("this")
16865     public void dumpCpuStatsLocked(PrintWriter pw) {
16866         int size = mUidStats.size();
16867         pw.println("Per UID CPU user & system time in ms:");
16868         for (int i = 0; i < size; i++) {
16869             int u = mUidStats.keyAt(i);
16870             Uid uid = mUidStats.get(u);
16871             pw.print("  "); pw.print(u); pw.print(": ");
16872             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
16873             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
16874         }
16875 
16876         pw.println("Per UID CPU active time in ms:");
16877         for (int i = 0; i < size; i++) {
16878             int u = mUidStats.keyAt(i);
16879             Uid uid = mUidStats.get(u);
16880             if (uid.getCpuActiveTime() > 0) {
16881                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
16882             }
16883         }
16884         pw.println("Per UID CPU cluster time in ms:");
16885         for (int i = 0; i < size; i++) {
16886             int u = mUidStats.keyAt(i);
16887             long[] times = mUidStats.get(u).getCpuClusterTimes();
16888             if (times != null) {
16889                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
16890             }
16891         }
16892         pw.println("Per UID CPU frequency time in ms:");
16893         for (int i = 0; i < size; i++) {
16894             int u = mUidStats.keyAt(i);
16895             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
16896             if (times != null) {
16897                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
16898             }
16899         }
16900 
16901         updateSystemServiceCallStats();
16902         if (mBinderThreadCpuTimesUs != null) {
16903             pw.println("Per UID System server binder time in ms:");
16904             long[] systemServiceTimeAtCpuSpeeds = getSystemServiceTimeAtCpuSpeeds();
16905             for (int i = 0; i < size; i++) {
16906                 int u = mUidStats.keyAt(i);
16907                 Uid uid = mUidStats.get(u);
16908                 double proportionalSystemServiceUsage = uid.getProportionalSystemServiceUsage();
16909                 long timeUs = 0;
16910                 for (int j = systemServiceTimeAtCpuSpeeds.length - 1; j >= 0; j--) {
16911                     timeUs += systemServiceTimeAtCpuSpeeds[j] * proportionalSystemServiceUsage;
16912                 }
16913 
16914                 pw.print("  ");
16915                 pw.print(u);
16916                 pw.print(": ");
16917                 pw.println(timeUs / 1000);
16918             }
16919         }
16920     }
16921 
16922     /**
16923      * Dump measured charge stats
16924      */
16925     @GuardedBy("this")
16926     public void dumpMeasuredEnergyStatsLocked(PrintWriter pw) {
16927         pw.printf("On battery measured charge stats (microcoulombs) \n");
16928         if (mGlobalMeasuredEnergyStats == null) {
16929             pw.printf("    Not supported on this device.\n");
16930             return;
16931         }
16932 
16933         dumpMeasuredEnergyStatsLocked(pw, "global usage", mGlobalMeasuredEnergyStats);
16934 
16935         int size = mUidStats.size();
16936         for (int i = 0; i < size; i++) {
16937             final int u = mUidStats.keyAt(i);
16938             final Uid uid = mUidStats.get(u);
16939             final String name = "uid " + uid.mUid;
16940             dumpMeasuredEnergyStatsLocked(pw, name, uid.mUidMeasuredEnergyStats);
16941         }
16942     }
16943 
16944     /** Dump measured charge stats for the given uid */
16945     @GuardedBy("this")
16946     private void dumpMeasuredEnergyStatsLocked(PrintWriter pw, String name,
16947             MeasuredEnergyStats stats) {
16948         if (stats == null) return;
16949         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16950         iPw.increaseIndent();
16951         iPw.printf("%s:\n", name);
16952         iPw.increaseIndent();
16953         stats.dump(iPw);
16954         iPw.decreaseIndent();
16955     }
16956 
16957     /**
16958      * Dump Power Profile
16959      */
16960     @GuardedBy("this")
16961     public void dumpPowerProfileLocked(PrintWriter pw) {
16962         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16963         iPw.printf("Power Profile: \n");
16964         iPw.increaseIndent();
16965         mPowerProfile.dump(iPw);
16966         iPw.decreaseIndent();
16967     }
16968 
16969     final ReentrantLock mWriteLock = new ReentrantLock();
16970 
16971     @GuardedBy("this")
16972     public void writeAsyncLocked() {
16973         writeStatsLocked(false);
16974         writeHistoryLocked(false);
16975     }
16976 
16977     @GuardedBy("this")
16978     public void writeSyncLocked() {
16979         writeStatsLocked(true);
16980         writeHistoryLocked(true);
16981     }
16982 
16983     @GuardedBy("this")
16984     void writeStatsLocked(boolean sync) {
16985         if (mStatsFile == null) {
16986             Slog.w(TAG,
16987                     "writeStatsLocked: no file associated with this instance");
16988             return;
16989         }
16990 
16991         if (mShuttingDown) {
16992             return;
16993         }
16994 
16995         final Parcel p = Parcel.obtain();
16996         final long start = SystemClock.uptimeMillis();
16997         writeSummaryToParcel(p, false/*history is in separate file*/);
16998         if (DEBUG) {
16999             Slog.d(TAG, "writeSummaryToParcel duration ms:"
17000                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
17001         }
17002         mLastWriteTimeMs = mClock.elapsedRealtime();
17003         writeParcelToFileLocked(p, mStatsFile, sync);
17004     }
17005 
17006     void writeHistoryLocked(boolean sync) {
17007         if (mBatteryStatsHistory.getActiveFile() == null) {
17008             Slog.w(TAG,
17009                     "writeHistoryLocked: no history file associated with this instance");
17010             return;
17011         }
17012 
17013         if (mShuttingDown) {
17014             return;
17015         }
17016 
17017         Parcel p = Parcel.obtain();
17018         final long start = SystemClock.uptimeMillis();
17019         writeHistoryBuffer(p, true);
17020         if (DEBUG) {
17021             Slog.d(TAG, "writeHistoryBuffer duration ms:"
17022                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
17023         }
17024         writeParcelToFileLocked(p, mBatteryStatsHistory.getActiveFile(), sync);
17025     }
17026 
17027     void writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync) {
17028         if (sync) {
17029             commitPendingDataToDisk(p, file);
17030         } else {
17031             BackgroundThread.getHandler().post(new Runnable() {
17032                 @Override public void run() {
17033                     commitPendingDataToDisk(p, file);
17034                 }
17035             });
17036         }
17037     }
17038 
17039     private void commitPendingDataToDisk(Parcel p, AtomicFile file) {
17040         mWriteLock.lock();
17041         FileOutputStream fos = null;
17042         try {
17043             final long startTimeMs = SystemClock.uptimeMillis();
17044             fos = file.startWrite();
17045             fos.write(p.marshall());
17046             fos.flush();
17047             file.finishWrite(fos);
17048             if (DEBUG) {
17049                 Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
17050                         + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
17051                         + " bytes:" + p.dataSize());
17052             }
17053             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
17054                     "batterystats", SystemClock.uptimeMillis() - startTimeMs);
17055         } catch (IOException e) {
17056             Slog.w(TAG, "Error writing battery statistics", e);
17057             file.failWrite(fos);
17058         } finally {
17059             p.recycle();
17060             mWriteLock.unlock();
17061         }
17062     }
17063 
17064     @UnsupportedAppUsage
17065     @GuardedBy("this")
17066     public void readLocked() {
17067         if (mDailyFile != null) {
17068             readDailyStatsLocked();
17069         }
17070 
17071         if (mStatsFile == null) {
17072             Slog.w(TAG, "readLocked: no file associated with this instance");
17073             return;
17074         }
17075 
17076         final AtomicFile activeHistoryFile = mBatteryStatsHistory.getActiveFile();
17077         if (activeHistoryFile == null) {
17078             Slog.w(TAG,
17079                     "readLocked: no history file associated with this instance");
17080             return;
17081         }
17082 
17083         mUidStats.clear();
17084 
17085         Parcel stats = Parcel.obtain();
17086         try {
17087             final long start = SystemClock.uptimeMillis();
17088             if (mStatsFile.exists()) {
17089                 byte[] raw = mStatsFile.readFully();
17090                 stats.unmarshall(raw, 0, raw.length);
17091                 stats.setDataPosition(0);
17092                 readSummaryFromParcel(stats);
17093                 if (DEBUG) {
17094                     Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
17095                             + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
17096                             - start));
17097                 }
17098             }
17099         } catch (Exception e) {
17100             Slog.e(TAG, "Error reading battery statistics", e);
17101             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
17102                     RESET_REASON_CORRUPT_FILE);
17103         } finally {
17104             stats.recycle();
17105         }
17106 
17107         Parcel history = Parcel.obtain();
17108         try {
17109             final long start = SystemClock.uptimeMillis();
17110             if (activeHistoryFile.exists()) {
17111                 byte[] raw = activeHistoryFile.readFully();
17112                 if (raw.length > 0) {
17113                     history.unmarshall(raw, 0, raw.length);
17114                     history.setDataPosition(0);
17115                     readHistoryBuffer(history);
17116                 }
17117                 if (DEBUG) {
17118                     Slog.d(TAG, "readLocked history file::"
17119                             + activeHistoryFile.getBaseFile().getPath()
17120                             + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
17121                             - start));
17122                 }
17123             }
17124         } catch (Exception e) {
17125             Slog.e(TAG, "Error reading battery history", e);
17126             clearHistoryLocked();
17127             mBatteryStatsHistory.resetAllFiles();
17128         } finally {
17129             history.recycle();
17130         }
17131 
17132         mEndPlatformVersion = Build.ID;
17133 
17134         if (mHistoryBuffer.dataPosition() > 0
17135                 || mBatteryStatsHistory.getFilesNumbers().size() > 1) {
17136             mRecordingHistory = true;
17137             final long elapsedRealtimeMs = mClock.elapsedRealtime();
17138             final long uptimeMs = mClock.uptimeMillis();
17139             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_START, mHistoryCur);
17140             startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
17141         }
17142 
17143         recordDailyStatsIfNeededLocked(false, mClock.currentTimeMillis());
17144     }
17145 
17146     public int describeContents() {
17147         return 0;
17148     }
17149 
17150     @GuardedBy("this")
17151     void  readHistoryBuffer(Parcel in) throws ParcelFormatException {
17152         final int version = in.readInt();
17153         if (version != VERSION) {
17154             Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
17155                     + ", expected " + VERSION + "; erasing old stats");
17156             return;
17157         }
17158 
17159         final long historyBaseTime = in.readLong();
17160 
17161         mHistoryBuffer.setDataSize(0);
17162         mHistoryBuffer.setDataPosition(0);
17163 
17164         int bufSize = in.readInt();
17165         int curPos = in.dataPosition();
17166         if (bufSize >= (mConstants.MAX_HISTORY_BUFFER*100)) {
17167             throw new ParcelFormatException("File corrupt: history data buffer too large " +
17168                     bufSize);
17169         } else if ((bufSize&~3) != bufSize) {
17170             throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
17171                     bufSize);
17172         } else {
17173             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
17174                     + " bytes at " + curPos);
17175             mHistoryBuffer.appendFrom(in, curPos, bufSize);
17176             in.setDataPosition(curPos + bufSize);
17177         }
17178 
17179         if (DEBUG_HISTORY) {
17180             StringBuilder sb = new StringBuilder(128);
17181             sb.append("****************** OLD mHistoryBaseTimeMs: ");
17182             TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
17183             Slog.i(TAG, sb.toString());
17184         }
17185         mHistoryBaseTimeMs = historyBaseTime;
17186         if (DEBUG_HISTORY) {
17187             StringBuilder sb = new StringBuilder(128);
17188             sb.append("****************** NEW mHistoryBaseTimeMs: ");
17189             TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
17190             Slog.i(TAG, sb.toString());
17191         }
17192 
17193         // We are just arbitrarily going to insert 1 minute from the sample of
17194         // the last run until samples in this run.
17195         if (mHistoryBaseTimeMs > 0) {
17196             long oldnow = mClock.elapsedRealtime();
17197             mHistoryBaseTimeMs = mHistoryBaseTimeMs - oldnow + 1;
17198             if (DEBUG_HISTORY) {
17199                 StringBuilder sb = new StringBuilder(128);
17200                 sb.append("****************** ADJUSTED mHistoryBaseTimeMs: ");
17201                 TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
17202                 Slog.i(TAG, sb.toString());
17203             }
17204         }
17205     }
17206 
17207     void writeHistoryBuffer(Parcel out, boolean inclData) {
17208         if (DEBUG_HISTORY) {
17209             StringBuilder sb = new StringBuilder(128);
17210             sb.append("****************** WRITING mHistoryBaseTimeMs: ");
17211             TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
17212             sb.append(" mLastHistoryElapsedRealtimeMs: ");
17213             TimeUtils.formatDuration(mLastHistoryElapsedRealtimeMs, sb);
17214             Slog.i(TAG, sb.toString());
17215         }
17216         out.writeInt(VERSION);
17217         out.writeLong(mHistoryBaseTimeMs + mLastHistoryElapsedRealtimeMs);
17218         if (!inclData) {
17219             out.writeInt(0);
17220             out.writeInt(0);
17221             return;
17222         }
17223 
17224         out.writeInt(mHistoryBuffer.dataSize());
17225         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
17226                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
17227         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
17228     }
17229 
17230     @GuardedBy("this")
17231     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
17232         final int version = in.readInt();
17233 
17234         if (version != VERSION) {
17235             Slog.w("BatteryStats", "readFromParcel: version got " + version
17236                 + ", expected " + VERSION + "; erasing old stats");
17237             return;
17238         }
17239 
17240         boolean inclHistory = in.readBoolean();
17241         if (inclHistory) {
17242             readHistoryBuffer(in);
17243             mBatteryStatsHistory.readFromParcel(in);
17244         }
17245 
17246         mHistoryTagPool.clear();
17247         mNextHistoryTagIdx = 0;
17248         mNumHistoryTagChars = 0;
17249 
17250         int numTags = in.readInt();
17251         for (int i=0; i<numTags; i++) {
17252             int idx = in.readInt();
17253             String str = in.readString();
17254             int uid = in.readInt();
17255             HistoryTag tag = new HistoryTag();
17256             tag.string = str;
17257             tag.uid = uid;
17258             tag.poolIdx = idx;
17259             mHistoryTagPool.put(tag, idx);
17260             if (idx >= mNextHistoryTagIdx) {
17261                 mNextHistoryTagIdx = idx+1;
17262             }
17263             mNumHistoryTagChars += tag.string.length() + 1;
17264         }
17265 
17266         mStartCount = in.readInt();
17267         mUptimeUs = in.readLong();
17268         mRealtimeUs = in.readLong();
17269         mStartClockTimeMs = in.readLong();
17270         mStartPlatformVersion = in.readString();
17271         mEndPlatformVersion = in.readString();
17272         mOnBatteryTimeBase.readSummaryFromParcel(in);
17273         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
17274         mDischargeUnplugLevel = in.readInt();
17275         mDischargePlugLevel = in.readInt();
17276         mDischargeCurrentLevel = in.readInt();
17277         mCurrentBatteryLevel = in.readInt();
17278         mEstimatedBatteryCapacityMah = in.readInt();
17279         mLastLearnedBatteryCapacityUah = in.readInt();
17280         mMinLearnedBatteryCapacityUah = in.readInt();
17281         mMaxLearnedBatteryCapacityUah = in.readInt();
17282         mLowDischargeAmountSinceCharge = in.readInt();
17283         mHighDischargeAmountSinceCharge = in.readInt();
17284         mDischargeAmountScreenOnSinceCharge = in.readInt();
17285         mDischargeAmountScreenOffSinceCharge = in.readInt();
17286         mDischargeAmountScreenDozeSinceCharge = in.readInt();
17287         mDischargeStepTracker.readFromParcel(in);
17288         mChargeStepTracker.readFromParcel(in);
17289         mDailyDischargeStepTracker.readFromParcel(in);
17290         mDailyChargeStepTracker.readFromParcel(in);
17291         mDischargeCounter.readSummaryFromParcelLocked(in);
17292         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
17293         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
17294         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
17295         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
17296         int NPKG = in.readInt();
17297         if (NPKG > 0) {
17298             mDailyPackageChanges = new ArrayList<>(NPKG);
17299             while (NPKG > 0) {
17300                 NPKG--;
17301                 PackageChange pc = new PackageChange();
17302                 pc.mPackageName = in.readString();
17303                 pc.mUpdate = in.readInt() != 0;
17304                 pc.mVersionCode = in.readLong();
17305                 mDailyPackageChanges.add(pc);
17306             }
17307         } else {
17308             mDailyPackageChanges = null;
17309         }
17310         mDailyStartTimeMs = in.readLong();
17311         mNextMinDailyDeadlineMs = in.readLong();
17312         mNextMaxDailyDeadlineMs = in.readLong();
17313         mBatteryTimeToFullSeconds = in.readLong();
17314 
17315         final MeasuredEnergyStats.Config config = MeasuredEnergyStats.Config.createFromParcel(in);
17316         final MeasuredEnergyStats measuredEnergyStats =
17317                 MeasuredEnergyStats.createAndReadSummaryFromParcel(mMeasuredEnergyStatsConfig, in);
17318         if (config != null && Arrays.equals(config.getStateNames(),
17319                 getBatteryConsumerProcessStateNames())) {
17320             /**
17321              * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
17322              *          later when {@link #initMeasuredEnergyStatsLocked} is called.
17323              */
17324             mMeasuredEnergyStatsConfig = config;
17325             mGlobalMeasuredEnergyStats = measuredEnergyStats;
17326         }
17327 
17328         mStartCount++;
17329 
17330         mScreenState = Display.STATE_UNKNOWN;
17331         mScreenOnTimer.readSummaryFromParcelLocked(in);
17332         mScreenDozeTimer.readSummaryFromParcelLocked(in);
17333         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
17334             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
17335         }
17336         mInteractive = false;
17337         mInteractiveTimer.readSummaryFromParcelLocked(in);
17338         mPhoneOn = false;
17339         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
17340         mLongestLightIdleTimeMs = in.readLong();
17341         mLongestFullIdleTimeMs = in.readLong();
17342         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
17343         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
17344         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
17345         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
17346         mPhoneOnTimer.readSummaryFromParcelLocked(in);
17347         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
17348             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
17349         }
17350         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
17351         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
17352             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
17353         }
17354         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
17355             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
17356             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
17357         }
17358 
17359         final int numRat = in.readInt();
17360         for (int i = 0; i < numRat; i++) {
17361             if (in.readInt() == 0) continue;
17362             getRatBatteryStatsLocked(i).readSummaryFromParcel(in);
17363         }
17364 
17365         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
17366         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
17367         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
17368         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
17369         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
17370         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
17371         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
17372         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
17373         mWifiOn = false;
17374         mWifiOnTimer.readSummaryFromParcelLocked(in);
17375         mGlobalWifiRunning = false;
17376         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
17377         for (int i=0; i<NUM_WIFI_STATES; i++) {
17378             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
17379         }
17380         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
17381             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
17382         }
17383         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
17384             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
17385         }
17386         mWifiActiveTimer.readSummaryFromParcelLocked(in);
17387         mWifiActivity.readSummaryFromParcel(in);
17388         for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
17389             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
17390         }
17391         mBluetoothActivity.readSummaryFromParcel(in);
17392         mModemActivity.readSummaryFromParcel(in);
17393         mHasWifiReporting = in.readInt() != 0;
17394         mHasBluetoothReporting = in.readInt() != 0;
17395         mHasModemReporting = in.readInt() != 0;
17396 
17397         mNumConnectivityChange = in.readInt();
17398         mFlashlightOnNesting = 0;
17399         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
17400         mCameraOnNesting = 0;
17401         mCameraOnTimer.readSummaryFromParcelLocked(in);
17402         mBluetoothScanNesting = 0;
17403         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
17404 
17405         int NRPMS = in.readInt();
17406         if (NRPMS > 10000) {
17407             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
17408         }
17409         for (int irpm = 0; irpm < NRPMS; irpm++) {
17410             if (in.readInt() != 0) {
17411                 String rpmName = in.readString();
17412                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
17413             }
17414         }
17415         int NSORPMS = in.readInt();
17416         if (NSORPMS > 10000) {
17417             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
17418         }
17419         for (int irpm = 0; irpm < NSORPMS; irpm++) {
17420             if (in.readInt() != 0) {
17421                 String rpmName = in.readString();
17422                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
17423             }
17424         }
17425         int NKW = in.readInt();
17426         if (NKW > 10000) {
17427             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
17428         }
17429         for (int ikw = 0; ikw < NKW; ikw++) {
17430             if (in.readInt() != 0) {
17431                 String kwltName = in.readString();
17432                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
17433             }
17434         }
17435 
17436         int NWR = in.readInt();
17437         if (NWR > 10000) {
17438             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
17439         }
17440         for (int iwr = 0; iwr < NWR; iwr++) {
17441             if (in.readInt() != 0) {
17442                 String reasonName = in.readString();
17443                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
17444             }
17445         }
17446 
17447         int NMS = in.readInt();
17448         for (int ims = 0; ims < NMS; ims++) {
17449             if (in.readInt() != 0) {
17450                 long kmstName = in.readLong();
17451                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
17452             }
17453         }
17454 
17455         final int NU = in.readInt();
17456         if (NU > 10000) {
17457             throw new ParcelFormatException("File corrupt: too many uids " + NU);
17458         }
17459         final long elapsedRealtimeMs = mClock.elapsedRealtime();
17460         final long uptimeMs = mClock.uptimeMillis();
17461         for (int iu = 0; iu < NU; iu++) {
17462             int uid = in.readInt();
17463             Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
17464             mUidStats.put(uid, u);
17465 
17466             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
17467             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
17468 
17469             u.mWifiRunning = false;
17470             if (in.readInt() != 0) {
17471                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
17472             }
17473             u.mFullWifiLockOut = false;
17474             if (in.readInt() != 0) {
17475                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
17476             }
17477             u.mWifiScanStarted = false;
17478             if (in.readInt() != 0) {
17479                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
17480             }
17481             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
17482             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
17483                 if (in.readInt() != 0) {
17484                     u.makeWifiBatchedScanBin(i, null);
17485                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
17486                 }
17487             }
17488             u.mWifiMulticastWakelockCount = 0;
17489             if (in.readInt() != 0) {
17490                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
17491             }
17492             if (in.readInt() != 0) {
17493                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
17494             }
17495             if (in.readInt() != 0) {
17496                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
17497             }
17498             if (in.readInt() != 0) {
17499                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
17500             }
17501             if (in.readInt() != 0) {
17502                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
17503             }
17504             if (in.readInt() != 0) {
17505                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
17506             }
17507             if (in.readInt() != 0) {
17508                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
17509             }
17510             if (in.readInt() != 0) {
17511                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
17512             }
17513             if (in.readInt() != 0) {
17514                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
17515             }
17516             if (in.readInt() != 0) {
17517                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
17518             }
17519             if (in.readInt() != 0) {
17520                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
17521             }
17522             if (in.readInt() != 0) {
17523                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
17524             }
17525             u.mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
17526             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
17527                 if (in.readInt() != 0) {
17528                     u.makeProcessState(i, null);
17529                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
17530                 }
17531             }
17532             if (in.readInt() != 0) {
17533                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
17534             }
17535 
17536             if (in.readInt() != 0) {
17537                 if (u.mUserActivityCounters == null) {
17538                     u.initUserActivityLocked();
17539                 }
17540                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
17541                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
17542                 }
17543             }
17544 
17545             if (in.readInt() != 0) {
17546                 u.ensureNetworkActivityLocked();
17547                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
17548                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
17549                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
17550                 }
17551                 if (in.readBoolean()) {
17552                     u.mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in,
17553                             mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
17554                             elapsedRealtimeMs);
17555                 }
17556                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
17557             }
17558 
17559             u.mUserCpuTime.readSummaryFromParcelLocked(in);
17560             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
17561 
17562             if (in.readInt() != 0) {
17563                 final int numClusters = in.readInt();
17564                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
17565                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
17566                 }
17567                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
17568                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
17569                 for (int cluster = 0; cluster < numClusters; cluster++) {
17570                     if (in.readInt() != 0) {
17571                         final int NSB = in.readInt();
17572                         if (mPowerProfile != null &&
17573                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
17574                             throw new ParcelFormatException("File corrupt: too many speed bins " +
17575                                     NSB);
17576                         }
17577 
17578                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
17579                         for (int speed = 0; speed < NSB; speed++) {
17580                             if (in.readInt() != 0) {
17581                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
17582                                         mOnBatteryTimeBase);
17583                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
17584                             }
17585                         }
17586                     } else {
17587                         u.mCpuClusterSpeedTimesUs[cluster] = null;
17588                     }
17589                 }
17590             } else {
17591                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
17592                 u.mCpuClusterSpeedTimesUs = null;
17593             }
17594 
17595             detachIfNotNull(u.mCpuFreqTimeMs);
17596             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
17597                     in, mOnBatteryTimeBase);
17598             detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
17599             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
17600                     in, mOnBatteryScreenOffTimeBase);
17601 
17602             int stateCount = in.readInt();
17603             if (stateCount != 0) {
17604                 u.mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in,
17605                         mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
17606                         mClock.elapsedRealtime());
17607             }
17608             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
17609 
17610             detachIfNotNull(u.mProcStateTimeMs);
17611             u.mProcStateTimeMs = null;
17612 
17613             stateCount = in.readInt();
17614             if (stateCount != 0) {
17615                 detachIfNotNull(u.mProcStateTimeMs);
17616                 u.mProcStateTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
17617                         mOnBatteryTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
17618                         getCpuFreqCount(), mClock.elapsedRealtime());
17619             }
17620 
17621             detachIfNotNull(u.mProcStateScreenOffTimeMs);
17622             u.mProcStateScreenOffTimeMs = null;
17623 
17624             stateCount = in.readInt();
17625             if (stateCount != 0) {
17626                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
17627                 u.mProcStateScreenOffTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
17628                         mOnBatteryScreenOffTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
17629                         getCpuFreqCount(), mClock.elapsedRealtime());
17630             }
17631 
17632             if (in.readInt() != 0) {
17633                 detachIfNotNull(u.mMobileRadioApWakeupCount);
17634                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
17635                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
17636             } else {
17637                 detachIfNotNull(u.mMobileRadioApWakeupCount);
17638                 u.mMobileRadioApWakeupCount = null;
17639             }
17640 
17641             if (in.readInt() != 0) {
17642                 detachIfNotNull(u.mWifiRadioApWakeupCount);
17643                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
17644                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
17645             } else {
17646                 detachIfNotNull(u.mWifiRadioApWakeupCount);
17647                 u.mWifiRadioApWakeupCount = null;
17648             }
17649 
17650             u.mUidMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(
17651                     mMeasuredEnergyStatsConfig, in);
17652 
17653             int NW = in.readInt();
17654             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
17655                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
17656             }
17657             for (int iw = 0; iw < NW; iw++) {
17658                 String wlName = in.readString();
17659                 u.readWakeSummaryFromParcelLocked(wlName, in);
17660             }
17661 
17662             int NS = in.readInt();
17663             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
17664                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
17665             }
17666             for (int is = 0; is < NS; is++) {
17667                 String name = in.readString();
17668                 u.readSyncSummaryFromParcelLocked(name, in);
17669             }
17670 
17671             int NJ = in.readInt();
17672             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
17673                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
17674             }
17675             for (int ij = 0; ij < NJ; ij++) {
17676                 String name = in.readString();
17677                 u.readJobSummaryFromParcelLocked(name, in);
17678             }
17679 
17680             u.readJobCompletionsFromParcelLocked(in);
17681 
17682             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
17683             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
17684             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
17685             detachIfNotNull(u.mJobsFreshnessBuckets);
17686             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
17687                 if (in.readInt() != 0) {
17688                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
17689                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
17690                 }
17691             }
17692 
17693             int NP = in.readInt();
17694             if (NP > 1000) {
17695                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
17696             }
17697             for (int is = 0; is < NP; is++) {
17698                 int seNumber = in.readInt();
17699                 if (in.readInt() != 0) {
17700                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
17701                 }
17702             }
17703 
17704             NP = in.readInt();
17705             if (NP > 1000) {
17706                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
17707             }
17708             for (int ip = 0; ip < NP; ip++) {
17709                 String procName = in.readString();
17710                 Uid.Proc p = u.getProcessStatsLocked(procName);
17711                 p.mUserTimeMs = in.readLong();
17712                 p.mSystemTimeMs = in.readLong();
17713                 p.mForegroundTimeMs = in.readLong();
17714                 p.mStarts = in.readInt();
17715                 p.mNumCrashes = in.readInt();
17716                 p.mNumAnrs = in.readInt();
17717                 p.readExcessivePowerFromParcelLocked(in);
17718             }
17719 
17720             NP = in.readInt();
17721             if (NP > 10000) {
17722                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
17723             }
17724             for (int ip = 0; ip < NP; ip++) {
17725                 String pkgName = in.readString();
17726                 detachIfNotNull(u.mPackageStats.get(pkgName));
17727                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
17728                 final int NWA = in.readInt();
17729                 if (NWA > 10000) {
17730                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
17731                 }
17732                 p.mWakeupAlarms.clear();
17733                 for (int iwa = 0; iwa < NWA; iwa++) {
17734                     String tag = in.readString();
17735                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
17736                     c.readSummaryFromParcelLocked(in);
17737                     p.mWakeupAlarms.put(tag, c);
17738                 }
17739                 NS = in.readInt();
17740                 if (NS > 10000) {
17741                     throw new ParcelFormatException("File corrupt: too many services " + NS);
17742                 }
17743                 for (int is = 0; is < NS; is++) {
17744                     String servName = in.readString();
17745                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
17746                     s.mStartTimeMs = in.readLong();
17747                     s.mStarts = in.readInt();
17748                     s.mLaunches = in.readInt();
17749                 }
17750             }
17751         }
17752 
17753         mBinderThreadCpuTimesUs =
17754                 LongSamplingCounterArray.readSummaryFromParcelLocked(in, mOnBatteryTimeBase);
17755     }
17756 
17757     /**
17758      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
17759      * disk.  This format does not allow a lossless round-trip.
17760      *
17761      * @param out the Parcel to be written to.
17762      */
17763     @GuardedBy("this")
17764     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
17765         pullPendingStateUpdatesLocked();
17766 
17767         // Pull the clock time.  This may update the time and make a new history entry
17768         // if we had originally pulled a time before the RTC was set.
17769         getStartClockTime();
17770 
17771         final long nowUptime = mClock.uptimeMillis() * 1000;
17772         final long nowRealtime = mClock.elapsedRealtime() * 1000;
17773 
17774         out.writeInt(VERSION);
17775 
17776         out.writeBoolean(inclHistory);
17777         if (inclHistory) {
17778             writeHistoryBuffer(out, true);
17779             mBatteryStatsHistory.writeToParcel(out);
17780         }
17781 
17782         out.writeInt(mHistoryTagPool.size());
17783         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
17784             HistoryTag tag = ent.getKey();
17785             out.writeInt(ent.getValue());
17786             out.writeString(tag.string);
17787             out.writeInt(tag.uid);
17788         }
17789 
17790         out.writeInt(mStartCount);
17791         out.writeLong(computeUptime(nowUptime, STATS_SINCE_CHARGED));
17792         out.writeLong(computeRealtime(nowRealtime, STATS_SINCE_CHARGED));
17793         out.writeLong(mStartClockTimeMs);
17794         out.writeString(mStartPlatformVersion);
17795         out.writeString(mEndPlatformVersion);
17796         mOnBatteryTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
17797         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
17798         out.writeInt(mDischargeUnplugLevel);
17799         out.writeInt(mDischargePlugLevel);
17800         out.writeInt(mDischargeCurrentLevel);
17801         out.writeInt(mCurrentBatteryLevel);
17802         out.writeInt(mEstimatedBatteryCapacityMah);
17803         out.writeInt(mLastLearnedBatteryCapacityUah);
17804         out.writeInt(mMinLearnedBatteryCapacityUah);
17805         out.writeInt(mMaxLearnedBatteryCapacityUah);
17806         out.writeInt(getLowDischargeAmountSinceCharge());
17807         out.writeInt(getHighDischargeAmountSinceCharge());
17808         out.writeInt(getDischargeAmountScreenOnSinceCharge());
17809         out.writeInt(getDischargeAmountScreenOffSinceCharge());
17810         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
17811         mDischargeStepTracker.writeToParcel(out);
17812         mChargeStepTracker.writeToParcel(out);
17813         mDailyDischargeStepTracker.writeToParcel(out);
17814         mDailyChargeStepTracker.writeToParcel(out);
17815         mDischargeCounter.writeSummaryFromParcelLocked(out);
17816         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
17817         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
17818         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
17819         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
17820         if (mDailyPackageChanges != null) {
17821             final int NPKG = mDailyPackageChanges.size();
17822             out.writeInt(NPKG);
17823             for (int i=0; i<NPKG; i++) {
17824                 PackageChange pc = mDailyPackageChanges.get(i);
17825                 out.writeString(pc.mPackageName);
17826                 out.writeInt(pc.mUpdate ? 1 : 0);
17827                 out.writeLong(pc.mVersionCode);
17828             }
17829         } else {
17830             out.writeInt(0);
17831         }
17832         out.writeLong(mDailyStartTimeMs);
17833         out.writeLong(mNextMinDailyDeadlineMs);
17834         out.writeLong(mNextMaxDailyDeadlineMs);
17835         out.writeLong(mBatteryTimeToFullSeconds);
17836 
17837         MeasuredEnergyStats.Config.writeToParcel(mMeasuredEnergyStatsConfig, out);
17838         MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out);
17839 
17840         mScreenOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17841         mScreenDozeTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17842         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
17843             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17844         }
17845         mInteractiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17846         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17847         out.writeLong(mLongestLightIdleTimeMs);
17848         out.writeLong(mLongestFullIdleTimeMs);
17849         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17850         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17851         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17852         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17853         mPhoneOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17854         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
17855             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17856         }
17857         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17858         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
17859             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17860         }
17861         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
17862             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
17863             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
17864         }
17865         final int numRat = mPerRatBatteryStats.length;
17866         out.writeInt(numRat);
17867         for (int i = 0; i < numRat; i++) {
17868             final RadioAccessTechnologyBatteryStats ratStat = mPerRatBatteryStats[i];
17869             if (ratStat == null) {
17870                 out.writeInt(0);
17871                 continue;
17872             }
17873             out.writeInt(1);
17874             ratStat.writeSummaryToParcel(out, nowRealtime);
17875         }
17876         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17877         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17878         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
17879         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
17880         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
17881         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17882         mWifiOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17883         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17884         for (int i=0; i<NUM_WIFI_STATES; i++) {
17885             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17886         }
17887         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
17888             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17889         }
17890         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
17891             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17892         }
17893         mWifiActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17894         mWifiActivity.writeSummaryToParcel(out);
17895         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
17896             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17897         }
17898         mBluetoothActivity.writeSummaryToParcel(out);
17899         mModemActivity.writeSummaryToParcel(out);
17900         out.writeInt(mHasWifiReporting ? 1 : 0);
17901         out.writeInt(mHasBluetoothReporting ? 1 : 0);
17902         out.writeInt(mHasModemReporting ? 1 : 0);
17903 
17904         out.writeInt(mNumConnectivityChange);
17905         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17906         mCameraOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17907         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17908 
17909         out.writeInt(mRpmStats.size());
17910         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
17911             Timer rpmt = ent.getValue();
17912             if (rpmt != null) {
17913                 out.writeInt(1);
17914                 out.writeString(ent.getKey());
17915                 rpmt.writeSummaryFromParcelLocked(out, nowRealtime);
17916             } else {
17917                 out.writeInt(0);
17918             }
17919         }
17920         out.writeInt(mScreenOffRpmStats.size());
17921         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
17922             Timer rpmt = ent.getValue();
17923             if (rpmt != null) {
17924                 out.writeInt(1);
17925                 out.writeString(ent.getKey());
17926                 rpmt.writeSummaryFromParcelLocked(out, nowRealtime);
17927             } else {
17928                 out.writeInt(0);
17929             }
17930         }
17931 
17932         out.writeInt(mKernelWakelockStats.size());
17933         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
17934             Timer kwlt = ent.getValue();
17935             if (kwlt != null) {
17936                 out.writeInt(1);
17937                 out.writeString(ent.getKey());
17938                 kwlt.writeSummaryFromParcelLocked(out, nowRealtime);
17939             } else {
17940                 out.writeInt(0);
17941             }
17942         }
17943 
17944         out.writeInt(mWakeupReasonStats.size());
17945         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
17946             SamplingTimer timer = ent.getValue();
17947             if (timer != null) {
17948                 out.writeInt(1);
17949                 out.writeString(ent.getKey());
17950                 timer.writeSummaryFromParcelLocked(out, nowRealtime);
17951             } else {
17952                 out.writeInt(0);
17953             }
17954         }
17955 
17956         out.writeInt(mKernelMemoryStats.size());
17957         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
17958             Timer kmt = mKernelMemoryStats.valueAt(i);
17959             if (kmt != null) {
17960                 out.writeInt(1);
17961                 out.writeLong(mKernelMemoryStats.keyAt(i));
17962                 kmt.writeSummaryFromParcelLocked(out, nowRealtime);
17963             } else {
17964                 out.writeInt(0);
17965             }
17966         }
17967 
17968         final int NU = mUidStats.size();
17969         out.writeInt(NU);
17970         for (int iu = 0; iu < NU; iu++) {
17971             out.writeInt(mUidStats.keyAt(iu));
17972             Uid u = mUidStats.valueAt(iu);
17973 
17974             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
17975             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, nowUptime,
17976                     nowRealtime);
17977 
17978             if (u.mWifiRunningTimer != null) {
17979                 out.writeInt(1);
17980                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17981             } else {
17982                 out.writeInt(0);
17983             }
17984             if (u.mFullWifiLockTimer != null) {
17985                 out.writeInt(1);
17986                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17987             } else {
17988                 out.writeInt(0);
17989             }
17990             if (u.mWifiScanTimer != null) {
17991                 out.writeInt(1);
17992                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17993             } else {
17994                 out.writeInt(0);
17995             }
17996             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
17997                 if (u.mWifiBatchedScanTimer[i] != null) {
17998                     out.writeInt(1);
17999                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
18000                 } else {
18001                     out.writeInt(0);
18002                 }
18003             }
18004             if (u.mWifiMulticastTimer != null) {
18005                 out.writeInt(1);
18006                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18007             } else {
18008                 out.writeInt(0);
18009             }
18010             if (u.mAudioTurnedOnTimer != null) {
18011                 out.writeInt(1);
18012                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18013             } else {
18014                 out.writeInt(0);
18015             }
18016             if (u.mVideoTurnedOnTimer != null) {
18017                 out.writeInt(1);
18018                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18019             } else {
18020                 out.writeInt(0);
18021             }
18022             if (u.mFlashlightTurnedOnTimer != null) {
18023                 out.writeInt(1);
18024                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18025             } else {
18026                 out.writeInt(0);
18027             }
18028             if (u.mCameraTurnedOnTimer != null) {
18029                 out.writeInt(1);
18030                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18031             } else {
18032                 out.writeInt(0);
18033             }
18034             if (u.mForegroundActivityTimer != null) {
18035                 out.writeInt(1);
18036                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18037             } else {
18038                 out.writeInt(0);
18039             }
18040             if (u.mForegroundServiceTimer != null) {
18041                 out.writeInt(1);
18042                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18043             } else {
18044                 out.writeInt(0);
18045             }
18046             if (u.mAggregatedPartialWakelockTimer != null) {
18047                 out.writeInt(1);
18048                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18049             } else {
18050                 out.writeInt(0);
18051             }
18052             if (u.mBluetoothScanTimer != null) {
18053                 out.writeInt(1);
18054                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18055             } else {
18056                 out.writeInt(0);
18057             }
18058             if (u.mBluetoothUnoptimizedScanTimer != null) {
18059                 out.writeInt(1);
18060                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18061             } else {
18062                 out.writeInt(0);
18063             }
18064             if (u.mBluetoothScanResultCounter != null) {
18065                 out.writeInt(1);
18066                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
18067             } else {
18068                 out.writeInt(0);
18069             }
18070             if (u.mBluetoothScanResultBgCounter != null) {
18071                 out.writeInt(1);
18072                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
18073             } else {
18074                 out.writeInt(0);
18075             }
18076             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
18077                 if (u.mProcessStateTimer[i] != null) {
18078                     out.writeInt(1);
18079                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
18080                 } else {
18081                     out.writeInt(0);
18082                 }
18083             }
18084             if (u.mVibratorOnTimer != null) {
18085                 out.writeInt(1);
18086                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18087             } else {
18088                 out.writeInt(0);
18089             }
18090 
18091             if (u.mUserActivityCounters == null) {
18092                 out.writeInt(0);
18093             } else {
18094                 out.writeInt(1);
18095                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
18096                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
18097                 }
18098             }
18099 
18100             if (u.mNetworkByteActivityCounters == null) {
18101                 out.writeInt(0);
18102             } else {
18103                 out.writeInt(1);
18104                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
18105                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
18106                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
18107                 }
18108                 if (u.mMobileRadioActiveTime != null) {
18109                     out.writeBoolean(true);
18110                     u.mMobileRadioActiveTime.writeToParcel(out);
18111                 } else {
18112                     out.writeBoolean(false);
18113                 }
18114                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
18115             }
18116 
18117             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
18118             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
18119 
18120             if (u.mCpuClusterSpeedTimesUs != null) {
18121                 out.writeInt(1);
18122                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
18123                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
18124                     if (cpuSpeeds != null) {
18125                         out.writeInt(1);
18126                         out.writeInt(cpuSpeeds.length);
18127                         for (LongSamplingCounter c : cpuSpeeds) {
18128                             if (c != null) {
18129                                 out.writeInt(1);
18130                                 c.writeSummaryFromParcelLocked(out);
18131                             } else {
18132                                 out.writeInt(0);
18133                             }
18134                         }
18135                     } else {
18136                         out.writeInt(0);
18137                     }
18138                 }
18139             } else {
18140                 out.writeInt(0);
18141             }
18142 
18143             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
18144             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
18145 
18146             if (u.mCpuActiveTimeMs != null) {
18147                 out.writeInt(u.mCpuActiveTimeMs.getStateCount());
18148                 u.mCpuActiveTimeMs.writeToParcel(out);
18149             } else {
18150                 out.writeInt(0);
18151             }
18152 
18153             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
18154 
18155             if (u.mProcStateTimeMs != null) {
18156                 out.writeInt(u.mProcStateTimeMs.getStateCount());
18157                 u.mProcStateTimeMs.writeToParcel(out);
18158             } else {
18159                 out.writeInt(0);
18160             }
18161 
18162             if (u.mProcStateScreenOffTimeMs != null) {
18163                 out.writeInt(u.mProcStateScreenOffTimeMs.getStateCount());
18164                 u.mProcStateScreenOffTimeMs.writeToParcel(out);
18165             } else {
18166                 out.writeInt(0);
18167             }
18168 
18169             if (u.mMobileRadioApWakeupCount != null) {
18170                 out.writeInt(1);
18171                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
18172             } else {
18173                 out.writeInt(0);
18174             }
18175 
18176             if (u.mWifiRadioApWakeupCount != null) {
18177                 out.writeInt(1);
18178                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
18179             } else {
18180                 out.writeInt(0);
18181             }
18182 
18183             MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out);
18184 
18185             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
18186             int NW = wakeStats.size();
18187             out.writeInt(NW);
18188             for (int iw=0; iw<NW; iw++) {
18189                 out.writeString(wakeStats.keyAt(iw));
18190                 Uid.Wakelock wl = wakeStats.valueAt(iw);
18191                 if (wl.mTimerFull != null) {
18192                     out.writeInt(1);
18193                     wl.mTimerFull.writeSummaryFromParcelLocked(out, nowRealtime);
18194                 } else {
18195                     out.writeInt(0);
18196                 }
18197                 if (wl.mTimerPartial != null) {
18198                     out.writeInt(1);
18199                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, nowRealtime);
18200                 } else {
18201                     out.writeInt(0);
18202                 }
18203                 if (wl.mTimerWindow != null) {
18204                     out.writeInt(1);
18205                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, nowRealtime);
18206                 } else {
18207                     out.writeInt(0);
18208                 }
18209                 if (wl.mTimerDraw != null) {
18210                     out.writeInt(1);
18211                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, nowRealtime);
18212                 } else {
18213                     out.writeInt(0);
18214                 }
18215             }
18216 
18217             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
18218             int NS = syncStats.size();
18219             out.writeInt(NS);
18220             for (int is=0; is<NS; is++) {
18221                 out.writeString(syncStats.keyAt(is));
18222                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, nowRealtime);
18223             }
18224 
18225             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
18226             int NJ = jobStats.size();
18227             out.writeInt(NJ);
18228             for (int ij=0; ij<NJ; ij++) {
18229                 out.writeString(jobStats.keyAt(ij));
18230                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, nowRealtime);
18231             }
18232 
18233             u.writeJobCompletionsToParcelLocked(out);
18234 
18235             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
18236             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
18237             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
18238             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
18239                 if (u.mJobsFreshnessBuckets[i] != null) {
18240                     out.writeInt(1);
18241                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
18242                 } else {
18243                     out.writeInt(0);
18244                 }
18245             }
18246 
18247             int NSE = u.mSensorStats.size();
18248             out.writeInt(NSE);
18249             for (int ise=0; ise<NSE; ise++) {
18250                 out.writeInt(u.mSensorStats.keyAt(ise));
18251                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
18252                 if (se.mTimer != null) {
18253                     out.writeInt(1);
18254                     se.mTimer.writeSummaryFromParcelLocked(out, nowRealtime);
18255                 } else {
18256                     out.writeInt(0);
18257                 }
18258             }
18259 
18260             int NP = u.mProcessStats.size();
18261             out.writeInt(NP);
18262             for (int ip=0; ip<NP; ip++) {
18263                 out.writeString(u.mProcessStats.keyAt(ip));
18264                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
18265                 out.writeLong(ps.mUserTimeMs);
18266                 out.writeLong(ps.mSystemTimeMs);
18267                 out.writeLong(ps.mForegroundTimeMs);
18268                 out.writeInt(ps.mStarts);
18269                 out.writeInt(ps.mNumCrashes);
18270                 out.writeInt(ps.mNumAnrs);
18271                 ps.writeExcessivePowerToParcelLocked(out);
18272             }
18273 
18274             NP = u.mPackageStats.size();
18275             out.writeInt(NP);
18276             if (NP > 0) {
18277                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
18278                     : u.mPackageStats.entrySet()) {
18279                     out.writeString(ent.getKey());
18280                     Uid.Pkg ps = ent.getValue();
18281                     final int NWA = ps.mWakeupAlarms.size();
18282                     out.writeInt(NWA);
18283                     for (int iwa=0; iwa<NWA; iwa++) {
18284                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
18285                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
18286                     }
18287                     NS = ps.mServiceStats.size();
18288                     out.writeInt(NS);
18289                     for (int is=0; is<NS; is++) {
18290                         out.writeString(ps.mServiceStats.keyAt(is));
18291                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
18292                         long time = ss.getStartTimeToNowLocked(
18293                                 mOnBatteryTimeBase.getUptime(nowUptime) / 1000);
18294                         out.writeLong(time);
18295                         out.writeInt(ss.mStarts);
18296                         out.writeInt(ss.mLaunches);
18297                     }
18298                 }
18299             }
18300         }
18301 
18302         LongSamplingCounterArray.writeSummaryToParcelLocked(out, mBinderThreadCpuTimesUs);
18303     }
18304 
18305     @GuardedBy("this")
18306     public void readFromParcel(Parcel in) {
18307         readFromParcelLocked(in);
18308     }
18309 
18310     @GuardedBy("this")
18311     @SuppressWarnings("GuardedBy")  // errorprone false positive on u.readFromParcelLocked
18312     void readFromParcelLocked(Parcel in) {
18313         int magic = in.readInt();
18314         if (magic != MAGIC) {
18315             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
18316         }
18317 
18318         readHistoryBuffer(in);
18319         mBatteryStatsHistory.readFromParcel(in);
18320 
18321         mStartCount = in.readInt();
18322         mStartClockTimeMs = in.readLong();
18323         mStartPlatformVersion = in.readString();
18324         mEndPlatformVersion = in.readString();
18325         mUptimeUs = in.readLong();
18326         mUptimeStartUs = in.readLong();
18327         mRealtimeUs = in.readLong();
18328         mRealtimeStartUs = in.readLong();
18329         mOnBattery = in.readInt() != 0;
18330         mEstimatedBatteryCapacityMah = in.readInt();
18331         mLastLearnedBatteryCapacityUah = in.readInt();
18332         mMinLearnedBatteryCapacityUah = in.readInt();
18333         mMaxLearnedBatteryCapacityUah = in.readInt();
18334         mOnBatteryInternal = false; // we are no longer really running.
18335         mOnBatteryTimeBase.readFromParcel(in);
18336         mOnBatteryScreenOffTimeBase.readFromParcel(in);
18337 
18338         mScreenState = Display.STATE_UNKNOWN;
18339         mScreenOnTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase, in);
18340         mScreenDozeTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase, in);
18341         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
18342             mScreenBrightnessTimer[i] = new StopwatchTimer(mClock, null, -100 - i, null,
18343                     mOnBatteryTimeBase, in);
18344         }
18345         mInteractive = false;
18346         mInteractiveTimer = new StopwatchTimer(mClock, null, -10, null, mOnBatteryTimeBase, in);
18347         mPhoneOn = false;
18348         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClock, null, -2, null,
18349                 mOnBatteryTimeBase, in);
18350         mLongestLightIdleTimeMs = in.readLong();
18351         mLongestFullIdleTimeMs = in.readLong();
18352         mDeviceIdleModeLightTimer = new StopwatchTimer(mClock, null, -14, null,
18353                 mOnBatteryTimeBase, in);
18354         mDeviceIdleModeFullTimer = new StopwatchTimer(mClock, null, -11, null,
18355                 mOnBatteryTimeBase, in);
18356         mDeviceLightIdlingTimer = new StopwatchTimer(mClock, null, -15, null,
18357                 mOnBatteryTimeBase, in);
18358         mDeviceIdlingTimer = new StopwatchTimer(mClock, null, -12, null, mOnBatteryTimeBase, in);
18359         mPhoneOnTimer = new StopwatchTimer(mClock, null, -3, null, mOnBatteryTimeBase, in);
18360         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
18361             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -200 - i,
18362                     null, mOnBatteryTimeBase, in);
18363         }
18364         mPhoneSignalScanningTimer = new StopwatchTimer(mClock, null, -200 + 1, null,
18365                 mOnBatteryTimeBase, in);
18366         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
18367             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClock, null, -300 - i,
18368                     null, mOnBatteryTimeBase, in);
18369         }
18370         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
18371             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
18372             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
18373         }
18374         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
18375         mMobileRadioActiveTimer = new StopwatchTimer(mClock, null, -400, null,
18376                 mOnBatteryTimeBase, in);
18377         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClock, null, -401, null,
18378                 mOnBatteryTimeBase, in);
18379         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
18380         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
18381         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
18382         mWifiMulticastWakelockTimer = new StopwatchTimer(mClock, null, -4, null,
18383                 mOnBatteryTimeBase, in);
18384         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
18385         mWifiOn = false;
18386         mWifiOnTimer = new StopwatchTimer(mClock, null, -4, null, mOnBatteryTimeBase, in);
18387         mGlobalWifiRunning = false;
18388         mGlobalWifiRunningTimer = new StopwatchTimer(mClock, null, -5, null,
18389                 mOnBatteryTimeBase, in);
18390         for (int i=0; i<NUM_WIFI_STATES; i++) {
18391             mWifiStateTimer[i] = new StopwatchTimer(mClock, null, -600 - i,
18392                     null, mOnBatteryTimeBase, in);
18393         }
18394         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
18395             mWifiSupplStateTimer[i] = new StopwatchTimer(mClock, null, -700 - i,
18396                     null, mOnBatteryTimeBase, in);
18397         }
18398         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
18399             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -800 - i,
18400                     null, mOnBatteryTimeBase, in);
18401         }
18402         mWifiActiveTimer = new StopwatchTimer(mClock, null, -900, null,
18403             mOnBatteryTimeBase, in);
18404         mWifiActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
18405                 NUM_WIFI_TX_LEVELS, in);
18406         for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
18407             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClock, null, -1000 - i,
18408                 null, mOnBatteryTimeBase, in);
18409         }
18410         mBluetoothActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
18411                 NUM_BT_TX_LEVELS, in);
18412         mModemActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
18413                 ModemActivityInfo.getNumTxPowerLevels(), in);
18414         mHasWifiReporting = in.readInt() != 0;
18415         mHasBluetoothReporting = in.readInt() != 0;
18416         mHasModemReporting = in.readInt() != 0;
18417 
18418         mNumConnectivityChange = in.readInt();
18419         mAudioOnNesting = 0;
18420         // TODO: It's likely a mistake that mAudioOnTimer/mVideoOnTimer don't write/read to parcel!
18421         mAudioOnTimer = new StopwatchTimer(mClock, null, -7, null, mOnBatteryTimeBase);
18422         mVideoOnNesting = 0;
18423         mVideoOnTimer = new StopwatchTimer(mClock, null, -8, null, mOnBatteryTimeBase);
18424         mFlashlightOnNesting = 0;
18425         mFlashlightOnTimer = new StopwatchTimer(mClock, null, -9, null, mOnBatteryTimeBase, in);
18426         mCameraOnNesting = 0;
18427         mCameraOnTimer = new StopwatchTimer(mClock, null, -13, null, mOnBatteryTimeBase, in);
18428         mBluetoothScanNesting = 0;
18429         mBluetoothScanTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase, in);
18430         mDischargeUnplugLevel = in.readInt();
18431         mDischargePlugLevel = in.readInt();
18432         mDischargeCurrentLevel = in.readInt();
18433         mCurrentBatteryLevel = in.readInt();
18434         mLowDischargeAmountSinceCharge = in.readInt();
18435         mHighDischargeAmountSinceCharge = in.readInt();
18436         mDischargeAmountScreenOn = in.readInt();
18437         mDischargeAmountScreenOnSinceCharge = in.readInt();
18438         mDischargeAmountScreenOff = in.readInt();
18439         mDischargeAmountScreenOffSinceCharge = in.readInt();
18440         mDischargeAmountScreenDoze = in.readInt();
18441         mDischargeAmountScreenDozeSinceCharge = in.readInt();
18442         mDischargeStepTracker.readFromParcel(in);
18443         mChargeStepTracker.readFromParcel(in);
18444         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
18445         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
18446         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
18447         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
18448         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
18449         mLastWriteTimeMs = in.readLong();
18450         mBatteryTimeToFullSeconds = in.readLong();
18451 
18452 
18453         final MeasuredEnergyStats.Config config = MeasuredEnergyStats.Config.createFromParcel(in);
18454         final MeasuredEnergyStats measuredEnergyStats =
18455                 MeasuredEnergyStats.createFromParcel(mMeasuredEnergyStatsConfig, in);
18456         if (config != null && Arrays.equals(config.getStateNames(),
18457                 getBatteryConsumerProcessStateNames())) {
18458             mMeasuredEnergyStatsConfig = config;
18459             mGlobalMeasuredEnergyStats = measuredEnergyStats;
18460         }
18461 
18462         mRpmStats.clear();
18463         int NRPMS = in.readInt();
18464         for (int irpm = 0; irpm < NRPMS; irpm++) {
18465             if (in.readInt() != 0) {
18466                 String rpmName = in.readString();
18467                 SamplingTimer rpmt = new SamplingTimer(mClock, mOnBatteryTimeBase, in);
18468                 mRpmStats.put(rpmName, rpmt);
18469             }
18470         }
18471         mScreenOffRpmStats.clear();
18472         int NSORPMS = in.readInt();
18473         for (int irpm = 0; irpm < NSORPMS; irpm++) {
18474             if (in.readInt() != 0) {
18475                 String rpmName = in.readString();
18476                 SamplingTimer rpmt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase, in);
18477                 mScreenOffRpmStats.put(rpmName, rpmt);
18478             }
18479         }
18480 
18481         mKernelWakelockStats.clear();
18482         int NKW = in.readInt();
18483         for (int ikw = 0; ikw < NKW; ikw++) {
18484             if (in.readInt() != 0) {
18485                 String wakelockName = in.readString();
18486                 SamplingTimer kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase, in);
18487                 mKernelWakelockStats.put(wakelockName, kwlt);
18488             }
18489         }
18490 
18491         mWakeupReasonStats.clear();
18492         int NWR = in.readInt();
18493         for (int iwr = 0; iwr < NWR; iwr++) {
18494             if (in.readInt() != 0) {
18495                 String reasonName = in.readString();
18496                 SamplingTimer timer = new SamplingTimer(mClock, mOnBatteryTimeBase, in);
18497                 mWakeupReasonStats.put(reasonName, timer);
18498             }
18499         }
18500 
18501         mKernelMemoryStats.clear();
18502         int nmt = in.readInt();
18503         for (int imt = 0; imt < nmt; imt++) {
18504             if (in.readInt() != 0) {
18505                 Long bucket = in.readLong();
18506                 SamplingTimer kmt = new SamplingTimer(mClock, mOnBatteryTimeBase, in);
18507                 mKernelMemoryStats.put(bucket, kmt);
18508             }
18509         }
18510 
18511         mPartialTimers.clear();
18512         mFullTimers.clear();
18513         mWindowTimers.clear();
18514         mWifiRunningTimers.clear();
18515         mFullWifiLockTimers.clear();
18516         mWifiScanTimers.clear();
18517         mWifiBatchedScanTimers.clear();
18518         mWifiMulticastTimers.clear();
18519         mAudioTurnedOnTimers.clear();
18520         mVideoTurnedOnTimers.clear();
18521         mFlashlightTurnedOnTimers.clear();
18522         mCameraTurnedOnTimers.clear();
18523 
18524         int numUids = in.readInt();
18525         mUidStats.clear();
18526         final long elapsedRealtimeMs = mClock.elapsedRealtime();
18527         final long uptimeMs = mClock.uptimeMillis();
18528         for (int i = 0; i < numUids; i++) {
18529             int uid = in.readInt();
18530             Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
18531             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase,
18532                     in);
18533             mUidStats.append(uid, u);
18534         }
18535 
18536         mBinderThreadCpuTimesUs = LongSamplingCounterArray.readFromParcel(in, mOnBatteryTimeBase);
18537     }
18538 
18539     @GuardedBy("this")
18540     public void writeToParcel(Parcel out, int flags) {
18541         writeToParcelLocked(out, true, flags);
18542     }
18543 
18544     @GuardedBy("this")
18545     public void writeToParcelWithoutUids(Parcel out, int flags) {
18546         writeToParcelLocked(out, false, flags);
18547     }
18548 
18549     @SuppressWarnings("unused")
18550     @GuardedBy("this")
18551     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
18552         // Need to update with current kernel wake lock counts.
18553         pullPendingStateUpdatesLocked();
18554 
18555         updateSystemServiceCallStats();
18556 
18557         // Pull the clock time.  This may update the time and make a new history entry
18558         // if we had originally pulled a time before the RTC was set.
18559         getStartClockTime();
18560 
18561         final long uSecUptime = mClock.uptimeMillis() * 1000;
18562         final long uSecRealtime = mClock.elapsedRealtime() * 1000;
18563         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
18564         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
18565 
18566         out.writeInt(MAGIC);
18567 
18568         writeHistoryBuffer(out, true);
18569         mBatteryStatsHistory.writeToParcel(out);
18570 
18571         out.writeInt(mStartCount);
18572         out.writeLong(mStartClockTimeMs);
18573         out.writeString(mStartPlatformVersion);
18574         out.writeString(mEndPlatformVersion);
18575         out.writeLong(mUptimeUs);
18576         out.writeLong(mUptimeStartUs);
18577         out.writeLong(mRealtimeUs);
18578         out.writeLong(mRealtimeStartUs);
18579         out.writeInt(mOnBattery ? 1 : 0);
18580         out.writeInt(mEstimatedBatteryCapacityMah);
18581         out.writeInt(mLastLearnedBatteryCapacityUah);
18582         out.writeInt(mMinLearnedBatteryCapacityUah);
18583         out.writeInt(mMaxLearnedBatteryCapacityUah);
18584         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
18585         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
18586 
18587         mScreenOnTimer.writeToParcel(out, uSecRealtime);
18588         mScreenDozeTimer.writeToParcel(out, uSecRealtime);
18589         for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
18590             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
18591         }
18592         mInteractiveTimer.writeToParcel(out, uSecRealtime);
18593         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
18594         out.writeLong(mLongestLightIdleTimeMs);
18595         out.writeLong(mLongestFullIdleTimeMs);
18596         mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
18597         mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
18598         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
18599         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
18600         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
18601         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
18602             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
18603         }
18604         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
18605         for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; i++) {
18606             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
18607         }
18608         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
18609             mNetworkByteActivityCounters[i].writeToParcel(out);
18610             mNetworkPacketActivityCounters[i].writeToParcel(out);
18611         }
18612         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
18613         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
18614         mMobileRadioActiveAdjustedTime.writeToParcel(out);
18615         mMobileRadioActiveUnknownTime.writeToParcel(out);
18616         mMobileRadioActiveUnknownCount.writeToParcel(out);
18617         mWifiMulticastWakelockTimer.writeToParcel(out, uSecRealtime);
18618         mWifiOnTimer.writeToParcel(out, uSecRealtime);
18619         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
18620         for (int i = 0; i < NUM_WIFI_STATES; i++) {
18621             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
18622         }
18623         for (int i = 0; i < NUM_WIFI_SUPPL_STATES; i++) {
18624             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
18625         }
18626         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
18627             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
18628         }
18629         mWifiActiveTimer.writeToParcel(out, uSecRealtime);
18630         mWifiActivity.writeToParcel(out, 0);
18631         for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
18632             mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
18633         }
18634         mBluetoothActivity.writeToParcel(out, 0);
18635         mModemActivity.writeToParcel(out, 0);
18636         out.writeInt(mHasWifiReporting ? 1 : 0);
18637         out.writeInt(mHasBluetoothReporting ? 1 : 0);
18638         out.writeInt(mHasModemReporting ? 1 : 0);
18639 
18640         out.writeInt(mNumConnectivityChange);
18641         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
18642         mCameraOnTimer.writeToParcel(out, uSecRealtime);
18643         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
18644         out.writeInt(mDischargeUnplugLevel);
18645         out.writeInt(mDischargePlugLevel);
18646         out.writeInt(mDischargeCurrentLevel);
18647         out.writeInt(mCurrentBatteryLevel);
18648         out.writeInt(mLowDischargeAmountSinceCharge);
18649         out.writeInt(mHighDischargeAmountSinceCharge);
18650         out.writeInt(mDischargeAmountScreenOn);
18651         out.writeInt(mDischargeAmountScreenOnSinceCharge);
18652         out.writeInt(mDischargeAmountScreenOff);
18653         out.writeInt(mDischargeAmountScreenOffSinceCharge);
18654         out.writeInt(mDischargeAmountScreenDoze);
18655         out.writeInt(mDischargeAmountScreenDozeSinceCharge);
18656         mDischargeStepTracker.writeToParcel(out);
18657         mChargeStepTracker.writeToParcel(out);
18658         mDischargeCounter.writeToParcel(out);
18659         mDischargeScreenOffCounter.writeToParcel(out);
18660         mDischargeScreenDozeCounter.writeToParcel(out);
18661         mDischargeLightDozeCounter.writeToParcel(out);
18662         mDischargeDeepDozeCounter.writeToParcel(out);
18663         out.writeLong(mLastWriteTimeMs);
18664         out.writeLong(mBatteryTimeToFullSeconds);
18665 
18666         MeasuredEnergyStats.Config.writeToParcel(mMeasuredEnergyStatsConfig, out);
18667 
18668         if (mGlobalMeasuredEnergyStats != null) {
18669             out.writeInt(1);
18670             mGlobalMeasuredEnergyStats.writeToParcel(out);
18671         } else {
18672             out.writeInt(0);
18673         }
18674 
18675         out.writeInt(mRpmStats.size());
18676         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
18677             SamplingTimer rpmt = ent.getValue();
18678             if (rpmt != null) {
18679                 out.writeInt(1);
18680                 out.writeString(ent.getKey());
18681                 rpmt.writeToParcel(out, uSecRealtime);
18682             } else {
18683                 out.writeInt(0);
18684             }
18685         }
18686         out.writeInt(mScreenOffRpmStats.size());
18687         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
18688             SamplingTimer rpmt = ent.getValue();
18689             if (rpmt != null) {
18690                 out.writeInt(1);
18691                 out.writeString(ent.getKey());
18692                 rpmt.writeToParcel(out, uSecRealtime);
18693             } else {
18694                 out.writeInt(0);
18695             }
18696         }
18697 
18698         if (inclUids) {
18699             out.writeInt(mKernelWakelockStats.size());
18700             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
18701                 SamplingTimer kwlt = ent.getValue();
18702                 if (kwlt != null) {
18703                     out.writeInt(1);
18704                     out.writeString(ent.getKey());
18705                     kwlt.writeToParcel(out, uSecRealtime);
18706                 } else {
18707                     out.writeInt(0);
18708                 }
18709             }
18710             out.writeInt(mWakeupReasonStats.size());
18711             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
18712                 SamplingTimer timer = ent.getValue();
18713                 if (timer != null) {
18714                     out.writeInt(1);
18715                     out.writeString(ent.getKey());
18716                     timer.writeToParcel(out, uSecRealtime);
18717                 } else {
18718                     out.writeInt(0);
18719                 }
18720             }
18721         } else {
18722             out.writeInt(0);
18723             out.writeInt(0);
18724         }
18725 
18726         out.writeInt(mKernelMemoryStats.size());
18727         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
18728             SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
18729             if (kmt != null) {
18730                 out.writeInt(1);
18731                 out.writeLong(mKernelMemoryStats.keyAt(i));
18732                 kmt.writeToParcel(out, uSecRealtime);
18733             } else {
18734                 out.writeInt(0);
18735             }
18736         }
18737 
18738         if (inclUids) {
18739             int size = mUidStats.size();
18740             out.writeInt(size);
18741             for (int i = 0; i < size; i++) {
18742                 out.writeInt(mUidStats.keyAt(i));
18743                 Uid uid = mUidStats.valueAt(i);
18744 
18745                 uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
18746             }
18747         } else {
18748             out.writeInt(0);
18749         }
18750         LongSamplingCounterArray.writeToParcel(out, mBinderThreadCpuTimesUs);
18751     }
18752 
18753     private void writeCpuSpeedCountersToParcel(Parcel out, LongSamplingCounter[][] counters) {
18754         if (counters == null) {
18755             out.writeInt(0);
18756             return;
18757         }
18758 
18759         out.writeInt(1);
18760         out.writeInt(counters.length);
18761         for (int i = 0; i < counters.length; i++) {
18762             LongSamplingCounter[] counterArray = counters[i];
18763             if (counterArray == null) {
18764                 out.writeInt(0);
18765                 continue;
18766             }
18767 
18768             out.writeInt(1);
18769             out.writeInt(counterArray.length);
18770             for (int j = 0; j < counterArray.length; j++) {
18771                 LongSamplingCounter c = counterArray[j];
18772                 if (c != null) {
18773                     out.writeInt(1);
18774                     c.writeToParcel(out);
18775                 } else {
18776                     out.writeInt(0);
18777                 }
18778             }
18779         }
18780     }
18781 
18782     private LongSamplingCounter[][] readCpuSpeedCountersFromParcel(Parcel in) {
18783         LongSamplingCounter[][] counters;
18784         if (in.readInt() != 0) {
18785             int numCpuClusters = in.readInt();
18786             if (mPowerProfile != null
18787                     && mPowerProfile.getNumCpuClusters() != numCpuClusters) {
18788                 throw new ParcelFormatException("Incompatible number of cpu clusters");
18789             }
18790 
18791             counters = new LongSamplingCounter[numCpuClusters][];
18792             for (int cluster = 0; cluster < numCpuClusters; cluster++) {
18793                 if (in.readInt() != 0) {
18794                     int numSpeeds = in.readInt();
18795                     if (mPowerProfile != null
18796                             && mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
18797                         throw new ParcelFormatException("Incompatible number of cpu speeds");
18798                     }
18799 
18800                     final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
18801                     counters[cluster] = cpuSpeeds;
18802                     for (int speed = 0; speed < numSpeeds; speed++) {
18803                         if (in.readInt() != 0) {
18804                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase, in);
18805                         }
18806                     }
18807                 } else {
18808                     counters[cluster] = null;
18809                 }
18810             }
18811         } else {
18812             counters = null;
18813         }
18814 
18815         return counters;
18816     }
18817 
18818     @UnsupportedAppUsage
18819     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
18820         new Parcelable.Creator<BatteryStatsImpl>() {
18821         public BatteryStatsImpl createFromParcel(Parcel in) {
18822             return new BatteryStatsImpl(in);
18823         }
18824 
18825         public BatteryStatsImpl[] newArray(int size) {
18826             return new BatteryStatsImpl[size];
18827         }
18828     };
18829 
18830     @GuardedBy("this")
18831     public void prepareForDumpLocked() {
18832         // Need to retrieve current kernel wake lock stats before printing.
18833         pullPendingStateUpdatesLocked();
18834 
18835         // Pull the clock time.  This may update the time and make a new history entry
18836         // if we had originally pulled a time before the RTC was set.
18837         getStartClockTime();
18838 
18839         updateSystemServiceCallStats();
18840     }
18841 
18842     @GuardedBy("this")
18843     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
18844         if (DEBUG) {
18845             pw.println("mOnBatteryTimeBase:");
18846             mOnBatteryTimeBase.dump(pw, "  ");
18847             pw.println("mOnBatteryScreenOffTimeBase:");
18848             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
18849             Printer pr = new PrintWriterPrinter(pw);
18850             pr.println("*** Screen on timer:");
18851             mScreenOnTimer.logState(pr, "  ");
18852             pr.println("*** Screen doze timer:");
18853             mScreenDozeTimer.logState(pr, "  ");
18854             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
18855                 pr.println("*** Screen brightness #" + i + ":");
18856                 mScreenBrightnessTimer[i].logState(pr, "  ");
18857             }
18858             pr.println("*** Interactive timer:");
18859             mInteractiveTimer.logState(pr, "  ");
18860             pr.println("*** Power save mode timer:");
18861             mPowerSaveModeEnabledTimer.logState(pr, "  ");
18862             pr.println("*** Device idle mode light timer:");
18863             mDeviceIdleModeLightTimer.logState(pr, "  ");
18864             pr.println("*** Device idle mode full timer:");
18865             mDeviceIdleModeFullTimer.logState(pr, "  ");
18866             pr.println("*** Device light idling timer:");
18867             mDeviceLightIdlingTimer.logState(pr, "  ");
18868             pr.println("*** Device idling timer:");
18869             mDeviceIdlingTimer.logState(pr, "  ");
18870             pr.println("*** Phone timer:");
18871             mPhoneOnTimer.logState(pr, "  ");
18872             for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
18873                 pr.println("*** Phone signal strength #" + i + ":");
18874                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
18875             }
18876             pr.println("*** Signal scanning :");
18877             mPhoneSignalScanningTimer.logState(pr, "  ");
18878             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
18879                 pr.println("*** Data connection type #" + i + ":");
18880                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
18881             }
18882             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
18883             pr.println("*** Mobile network active timer:");
18884             mMobileRadioActiveTimer.logState(pr, "  ");
18885             pr.println("*** Mobile network active adjusted timer:");
18886             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
18887             pr.println("*** Wifi Multicast WakeLock Timer:");
18888             mWifiMulticastWakelockTimer.logState(pr, "  ");
18889             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
18890             pr.println("*** Wifi timer:");
18891             mWifiOnTimer.logState(pr, "  ");
18892             pr.println("*** WifiRunning timer:");
18893             mGlobalWifiRunningTimer.logState(pr, "  ");
18894             for (int i=0; i<NUM_WIFI_STATES; i++) {
18895                 pr.println("*** Wifi state #" + i + ":");
18896                 mWifiStateTimer[i].logState(pr, "  ");
18897             }
18898             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
18899                 pr.println("*** Wifi suppl state #" + i + ":");
18900                 mWifiSupplStateTimer[i].logState(pr, "  ");
18901             }
18902             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
18903                 pr.println("*** Wifi signal strength #" + i + ":");
18904                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
18905             }
18906             for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
18907                 pr.println("*** GPS signal quality #" + i + ":");
18908                 mGpsSignalQualityTimer[i].logState(pr, "  ");
18909             }
18910             pr.println("*** Flashlight timer:");
18911             mFlashlightOnTimer.logState(pr, "  ");
18912             pr.println("*** Camera timer:");
18913             mCameraOnTimer.logState(pr, "  ");
18914         }
18915         super.dumpLocked(context, pw, flags, reqUid, histStart);
18916 
18917         pw.print("Per process state tracking available: ");
18918         pw.println(trackPerProcStateCpuTimes());
18919         pw.print("Total cpu time reads: ");
18920         pw.println(mNumSingleUidCpuTimeReads);
18921         pw.print("Batching Duration (min): ");
18922         pw.println((mClock.uptimeMillis() - mCpuTimeReadsTrackingStartTimeMs) / (60 * 1000));
18923         pw.print("All UID cpu time reads since the later of device start or stats reset: ");
18924         pw.println(mNumAllUidCpuTimeReads);
18925         pw.print("UIDs removed since the later of device start or stats reset: ");
18926         pw.println(mNumUidsRemoved);
18927 
18928         pw.println("Currently mapped isolated uids:");
18929         final int numIsolatedUids = mIsolatedUids.size();
18930         for (int i = 0; i < numIsolatedUids; i++) {
18931             final int isolatedUid = mIsolatedUids.keyAt(i);
18932             final int ownerUid = mIsolatedUids.valueAt(i);
18933             final int refCount = mIsolatedUidRefCounts.get(isolatedUid);
18934             pw.println("  " + isolatedUid + "->" + ownerUid + " (ref count = " + refCount + ")");
18935         }
18936 
18937         pw.println();
18938         dumpConstantsLocked(pw);
18939 
18940         pw.println();
18941         dumpMeasuredEnergyStatsLocked(pw);
18942     }
18943 }
18944