• 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.server.power.stats;
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.BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS;
23 import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
24 import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
25 
26 import android.annotation.IntDef;
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.annotation.SuppressLint;
30 import android.app.ActivityManager;
31 import android.app.AlarmManager;
32 import android.app.usage.NetworkStatsManager;
33 import android.bluetooth.BluetoothActivityEnergyInfo;
34 import android.bluetooth.BluetoothAdapter;
35 import android.bluetooth.BluetoothManager;
36 import android.bluetooth.UidTraffic;
37 import android.content.BroadcastReceiver;
38 import android.content.ContentResolver;
39 import android.content.Context;
40 import android.content.Intent;
41 import android.content.IntentFilter;
42 import android.content.pm.PackageManager;
43 import android.database.ContentObserver;
44 import android.hardware.usb.UsbManager;
45 import android.location.GnssSignalQuality;
46 import android.net.NetworkStats;
47 import android.net.Uri;
48 import android.net.wifi.WifiManager;
49 import android.os.BatteryConsumer;
50 import android.os.BatteryManager;
51 import android.os.BatteryStats;
52 import android.os.BatteryUsageStats;
53 import android.os.BatteryUsageStatsQuery;
54 import android.os.Binder;
55 import android.os.BluetoothBatteryStats;
56 import android.os.Build;
57 import android.os.ConditionVariable;
58 import android.os.Handler;
59 import android.os.IBatteryPropertiesRegistrar;
60 import android.os.Looper;
61 import android.os.Message;
62 import android.os.OsProtoEnums;
63 import android.os.Parcel;
64 import android.os.ParcelFormatException;
65 import android.os.Parcelable;
66 import android.os.PowerManager;
67 import android.os.Process;
68 import android.os.RemoteException;
69 import android.os.ServiceManager;
70 import android.os.SystemClock;
71 import android.os.UserHandle;
72 import android.os.WakeLockStats;
73 import android.os.WorkSource;
74 import android.os.WorkSource.WorkChain;
75 import android.os.connectivity.CellularBatteryStats;
76 import android.os.connectivity.GpsBatteryStats;
77 import android.os.connectivity.WifiActivityEnergyInfo;
78 import android.os.connectivity.WifiBatteryStats;
79 import android.power.PowerStatsInternal;
80 import android.provider.Settings;
81 import android.telephony.AccessNetworkConstants;
82 import android.telephony.Annotation.NetworkType;
83 import android.telephony.CellSignalStrength;
84 import android.telephony.CellSignalStrengthLte;
85 import android.telephony.CellSignalStrengthNr;
86 import android.telephony.DataConnectionRealTimeInfo;
87 import android.telephony.ModemActivityInfo;
88 import android.telephony.NetworkRegistrationInfo;
89 import android.telephony.ServiceState;
90 import android.telephony.ServiceState.RegState;
91 import android.telephony.SignalStrength;
92 import android.telephony.TelephonyManager;
93 import android.text.TextUtils;
94 import android.text.format.DateUtils;
95 import android.util.ArrayMap;
96 import android.util.ArraySet;
97 import android.util.AtomicFile;
98 import android.util.IndentingPrintWriter;
99 import android.util.KeyValueListParser;
100 import android.util.Log;
101 import android.util.LongSparseArray;
102 import android.util.LongSparseLongArray;
103 import android.util.MutableInt;
104 import android.util.PrintWriterPrinter;
105 import android.util.Printer;
106 import android.util.Slog;
107 import android.util.SparseArray;
108 import android.util.SparseBooleanArray;
109 import android.util.SparseDoubleArray;
110 import android.util.SparseIntArray;
111 import android.util.SparseLongArray;
112 import android.util.TimeUtils;
113 import android.util.Xml;
114 import android.view.Display;
115 
116 import com.android.internal.annotations.GuardedBy;
117 import com.android.internal.annotations.VisibleForTesting;
118 import com.android.internal.os.BackgroundThread;
119 import com.android.internal.os.BatteryStatsHistory;
120 import com.android.internal.os.BatteryStatsHistoryIterator;
121 import com.android.internal.os.BinderCallsStats;
122 import com.android.internal.os.BinderTransactionNameResolver;
123 import com.android.internal.os.Clock;
124 import com.android.internal.os.CpuScalingPolicies;
125 import com.android.internal.os.KernelCpuSpeedReader;
126 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
127 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
128 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
129 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
130 import com.android.internal.os.KernelMemoryBandwidthStats;
131 import com.android.internal.os.KernelSingleUidTimeReader;
132 import com.android.internal.os.LongArrayMultiStateCounter;
133 import com.android.internal.os.LongMultiStateCounter;
134 import com.android.internal.os.MonotonicClock;
135 import com.android.internal.os.PowerProfile;
136 import com.android.internal.os.PowerStats;
137 import com.android.internal.os.RailStats;
138 import com.android.internal.os.RpmStats;
139 import com.android.internal.power.EnergyConsumerStats;
140 import com.android.internal.power.EnergyConsumerStats.StandardPowerBucket;
141 import com.android.internal.util.ArrayUtils;
142 import com.android.internal.util.FrameworkStatsLog;
143 import com.android.internal.util.XmlUtils;
144 import com.android.modules.utils.TypedXmlPullParser;
145 import com.android.modules.utils.TypedXmlSerializer;
146 import com.android.server.LocalServices;
147 import com.android.server.power.feature.PowerManagerFlags;
148 import com.android.server.power.optimization.Flags;
149 import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
150 import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
151 
152 import libcore.util.EmptyArray;
153 
154 import org.xmlpull.v1.XmlPullParser;
155 import org.xmlpull.v1.XmlPullParserException;
156 
157 import java.io.ByteArrayOutputStream;
158 import java.io.File;
159 import java.io.FileInputStream;
160 import java.io.FileNotFoundException;
161 import java.io.FileOutputStream;
162 import java.io.IOException;
163 import java.io.PrintWriter;
164 import java.lang.annotation.Retention;
165 import java.lang.annotation.RetentionPolicy;
166 import java.util.ArrayList;
167 import java.util.Arrays;
168 import java.util.Calendar;
169 import java.util.Collection;
170 import java.util.HashMap;
171 import java.util.HashSet;
172 import java.util.Iterator;
173 import java.util.LinkedList;
174 import java.util.List;
175 import java.util.Map;
176 import java.util.Queue;
177 import java.util.concurrent.Executor;
178 import java.util.concurrent.TimeUnit;
179 import java.util.concurrent.atomic.AtomicInteger;
180 import java.util.concurrent.locks.ReentrantLock;
181 import java.util.function.LongSupplier;
182 import java.util.function.Supplier;
183 
184 /**
185  * All information we are collecting about things that can happen that impact
186  * battery life.  All times are represented in microseconds except where indicated
187  * otherwise.
188  */
189 public class BatteryStatsImpl extends BatteryStats {
190     private static final String TAG = "BatteryStatsImpl";
191     private static final boolean DEBUG = false;
192     public static final boolean DEBUG_ENERGY = false;
193     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
194     private static final boolean DEBUG_BINDER_STATS = false;
195     private static final boolean DEBUG_MEMORY = false;
196 
197     private static final String HISTORY_DIR = "battery-history";
198 
199     // TODO: remove "tcp" from network methods, since we measure total stats.
200 
201     // Current on-disk Parcel version. Must be updated when the format of the parcelable changes
202     public static final int VERSION =
203             !Flags.disableSystemServicePowerAttr() ? 214 : 215;
204 
205     // The maximum number of names wakelocks we will keep track of
206     // per uid; once the limit is reached, we batch the remaining wakelocks
207     // in to one common name.
208     private static final int MAX_WAKELOCKS_PER_UID = isLowRamDevice() ? 40 : 200;
209 
210     private static final int CELL_SIGNAL_STRENGTH_LEVEL_COUNT = getCellSignalStrengthLevelCount();
211 
212     private static final int MODEM_TX_POWER_LEVEL_COUNT = getModemTxPowerLevelCount();
213 
214     // Number of transmit power states the Wifi controller can be in.
215     private static final int NUM_WIFI_TX_LEVELS = 1;
216 
217     // Number of transmit power states the Bluetooth controller can be in.
218     private static final int NUM_BT_TX_LEVELS = 1;
219 
220     /**
221      * Holding a wakelock costs more than just using the cpu.
222      * Currently, we assign only half the cpu time to an app that is running but
223      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
224      * If no app is holding a wakelock, then the distribution is normal.
225      */
226     @VisibleForTesting
227     public static final int WAKE_LOCK_WEIGHT = 50;
228 
229     /**
230      * Minimum duration of a battery session. Attempt to automatically start a new
231      * session within this interval are ignored. Explicit resets (e.g. with an adb command) are
232      * not affected by this restriction.
233      */
234     private static final long MIN_BATTERY_SESSION_DURATION_MILLIS = 60000;
235 
236     public static final int RESET_REASON_CORRUPT_FILE = 1;
237     public static final int RESET_REASON_ADB_COMMAND = 2;
238     public static final int RESET_REASON_FULL_CHARGE = 3;
239     public static final int RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE = 4;
240     public static final int RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION = 5;
241 
242     @NonNull
243     private final MonotonicClock mMonotonicClock;
244 
245     protected Clock mClock;
246 
247     private final AtomicFile mStatsFile;
248     public final AtomicFile mCheckinFile;
249     public final AtomicFile mDailyFile;
250 
251     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
252     static final int MSG_REPORT_POWER_CHANGE = 2;
253     static final int MSG_REPORT_CHARGING = 3;
254     static final int MSG_REPORT_RESET_STATS = 4;
255     static final long DELAY_UPDATE_WAKELOCKS = 60 * 1000;
256 
257     private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
258     private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
259 
260     private static final LongCounter ZERO_LONG_COUNTER = new LongCounter() {
261         @Override
262         public long getCountLocked(int which) {
263             return 0;
264         }
265 
266         @Override
267         public long getCountForProcessState(int procState) {
268             return 0;
269         }
270 
271         @Override
272         public void logState(Printer pw, String prefix) {
273             pw.println(prefix + "mCount=0");
274         }
275     };
276 
277     private static final LongCounter[] ZERO_LONG_COUNTER_ARRAY =
278             new LongCounter[]{ZERO_LONG_COUNTER};
279 
280     @VisibleForTesting
281     protected CpuScalingPolicies mCpuScalingPolicies;
282 
283     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
284 
285     @VisibleForTesting
286     protected KernelWakelockReader mKernelWakelockReader;
287     @VisibleForTesting
288     protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
289     @VisibleForTesting
290     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
291     @VisibleForTesting
292     protected KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader;
293     @VisibleForTesting
294     protected KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader;
295     @VisibleForTesting
296     protected KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader;
297     @VisibleForTesting
298     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
299     @VisibleForTesting
300     protected SystemServerCpuThreadReader mSystemServerCpuThreadReader;
301 
302     private KernelMemoryBandwidthStats mKernelMemoryBandwidthStats;
303     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
304     private int[] mCpuPowerBracketMap;
305     private final CpuPowerStatsCollector mCpuPowerStatsCollector;
306     private final WakelockPowerStatsCollector mWakelockPowerStatsCollector;
307     private final ScreenPowerStatsCollector mScreenPowerStatsCollector;
308     private final MobileRadioPowerStatsCollector mMobileRadioPowerStatsCollector;
309     private final WifiPowerStatsCollector mWifiPowerStatsCollector;
310     private final BluetoothPowerStatsCollector mBluetoothPowerStatsCollector;
311     private final CameraPowerStatsCollector mCameraPowerStatsCollector;
312     private final GnssPowerStatsCollector mGnssPowerStatsCollector;
313     private final CustomEnergyConsumerPowerStatsCollector mCustomEnergyConsumerPowerStatsCollector;
314     private final SparseBooleanArray mPowerStatsCollectorEnabled = new SparseBooleanArray();
315     private boolean mMoveWscLoggingToNotifierEnabled = false;
316 
317     static class BatteryStatsSession {
318         private final BatteryStatsHistory mHistory;
319         private final long mMonotonicStartTime;
320         private final long mStartClockTime;
321         private final long mEstimatedBatteryCapacityMah;
322         private final long mBatteryTimeRemainingMs;
323         private final long mChargeTimeRemainingMs;
324         private final String[] mCustomEnergyConsumerNames;
325         private final BatteryStatsImpl mBatteryStats;
326 
BatteryStatsSession(BatteryStatsHistory history, long monotonicStartTime, long startClockTime, long batteryTimeRemainingMs, long chargeTimeRemainingMs, long estimatedBatteryCapacityMah, String[] customEnergyConsumerNames, BatteryStatsImpl batteryStats)327         BatteryStatsSession(BatteryStatsHistory history, long monotonicStartTime,
328                 long startClockTime, long batteryTimeRemainingMs, long chargeTimeRemainingMs,
329                 long estimatedBatteryCapacityMah, String[] customEnergyConsumerNames,
330                 BatteryStatsImpl batteryStats) {
331             mHistory = history;
332             mMonotonicStartTime = monotonicStartTime;
333             mStartClockTime = startClockTime;
334             mEstimatedBatteryCapacityMah = estimatedBatteryCapacityMah;
335             mBatteryTimeRemainingMs = batteryTimeRemainingMs;
336             mChargeTimeRemainingMs = chargeTimeRemainingMs;
337             mCustomEnergyConsumerNames = customEnergyConsumerNames;
338             mBatteryStats = batteryStats;
339         }
340 
getHistory()341         BatteryStatsHistory getHistory() {
342             return mHistory;
343         }
344 
getMonotonicStartTime()345         long getMonotonicStartTime() {
346             return mMonotonicStartTime;
347         }
348 
getStartClockTime()349         long getStartClockTime() {
350             return mStartClockTime;
351         }
352 
getBatteryTimeRemainingMs()353         long getBatteryTimeRemainingMs() {
354             return mBatteryTimeRemainingMs;
355         }
356 
getChargeTimeRemainingMs()357         long getChargeTimeRemainingMs() {
358             return mChargeTimeRemainingMs;
359         }
360 
getEstimatedBatteryCapacity()361         double getEstimatedBatteryCapacity() {
362             return mEstimatedBatteryCapacityMah;
363         }
364 
getCustomEnergyConsumerNames()365         String[] getCustomEnergyConsumerNames() {
366             return mCustomEnergyConsumerNames;
367         }
368 
369         /** @deprecated This method will be removed once PowerCalculators are removed from the
370          * code base. */
371         @Deprecated
getBatteryStats()372         public BatteryStatsImpl getBatteryStats() {
373             return mBatteryStats;
374         }
375     }
376 
getBatteryStatsSession()377     BatteryStatsSession getBatteryStatsSession() {
378         synchronized (this) {
379             long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
380             long batteryTimeRemainingUs = computeBatteryTimeRemaining(elapsedTimeUs);
381             long batteryTimeRemainingMs =
382                     batteryTimeRemainingUs >= 0 ? batteryTimeRemainingUs / 1000 : -1;
383             long chargeTimeRemainingUs = computeChargeTimeRemaining(elapsedTimeUs);
384             long chargeTimeRemainingMs =
385                     chargeTimeRemainingUs >= 0 ? chargeTimeRemainingUs / 1000 : -1;
386             return new BatteryStatsSession(mHistory, getMonotonicStartTime(), getStartClockTime(),
387                     batteryTimeRemainingMs, chargeTimeRemainingMs, getEstimatedBatteryCapacity(),
388                     getCustomEnergyConsumerNames(), this);
389         }
390     }
391 
392     private ScreenPowerStatsCollector.ScreenUsageTimeRetriever mScreenUsageTimeRetriever =
393             new ScreenPowerStatsCollector.ScreenUsageTimeRetriever() {
394 
395                 @Override
396                 public long getScreenOnTimeMs(int display) {
397                     synchronized (BatteryStatsImpl.this) {
398                         return getDisplayScreenOnTime(display,
399                                 mClock.elapsedRealtime() * 1000) / 1000;
400                     }
401                 }
402 
403                 @Override
404                 public long getBrightnessLevelTimeMs(int display, int brightnessLevel) {
405                     synchronized (BatteryStatsImpl.this) {
406                         return getDisplayScreenBrightnessTime(display, brightnessLevel,
407                                 mClock.elapsedRealtime() * 1000) / 1000;
408                     }
409                 }
410 
411                 @Override
412                 public long getScreenDozeTimeMs(int display) {
413                     synchronized (BatteryStatsImpl.this) {
414                         return getDisplayScreenDozeTime(display,
415                                 mClock.elapsedRealtime() * 1000) / 1000;
416                     }
417                 }
418 
419                 @Override
420                 public void retrieveTopActivityTimes(Callback callback) {
421                     synchronized (BatteryStatsImpl.this) {
422                         long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
423                         for (int i = mUidStats.size() - 1; i >= 0; i--) {
424                             Uid uid = mUidStats.valueAt(i);
425                             long topStateTime = uid.getProcessStateTime(Uid.PROCESS_STATE_TOP,
426                                     elapsedTimeUs, STATS_SINCE_CHARGED) / 1000;
427                             Timer timer = uid.getForegroundActivityTimer();
428                             if (timer == null) {
429                                 callback.onUidTopActivityTime(uid.mUid, topStateTime);
430                             } else {
431                                 long topActivityTime = timer.getTotalTimeLocked(elapsedTimeUs,
432                                         STATS_SINCE_CHARGED) / 1000;
433                                 callback.onUidTopActivityTime(uid.mUid, Math.min(topStateTime,
434                                         topActivityTime));
435                             }
436                         }
437                     }
438                 }
439             };
440     private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
441             new WifiPowerStatsCollector.WifiStatsRetriever() {
442                 @Override
443                 public void retrieveWifiScanTimes(Callback callback) {
444                     synchronized (BatteryStatsImpl.this) {
445                         retrieveWifiScanTimesLocked(callback);
446                     }
447                 }
448 
449                 @Override
450                 public long getWifiActiveDuration() {
451                     synchronized (BatteryStatsImpl.this) {
452                         return getGlobalWifiRunningTime(mClock.elapsedRealtime() * 1000,
453                                 STATS_SINCE_CHARGED) / 1000;
454                     }
455                 }
456             };
457 
458     private class BluetoothStatsRetrieverImpl implements
459             BluetoothPowerStatsCollector.BluetoothStatsRetriever {
460         private final BluetoothManager mBluetoothManager;
461 
BluetoothStatsRetrieverImpl(BluetoothManager bluetoothManager)462         BluetoothStatsRetrieverImpl(BluetoothManager bluetoothManager) {
463             mBluetoothManager = bluetoothManager;
464         }
465 
466         @Override
retrieveBluetoothScanTimes(Callback callback)467         public void retrieveBluetoothScanTimes(Callback callback) {
468             synchronized (BatteryStatsImpl.this) {
469                 retrieveBluetoothScanTimesLocked(callback);
470             }
471         }
472 
473         @Override
requestControllerActivityEnergyInfo(Executor executor, BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback)474         public boolean requestControllerActivityEnergyInfo(Executor executor,
475                 BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback) {
476             if (mBluetoothManager == null) {
477                 return false;
478             }
479 
480             BluetoothAdapter adapter = mBluetoothManager.getAdapter();
481             if (adapter == null) {
482                 return false;
483             }
484 
485             adapter.requestControllerActivityEnergyInfo(executor, callback);
486             return true;
487         }
488     }
489 
490     private final WakelockPowerStatsCollector.WakelockDurationRetriever mWakelockDurationRetriever =
491             new WakelockPowerStatsCollector.WakelockDurationRetriever() {
492 
493                 @Override
494                 public long getWakelockDurationMillis() {
495                     synchronized (BatteryStatsImpl.this) {
496                         long batteryUptimeUs = getBatteryUptime(mClock.uptimeMillis() * 1000);
497                         long screenOnTimeUs = getScreenOnTime(mClock.elapsedRealtime() * 1000,
498                                 BatteryStats.STATS_SINCE_CHARGED);
499                         return Math.max(0, (batteryUptimeUs - screenOnTimeUs) / 1000);
500                     }
501                 }
502 
503                 @Override
504                 public void retrieveUidWakelockDuration(Callback callback) {
505                     synchronized (BatteryStatsImpl.this) {
506                         long rawRealtimeUs = mClock.elapsedRealtime() * 1000;
507                         for (int i = mUidStats.size() - 1; i >= 0; i--) {
508                             Uid u = mUidStats.valueAt(i);
509                             long wakeLockTimeUs = 0;
510                             ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats =
511                                     u.getWakelockStats();
512                             final int wakelockStatsCount = wakelockStats.size();
513                             for (int j = 0; j < wakelockStatsCount; j++) {
514                                 final BatteryStats.Uid.Wakelock wakelock = wakelockStats.valueAt(j);
515                                 BatteryStats.Timer timer = wakelock.getWakeTime(
516                                         BatteryStats.WAKE_TYPE_PARTIAL);
517                                 if (timer != null) {
518                                     wakeLockTimeUs += timer.getTotalTimeLocked(rawRealtimeUs,
519                                             BatteryStats.STATS_SINCE_CHARGED);
520                                 }
521                             }
522 
523                             long wakelockTimeMs = wakeLockTimeUs / 1000;
524                             if (wakelockTimeMs != 0) {
525                                 callback.onUidWakelockDuration(u.getUid(), wakelockTimeMs);
526                             }
527                         }
528                     }
529                 }
530             };
531 
getKernelMemoryStats()532     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
533         return mKernelMemoryStats;
534     }
535 
536     private static final int[] SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS = {
537             EnergyConsumerStats.POWER_BUCKET_CPU,
538             EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
539             EnergyConsumerStats.POWER_BUCKET_WIFI,
540             EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
541     };
542 
543     // TimeInState counters need NUM_PROCESS_STATE states in order to accommodate
544     // Uid.PROCESS_STATE_NONEXISTENT, which is outside the range of legitimate proc states.
545     private static final int PROC_STATE_TIME_COUNTER_STATE_COUNT = NUM_PROCESS_STATE + 1;
546 
547     @GuardedBy("this")
548     public boolean mPerProcStateCpuTimesAvailable = true;
549 
550     @GuardedBy("this")
551     private long mNumSingleUidCpuTimeReads;
552     @GuardedBy("this")
553     private long mCpuTimeReadsTrackingStartTimeMs = SystemClock.uptimeMillis();
554     @GuardedBy("this")
555     private int mNumUidsRemoved;
556     @GuardedBy("this")
557     private int mNumAllUidCpuTimeReads;
558 
559     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
560     private RpmStats mTmpRpmStats = null;
561     /** The soonest the RPM stats can be updated after it was last updated. */
562     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
563     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
564     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
565 
566     /** Container for Rail Energy Data stats. */
567     private RailStats mTmpRailStats;
568 
569     /**
570      * Estimate UID modem power usage based on their estimated mobile radio active time.
571      */
572     public static final int PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME = 1;
573     /**
574      * Estimate UID modem power consumption by proportionally attributing estimated Rx and Tx
575      * power consumption individually.
576      * ModemActivityInfo must be available.
577      */
578     public static final int PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX = 2;
579 
580     @IntDef(flag = true, prefix = "PER_UID_MODEM_MODEL_", value = {
581             PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME,
582             PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX,
583     })
584     @Retention(RetentionPolicy.SOURCE)
585     public @interface PerUidModemPowerModel {
586     }
587 
588     /**
589      * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
590      * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
591      * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
592      *
593      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
594      * Batterystats both need to access UID cpu time. To resolve this race condition, only
595      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
596      * implemented so that STATSD can capture those UID times before they are deleted.
597      */
598     @GuardedBy("this")
599     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
600     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
601 
602     @NonNull
getHistory()603     public BatteryStatsHistory getHistory() {
604         return mHistory;
605     }
606 
607     @NonNull
copyHistory()608     BatteryStatsHistory copyHistory() {
609         return mHistory.copy();
610     }
611 
612     @VisibleForTesting
613     public final class UidToRemove {
614         private final int mStartUid;
615         private final int mEndUid;
616         private final long mUidRemovalTimestamp;
617 
618         /** Remove just one UID */
UidToRemove(int uid, long timestamp)619         public UidToRemove(int uid, long timestamp) {
620             this(uid, uid, timestamp);
621         }
622 
623         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)624         public UidToRemove(int startUid, int endUid, long timestamp) {
625             mStartUid = startUid;
626             mEndUid = endUid;
627             mUidRemovalTimestamp = timestamp;
628         }
629 
getUidRemovalTimestamp()630         public long getUidRemovalTimestamp() {
631             return mUidRemovalTimestamp;
632         }
633 
634         @GuardedBy("BatteryStatsImpl.this")
removeLocked()635         void removeLocked() {
636             removeCpuStatsForUidRangeLocked(mStartUid, mEndUid);
637         }
638     }
639 
640     private boolean mSaveBatteryUsageStatsOnReset;
641     private boolean mResetBatteryHistoryOnNewSession;
642     private boolean mAccumulateBatteryUsageStats;
643     private BatteryUsageStatsProvider mBatteryUsageStatsProvider;
644     private PowerStatsStore mPowerStatsStore;
645 
646     public interface BatteryCallback {
batteryNeedsCpuUpdate()647         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)648         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)649         public void batterySendBroadcast(Intent intent);
batteryStatsReset()650         public void batteryStatsReset();
651     }
652 
653     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)654         public void fillLowPowerStats(RpmStats rpmStats);
655     }
656 
657     /** interface to update rail information for power monitor */
658     public interface EnergyStatsRetriever {
659         /** Function to fill the map for the rail data stats
660          * Used for power monitoring feature
661          * @param railStats
662          */
fillRailDataStats(RailStats railStats)663         void fillRailDataStats(RailStats railStats);
664     }
665 
666     public static abstract class UserInfoProvider {
667         private int[] userIds;
getUserIds()668         protected abstract @Nullable int[] getUserIds();
669         @VisibleForTesting
refreshUserIds()670         public final void refreshUserIds() {
671             userIds = getUserIds();
672         }
673         @VisibleForTesting
exists(int userId)674         public boolean exists(int userId) {
675             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
676         }
677     }
678 
679     /** Provide BatteryStatsImpl configuration choices */
680     public static class BatteryStatsConfig {
681         static final int RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG = 1 << 0;
682         static final int RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG = 1 << 1;
683 
684         private final int mFlags;
685         private final Long mDefaultPowerStatsThrottlePeriod;
686         private final Map<String, Long> mPowerStatsThrottlePeriods;
687         private final int mMaxHistorySizeBytes;
688 
BatteryStatsConfig(Builder builder)689         private BatteryStatsConfig(Builder builder) {
690             int flags = 0;
691             if (builder.mResetOnUnplugHighBatteryLevel) {
692                 flags |= RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG;
693             }
694             if (builder.mResetOnUnplugAfterSignificantCharge) {
695                 flags |= RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
696             }
697             mFlags = flags;
698             mDefaultPowerStatsThrottlePeriod = builder.mDefaultPowerStatsThrottlePeriod;
699             mPowerStatsThrottlePeriods = builder.mPowerStatsThrottlePeriods;
700             mMaxHistorySizeBytes = builder.mMaxHistorySizeBytes;
701         }
702 
703         /**
704          * Returns whether a BatteryStats reset should occur on unplug when the battery level is
705          * high.
706          */
shouldResetOnUnplugHighBatteryLevel()707         public boolean shouldResetOnUnplugHighBatteryLevel() {
708             return (mFlags & RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG)
709                     == RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG;
710         }
711 
712         /**
713          * Returns whether a BatteryStats reset should occur on unplug if the battery charge a
714          * significant amount since it has been plugged in.
715          */
shouldResetOnUnplugAfterSignificantCharge()716         public boolean shouldResetOnUnplugAfterSignificantCharge() {
717             return (mFlags & RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG)
718                     == RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
719         }
720 
721         /**
722          * Returns  the minimum amount of time (in millis) to wait between passes
723          * of power stats collection for the specified power component.
724          */
getPowerStatsThrottlePeriod(String powerComponentName)725         public long getPowerStatsThrottlePeriod(String powerComponentName) {
726             return mPowerStatsThrottlePeriods.getOrDefault(powerComponentName,
727                     mDefaultPowerStatsThrottlePeriod);
728         }
729 
getMaxHistorySizeBytes()730         public int getMaxHistorySizeBytes() {
731             return mMaxHistorySizeBytes;
732         }
733 
734         /**
735          * Builder for BatteryStatsConfig
736          */
737         public static class Builder {
738             private boolean mResetOnUnplugHighBatteryLevel;
739             private boolean mResetOnUnplugAfterSignificantCharge;
740             private static final long DEFAULT_POWER_STATS_THROTTLE_PERIOD =
741                     TimeUnit.HOURS.toMillis(1);
742             private static final long DEFAULT_POWER_STATS_THROTTLE_PERIOD_CPU =
743                     TimeUnit.MINUTES.toMillis(1);
744             private static final int DEFAULT_MAX_HISTORY_SIZE = 4 * 1024 * 1024;
745             private long mDefaultPowerStatsThrottlePeriod = DEFAULT_POWER_STATS_THROTTLE_PERIOD;
746             private final Map<String, Long> mPowerStatsThrottlePeriods = new HashMap<>();
747             private int mMaxHistorySizeBytes = DEFAULT_MAX_HISTORY_SIZE;
748 
Builder()749             public Builder() {
750                 mResetOnUnplugHighBatteryLevel = true;
751                 mResetOnUnplugAfterSignificantCharge = true;
752                 setPowerStatsThrottlePeriodMillis(BatteryConsumer.powerComponentIdToString(
753                                 BatteryConsumer.POWER_COMPONENT_CPU),
754                         DEFAULT_POWER_STATS_THROTTLE_PERIOD_CPU);
755             }
756 
757             /**
758              * Build the BatteryStatsConfig.
759              */
build()760             public BatteryStatsConfig build() {
761                 return new BatteryStatsConfig(this);
762             }
763 
764             /**
765              * Set whether a BatteryStats reset should occur on unplug when the battery level is
766              * high.
767              */
setResetOnUnplugHighBatteryLevel(boolean reset)768             public Builder setResetOnUnplugHighBatteryLevel(boolean reset) {
769                 mResetOnUnplugHighBatteryLevel = reset;
770                 return this;
771             }
772 
773             /**
774              * Set whether a BatteryStats reset should occur on unplug if the battery charge a
775              * significant amount since it has been plugged in.
776              */
setResetOnUnplugAfterSignificantCharge(boolean reset)777             public Builder setResetOnUnplugAfterSignificantCharge(boolean reset) {
778                 mResetOnUnplugAfterSignificantCharge = reset;
779                 return this;
780             }
781 
782             /**
783              * Sets the minimum amount of time (in millis) to wait between passes
784              * of power stats collection for the specified power component.
785              */
setPowerStatsThrottlePeriodMillis(String powerComponentName, long periodMs)786             public Builder setPowerStatsThrottlePeriodMillis(String powerComponentName,
787                     long periodMs) {
788                 mPowerStatsThrottlePeriods.put(powerComponentName, periodMs);
789                 return this;
790             }
791 
792             /**
793              * Sets the minimum amount of time (in millis) to wait between passes
794              * of power stats collection for any components not configured explicitly.
795              */
setDefaultPowerStatsThrottlePeriodMillis(long periodMs)796             public Builder setDefaultPowerStatsThrottlePeriodMillis(long periodMs) {
797                 mDefaultPowerStatsThrottlePeriod = periodMs;
798                 return this;
799             }
800 
801             /**
802              * Sets the maximum amount of disk space, in bytes, that battery history can
803              * utilize. As this space fills up, the oldest history chunks must be expunged.
804              */
setMaxHistorySizeBytes(int maxHistorySizeBytes)805             public Builder setMaxHistorySizeBytes(int maxHistorySizeBytes) {
806                 mMaxHistorySizeBytes = maxHistorySizeBytes;
807                 return this;
808             }
809         }
810     }
811 
812     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
813 
814     private final Runnable mDeferSetCharging = new Runnable() {
815         @Override
816         public void run() {
817             synchronized (BatteryStatsImpl.this) {
818                 if (mOnBattery) {
819                     // if the device gets unplugged in the time between this runnable being
820                     // executed and the lock being taken, we don't want to set charging state
821                     return;
822                 }
823                 boolean changed = setChargingLocked(true);
824                 if (changed) {
825                     final long uptimeMs = mClock.uptimeMillis();
826                     final long elapsedRealtimeMs = mClock.elapsedRealtime();
827                     mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
828                 }
829             }
830         }
831     };
832 
833     public final EnergyStatsRetriever mEnergyConsumerRetriever;
834 
835     /**
836      * This handler is running on {@link BackgroundThread}.
837      */
838     final class MyHandler extends Handler {
MyHandler(Looper looper)839         public MyHandler(Looper looper) {
840             super(looper, null, true);
841         }
842 
843         @Override
handleMessage(Message msg)844         public void handleMessage(Message msg) {
845             BatteryCallback cb = mCallback;
846             if (cb == null) {
847                 return;
848             }
849             switch (msg.what) {
850                 case MSG_REPORT_CPU_UPDATE_NEEDED:
851                     cb.batteryNeedsCpuUpdate();
852                     break;
853                 case MSG_REPORT_POWER_CHANGE:
854                     cb.batteryPowerChanged(msg.arg1 != 0);
855                     break;
856                 case MSG_REPORT_CHARGING:
857                     final String action;
858                     synchronized (BatteryStatsImpl.this) {
859                         action = mCharging ? BatteryManager.ACTION_CHARGING
860                                 : BatteryManager.ACTION_DISCHARGING;
861                     }
862                     Intent intent = new Intent(action);
863                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
864                     cb.batterySendBroadcast(intent);
865                     break;
866                 case MSG_REPORT_RESET_STATS:
867                     cb.batteryStatsReset();
868             }
869         }
870     }
871 
postBatteryNeedsCpuUpdateMsg()872     public void postBatteryNeedsCpuUpdateMsg() {
873         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
874     }
875 
876     /**
877      * Update per-freq cpu times for the supplied UID.
878      */
879     @GuardedBy("this")
880     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
881     @VisibleForTesting
updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs)882     public void updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
883         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
884             return;
885         }
886 
887         ensureKernelSingleUidTimeReaderLocked();
888 
889         final Uid u = getUidStatsLocked(uid);
890 
891         mNumSingleUidCpuTimeReads++;
892 
893         LongArrayMultiStateCounter onBatteryCounter =
894                 u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
895         LongArrayMultiStateCounter onBatteryScreenOffCounter =
896                 u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
897 
898 
899         mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, elapsedRealtimeMs);
900         mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, elapsedRealtimeMs);
901 
902         if (u.mChildUids != null) {
903             long[] delta = getCpuTimeInFreqContainer();
904             int childUidCount = u.mChildUids.size();
905             for (int j = childUidCount - 1; j >= 0; --j) {
906                 LongArrayMultiStateCounter cpuTimeInFreqCounter =
907                         u.mChildUids.valueAt(j).cpuTimeInFreqCounter;
908                 if (cpuTimeInFreqCounter != null) {
909                     mKernelSingleUidTimeReader.addDelta(u.mChildUids.keyAt(j),
910                             cpuTimeInFreqCounter, elapsedRealtimeMs, delta);
911                     onBatteryCounter.addCounts(delta);
912                     onBatteryScreenOffCounter.addCounts(delta);
913                 }
914             }
915         }
916     }
917 
918     /**
919      * Removes kernel CPU stats for removed UIDs, in the order they were added to the
920      * mPendingRemovedUids queue.
921      */
922     @GuardedBy("this")
923     @SuppressWarnings("GuardedBy")    // errorprone false positive on removeLocked
clearPendingRemovedUidsLocked()924     public void clearPendingRemovedUidsLocked() {
925         long cutOffTimeMs = mClock.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
926         while (!mPendingRemovedUids.isEmpty()
927                 && mPendingRemovedUids.peek().getUidRemovalTimestamp() < cutOffTimeMs) {
928             mPendingRemovedUids.poll().removeLocked();
929         }
930     }
931 
932     /**
933      * When the battery/screen state changes, we don't attribute the cpu times to any process
934      * but we still need to take snapshots of all uids to get correct deltas later on.
935      */
936     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
updateCpuTimesForAllUids()937     public void updateCpuTimesForAllUids() {
938         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
939             mCpuPowerStatsCollector.schedule();
940             return;
941         }
942 
943         synchronized (BatteryStatsImpl.this) {
944             if (!trackPerProcStateCpuTimes()) {
945                 return;
946             }
947 
948             ensureKernelSingleUidTimeReaderLocked();
949 
950             // TODO(b/197162116): just get a list of UIDs
951             final SparseArray<long[]> allUidCpuFreqTimesMs =
952                     mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
953             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
954                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
955                 final int parentUid = mapUid(uid);
956                 final Uid u = getAvailableUidStatsLocked(parentUid);
957                 if (u == null) {
958                     continue;
959                 }
960 
961                 final int procState = u.mProcessState;
962                 if (procState == Uid.PROCESS_STATE_NONEXISTENT) {
963                     continue;
964                 }
965 
966                 final long elapsedRealtimeMs = mClock.elapsedRealtime();
967                 final long uptimeMs = mClock.uptimeMillis();
968                 final LongArrayMultiStateCounter onBatteryCounter =
969                         u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
970                 final LongArrayMultiStateCounter onBatteryScreenOffCounter =
971                         u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
972 
973                 if (uid == parentUid || Process.isSdkSandboxUid(uid)) {
974                     mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter,
975                             elapsedRealtimeMs);
976                     mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryScreenOffCounter,
977                             elapsedRealtimeMs);
978                 } else {
979                     Uid.ChildUid childUid = u.getChildUid(uid);
980                     if (childUid != null) {
981                         final LongArrayMultiStateCounter counter = childUid.cpuTimeInFreqCounter;
982                         if (counter != null) {
983                             final long[] deltaContainer = getCpuTimeInFreqContainer();
984                             mKernelSingleUidTimeReader.addDelta(uid, counter, elapsedRealtimeMs,
985                                     deltaContainer);
986                             onBatteryCounter.addCounts(deltaContainer);
987                             onBatteryScreenOffCounter.addCounts(deltaContainer);
988                         }
989                     }
990                 }
991             }
992         }
993     }
994 
995     @GuardedBy("this")
ensureKernelSingleUidTimeReaderLocked()996     private void ensureKernelSingleUidTimeReaderLocked() {
997         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)
998                 || mKernelSingleUidTimeReader != null) {
999             return;
1000         }
1001 
1002         mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(
1003                 mCpuScalingPolicies.getScalingStepCount());
1004         mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.perClusterTimesAvailable()
1005                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
1006     }
1007 
1008     public interface ExternalStatsSync {
1009         int UPDATE_CPU = 0x01;
1010         int UPDATE_WIFI = 0x02;
1011         int UPDATE_RADIO = 0x04;
1012         int UPDATE_BT = 0x08;
1013         int UPDATE_RPM = 0x10;
1014         int UPDATE_DISPLAY = 0x20;
1015         int UPDATE_CAMERA = 0x40;
1016         int RESET = 0x80;
1017 
1018         int UPDATE_ALL =
1019                 UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY
1020                         | UPDATE_CAMERA;
1021 
1022         int UPDATE_ON_PROC_STATE_CHANGE = UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
1023 
1024         int UPDATE_ON_RESET = UPDATE_ALL | RESET;
1025 
1026         @IntDef(flag = true, prefix = "UPDATE_", value = {
1027                 UPDATE_CPU,
1028                 UPDATE_WIFI,
1029                 UPDATE_RADIO,
1030                 UPDATE_BT,
1031                 UPDATE_RPM,
1032                 UPDATE_DISPLAY,
1033                 UPDATE_CAMERA,
1034                 UPDATE_ALL,
1035         })
1036         @Retention(RetentionPolicy.SOURCE)
1037         public @interface ExternalUpdateFlag {
1038         }
1039 
1040         /**
1041          * Schedules a sync of kernel metrics in accordance with the specified flags.
1042          */
scheduleSync(String reason, @ExternalUpdateFlag int flags)1043         void scheduleSync(String reason, @ExternalUpdateFlag int flags);
1044 
1045         /**
1046          * Schedules a CPU stats sync after a UID removal.
1047          */
scheduleCpuSyncDueToRemovedUid(int uid)1048         void scheduleCpuSyncDueToRemovedUid(int uid);
1049 
1050         /**
1051          * Schedule a sync because of a screen state change.
1052          */
scheduleSyncDueToScreenStateChange(@xternalUpdateFlag int flags, boolean onBattery, boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates)1053         void scheduleSyncDueToScreenStateChange(@ExternalUpdateFlag int flags, boolean onBattery,
1054                 boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates);
1055 
1056         /**
1057          * Schedules a sync after a wakelock state change
1058          */
scheduleCpuSyncDueToWakelockChange(long delayMillis)1059         void scheduleCpuSyncDueToWakelockChange(long delayMillis);
1060 
1061         /**
1062          * Canceles any pending sync due to a wakelock state change
1063          */
cancelCpuSyncDueToWakelockChange()1064         void cancelCpuSyncDueToWakelockChange();
1065 
1066         /** Schedule removal of UIDs corresponding to a removed user */
scheduleCleanupDueToRemovedUser(int userId)1067         void scheduleCleanupDueToRemovedUser(int userId);
1068         /** Schedule a sync because of a process state change */
scheduleSyncDueToProcessStateChange(int flags, long delayMillis)1069         void scheduleSyncDueToProcessStateChange(int flags, long delayMillis);
1070     }
1071 
1072     public Handler mHandler;
1073     private ExternalStatsSync mExternalSync = null;
1074     @VisibleForTesting
1075     protected UserInfoProvider mUserInfoProvider = null;
1076 
1077     private BatteryCallback mCallback;
1078 
1079     /**
1080      * Mapping child uids to their parent uid.
1081      */
1082     @VisibleForTesting
1083     protected final PowerStatsUidResolver mPowerStatsUidResolver;
1084 
1085     /**
1086      * The statistics we have collected organized by uids.
1087      */
1088     private final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
1089 
1090     // A set of pools of currently active timers.  When a timer is queried, we will divide the
1091     // elapsed time by the number of active timers to arrive at that timer's share of the time.
1092     // In order to do this, we must refresh each timer whenever the number of active timers
1093     // changes.
1094     @VisibleForTesting
1095     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
1096     private final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
1097     private final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
1098     private final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
1099     private final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
1100     private final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
1101     private final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
1102     private final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
1103     private final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
1104     private final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers =
1105             new SparseArray<>();
1106     private final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
1107     private final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
1108     private final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
1109     private final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
1110     private final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
1111 
1112     // Last partial timers we use for distributing CPU usage.
1113     @VisibleForTesting
1114     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
1115 
1116     // These are the objects that will want to do something when the device
1117     // is unplugged from power.
1118     protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
1119 
1120     // These are the objects that will want to do something when the device
1121     // is unplugged from power *and* the screen is off or doze.
1122     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
1123 
1124     private boolean mSystemReady;
1125     private boolean mShuttingDown;
1126 
1127     private final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
1128     private final BatteryHistoryStepDetailsProvider mStepDetailsProvider =
1129             new BatteryHistoryStepDetailsProvider(this);
1130 
1131     private boolean mHaveBatteryLevel = false;
1132     private boolean mBatteryPluggedIn;
1133     private long mBatteryPluggedInRealTimeMs = 0;
1134     private int mBatteryStatus;
1135     private int mBatteryLevel;
1136     private int mBatteryPlugType;
1137     private int mBatteryChargeUah;
1138     private int mBatteryHealth;
1139     private int mBatteryTemperature;
1140     private int mBatteryVoltageMv;
1141 
1142     @Nullable
1143     private final BatteryHistoryDirectory mBatteryHistoryDirectory;
1144     @NonNull
1145     private final BatteryStatsHistory mHistory;
1146 
1147     int mStartCount;
1148 
1149     /**
1150      * Set to true when a reset occurs, informing us that the next time BatteryExternalStatsWorker
1151      * gives us data, we mustn't process it since this data includes pre-reset-period data.
1152      */
1153     @GuardedBy("this")
1154     boolean mIgnoreNextExternalStats = false;
1155 
1156     long mStartClockTimeMs;
1157     String mStartPlatformVersion;
1158     String mEndPlatformVersion;
1159 
1160     long mUptimeUs;
1161     long mUptimeStartUs;
1162     long mRealtimeUs;
1163     long mRealtimeStartUs;
1164     long mMonotonicStartTime;
1165     long mMonotonicEndTime = MonotonicClock.UNDEFINED;
1166 
1167     int mWakeLockNesting;
1168     boolean mWakeLockImportant;
1169     public boolean mRecordAllHistory;
1170     boolean mNoAutoReset;
1171 
1172     /**
1173      * Overall screen state. For multidisplay devices, this represents the current highest screen
1174      * state of the displays.
1175      */
1176     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
1177     protected int mScreenState = Display.STATE_UNKNOWN;
1178     /**
1179      * Overall screen on timer. For multidisplay devices, this represents the time spent with at
1180      * least one display in the screen on state.
1181      */
1182     StopwatchTimer mScreenOnTimer;
1183     /**
1184      * Overall screen doze timer. For multidisplay devices, this represents the time spent with
1185      * screen doze being the highest screen state.
1186      */
1187     StopwatchTimer mScreenDozeTimer;
1188     /**
1189      * Overall screen brightness bin. For multidisplay devices, this represents the current
1190      * brightest screen.
1191      */
1192     int mScreenBrightnessBin = -1;
1193     /**
1194      * Overall screen brightness timers. For multidisplay devices, the {@link mScreenBrightnessBin}
1195      * timer will be active at any given time
1196      */
1197     final StopwatchTimer[] mScreenBrightnessTimer =
1198             new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
1199 
1200     boolean mPretendScreenOff;
1201 
1202     private static class DisplayBatteryStats {
1203         /**
1204          * Per display screen state.
1205          */
1206         public int screenState = Display.STATE_UNKNOWN;
1207         /**
1208          * Per display screen on timers.
1209          */
1210         public StopwatchTimer screenOnTimer;
1211         /**
1212          * Per display screen doze timers.
1213          */
1214         public StopwatchTimer screenDozeTimer;
1215         /**
1216          * Per display screen brightness bins.
1217          */
1218         public int screenBrightnessBin = -1;
1219         /**
1220          * Per display screen brightness timers.
1221          */
1222         public StopwatchTimer[] screenBrightnessTimers =
1223                 new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
1224         /**
1225          * Per display screen state the last time {@link #updateDisplayEnergyConsumerStatsLocked}
1226          * was called.
1227          */
1228         public int screenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
1229 
DisplayBatteryStats(Clock clock, TimeBase timeBase)1230         DisplayBatteryStats(Clock clock, TimeBase timeBase) {
1231             screenOnTimer = new StopwatchTimer(clock, null, -1, null,
1232                     timeBase);
1233             screenDozeTimer = new StopwatchTimer(clock, null, -1, null,
1234                     timeBase);
1235             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1236                 screenBrightnessTimers[i] = new StopwatchTimer(clock, null, -100 - i, null,
1237                         timeBase);
1238             }
1239         }
1240 
1241         /**
1242          * Reset display timers.
1243          */
reset(long elapsedRealtimeUs)1244         public void reset(long elapsedRealtimeUs) {
1245             screenOnTimer.reset(false, elapsedRealtimeUs);
1246             screenDozeTimer.reset(false, elapsedRealtimeUs);
1247             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1248                 screenBrightnessTimers[i].reset(false, elapsedRealtimeUs);
1249             }
1250         }
1251 
1252         /**
1253          * Write data to summary parcel
1254          */
writeSummaryToParcel(Parcel out, long elapsedRealtimeUs)1255         public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
1256             screenOnTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1257             screenDozeTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1258             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1259                 screenBrightnessTimers[i].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1260             }
1261         }
1262 
1263         /**
1264          * Read data from summary parcel
1265          */
readSummaryFromParcel(Parcel in)1266         public void readSummaryFromParcel(Parcel in) {
1267             screenOnTimer.readSummaryFromParcelLocked(in);
1268             screenDozeTimer.readSummaryFromParcelLocked(in);
1269             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1270                 screenBrightnessTimers[i].readSummaryFromParcelLocked(in);
1271             }
1272         }
1273     }
1274 
1275     DisplayBatteryStats[] mPerDisplayBatteryStats;
1276 
1277     private int mDisplayMismatchWtfCount = 0;
1278 
1279     boolean mInteractive;
1280     StopwatchTimer mInteractiveTimer;
1281 
1282     boolean mPowerSaveModeEnabled;
1283     StopwatchTimer mPowerSaveModeEnabledTimer;
1284 
1285     boolean mDeviceIdling;
1286     StopwatchTimer mDeviceIdlingTimer;
1287 
1288     boolean mDeviceLightIdling;
1289     StopwatchTimer mDeviceLightIdlingTimer;
1290 
1291     int mDeviceIdleMode;
1292     long mLastIdleTimeStartMs;
1293     long mLongestLightIdleTimeMs;
1294     long mLongestFullIdleTimeMs;
1295     StopwatchTimer mDeviceIdleModeLightTimer;
1296     StopwatchTimer mDeviceIdleModeFullTimer;
1297 
1298     boolean mPhoneOn;
1299     StopwatchTimer mPhoneOnTimer;
1300 
1301     int mAudioOnNesting;
1302     StopwatchTimer mAudioOnTimer;
1303 
1304     int mVideoOnNesting;
1305     StopwatchTimer mVideoOnTimer;
1306 
1307     int mFlashlightOnNesting;
1308     StopwatchTimer mFlashlightOnTimer;
1309 
1310     int mCameraOnNesting;
1311     StopwatchTimer mCameraOnTimer;
1312 
1313     private static final int USB_DATA_UNKNOWN = 0;
1314     private static final int USB_DATA_DISCONNECTED = 1;
1315     private static final int USB_DATA_CONNECTED = 2;
1316     int mUsbDataState = USB_DATA_UNKNOWN;
1317 
1318     int mGpsSignalQualityBin = -1;
1319     final StopwatchTimer[] mGpsSignalQualityTimer =
1320         new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
1321 
1322     int mPhoneSignalStrengthBin = -1;
1323     int mPhoneSignalStrengthBinRaw = -1;
1324     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
1325             new StopwatchTimer[CELL_SIGNAL_STRENGTH_LEVEL_COUNT];
1326 
1327     StopwatchTimer mPhoneSignalScanningTimer;
1328 
1329     int mPhoneDataConnectionType = -1;
1330     final StopwatchTimer[] mPhoneDataConnectionsTimer =
1331             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
1332 
1333     int mNrState = -1;
1334     StopwatchTimer mNrNsaTimer;
1335 
1336     @RadioAccessTechnology
1337     int mActiveRat = RADIO_ACCESS_TECHNOLOGY_OTHER;
1338 
1339     private static class RadioAccessTechnologyBatteryStats {
1340         /**
1341          * This RAT is currently being used.
1342          */
1343         private boolean mActive = false;
1344         /**
1345          * Current active frequency range for this RAT.
1346          */
1347         @ServiceState.FrequencyRange
1348         private int mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
1349         /**
1350          * Current signal strength for this RAT.
1351          */
1352         private int mSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
1353         /**
1354          * Timers for each combination of frequency range and signal strength.
1355          */
1356         public final StopwatchTimer[][] perStateTimers;
1357         /**
1358          * Counters tracking the time (in milliseconds) spent transmitting data in a given state.
1359          */
1360         @Nullable
1361         private LongSamplingCounter[][] mPerStateTxDurationMs = null;
1362         /**
1363          * Counters tracking the time (in milliseconds) spent receiving data in at given frequency.
1364          */
1365         @Nullable
1366         private LongSamplingCounter[] mPerFrequencyRxDurationMs = null;
1367 
RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase)1368         RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
1369             perStateTimers =
1370                     new StopwatchTimer[freqCount][CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1371             for (int i = 0; i < freqCount; i++) {
1372                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1373                     perStateTimers[i][j] = new StopwatchTimer(clock, null, -1, null, timeBase);
1374                 }
1375             }
1376         }
1377 
1378         /**
1379          * Note this RAT is currently being used.
1380          */
noteActive(boolean active, long elapsedRealtimeMs)1381         public void noteActive(boolean active, long elapsedRealtimeMs) {
1382             if (mActive == active) return;
1383             mActive = active;
1384             if (mActive) {
1385                 perStateTimers[mFrequencyRange][mSignalStrength].startRunningLocked(
1386                         elapsedRealtimeMs);
1387             } else {
1388                 perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(
1389                         elapsedRealtimeMs);
1390             }
1391         }
1392 
1393         /**
1394          * Note current frequency range has changed.
1395          */
noteFrequencyRange(@erviceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs)1396         public void noteFrequencyRange(@ServiceState.FrequencyRange int frequencyRange,
1397                 long elapsedRealtimeMs) {
1398             if (mFrequencyRange == frequencyRange) return;
1399 
1400             if (!mActive) {
1401                 // RAT not in use, note the frequency change and move on.
1402                 mFrequencyRange = frequencyRange;
1403                 return;
1404             }
1405             perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
1406             perStateTimers[frequencyRange][mSignalStrength].startRunningLocked(elapsedRealtimeMs);
1407             mFrequencyRange = frequencyRange;
1408         }
1409 
1410         /**
1411          * Note current signal strength has changed.
1412          */
noteSignalStrength(int signalStrength, long elapsedRealtimeMs)1413         public void noteSignalStrength(int signalStrength, long elapsedRealtimeMs) {
1414             if (mSignalStrength == signalStrength) return;
1415 
1416             if (!mActive) {
1417                 // RAT not in use, note the signal strength change and move on.
1418                 mSignalStrength = signalStrength;
1419                 return;
1420             }
1421             perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
1422             perStateTimers[mFrequencyRange][signalStrength].startRunningLocked(elapsedRealtimeMs);
1423             mSignalStrength = signalStrength;
1424         }
1425 
1426         /**
1427          * Returns the duration in milliseconds spent in a given state since the last mark.
1428          */
getTimeSinceMark(@erviceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)1429         public long getTimeSinceMark(@ServiceState.FrequencyRange int frequencyRange,
1430                 int signalStrength, long elapsedRealtimeMs) {
1431             return perStateTimers[frequencyRange][signalStrength].getTimeSinceMarkLocked(
1432                     elapsedRealtimeMs * 1000) / 1000;
1433         }
1434 
1435         /**
1436          * Set mark for all timers.
1437          */
setMark(long elapsedRealtimeMs)1438         public void setMark(long elapsedRealtimeMs) {
1439             final int size = perStateTimers.length;
1440             for (int i = 0; i < size; i++) {
1441                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1442                     perStateTimers[i][j].setMark(elapsedRealtimeMs);
1443                 }
1444             }
1445         }
1446 
1447         /**
1448          * Returns numbers of frequencies tracked for this RAT.
1449          */
getFrequencyRangeCount()1450         public int getFrequencyRangeCount() {
1451             return perStateTimers.length;
1452         }
1453 
1454         /**
1455          * Add TX time for a given state.
1456          */
incrementTxDuration(@erviceState.FrequencyRange int frequencyRange, int signalStrength, long durationMs)1457         public void incrementTxDuration(@ServiceState.FrequencyRange int frequencyRange,
1458                 int signalStrength, long durationMs) {
1459             getTxDurationCounter(frequencyRange, signalStrength, true).addCountLocked(durationMs);
1460         }
1461 
1462         /**
1463          * Add TX time for a given frequency.
1464          */
incrementRxDuration(@erviceState.FrequencyRange int frequencyRange, long durationMs)1465         public void incrementRxDuration(@ServiceState.FrequencyRange int frequencyRange,
1466                 long durationMs) {
1467             getRxDurationCounter(frequencyRange, true).addCountLocked(durationMs);
1468         }
1469 
1470         /**
1471          * Reset radio access technology timers and counts.
1472          */
reset(long elapsedRealtimeUs)1473         public void reset(long elapsedRealtimeUs) {
1474             final int size = perStateTimers.length;
1475             for (int i = 0; i < size; i++) {
1476                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1477                     perStateTimers[i][j].reset(false, elapsedRealtimeUs);
1478                     if (mPerStateTxDurationMs == null) continue;
1479                     mPerStateTxDurationMs[i][j].reset(false, elapsedRealtimeUs);
1480                 }
1481                 if (mPerFrequencyRxDurationMs == null) continue;
1482                 mPerFrequencyRxDurationMs[i].reset(false, elapsedRealtimeUs);
1483             }
1484         }
1485 
1486         /**
1487          * Write data to summary parcel
1488          */
writeSummaryToParcel(Parcel out, long elapsedRealtimeUs)1489         public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
1490             final int freqCount = perStateTimers.length;
1491             out.writeInt(freqCount);
1492             out.writeInt(CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS);
1493             for (int i = 0; i < freqCount; i++) {
1494                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1495                     perStateTimers[i][j].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1496                 }
1497             }
1498 
1499             if (mPerStateTxDurationMs == null) {
1500                 out.writeInt(0);
1501             } else {
1502                 out.writeInt(1);
1503                 for (int i = 0; i < freqCount; i++) {
1504                     for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1505                         mPerStateTxDurationMs[i][j].writeSummaryFromParcelLocked(out);
1506                     }
1507                 }
1508             }
1509 
1510             if (mPerFrequencyRxDurationMs == null) {
1511                 out.writeInt(0);
1512             } else {
1513                 out.writeInt(1);
1514                 for (int i = 0; i < freqCount; i++) {
1515                     mPerFrequencyRxDurationMs[i].writeSummaryFromParcelLocked(out);
1516                 }
1517             }
1518         }
1519 
1520         /**
1521          * Read data from summary parcel
1522          */
readSummaryFromParcel(Parcel in)1523         public void readSummaryFromParcel(Parcel in) {
1524             final int oldFreqCount = in.readInt();
1525             final int oldSignalStrengthCount = in.readInt();
1526             final int currFreqCount = perStateTimers.length;
1527             final int currSignalStrengthCount = CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS;
1528 
1529             for (int freq = 0; freq < oldFreqCount; freq++) {
1530                 for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
1531                     if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
1532                         // Mismatch with the summary parcel. Consume the data but don't use it.
1533                         final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
1534                                 new TimeBase());
1535                         // Consume perStateTimers data.
1536                         temp.readSummaryFromParcelLocked(in);
1537                     } else {
1538                         perStateTimers[freq][strength].readSummaryFromParcelLocked(in);
1539                     }
1540                 }
1541             }
1542 
1543             if (in.readInt() == 1) {
1544                 for (int freq = 0; freq < oldFreqCount; freq++) {
1545                     for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
1546                         if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
1547                             // Mismatch with the summary parcel. Consume the data but don't use it.
1548                             final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
1549                                     new TimeBase());
1550                             // Consume mPerStateTxDurationMs data.
1551                             temp.readSummaryFromParcelLocked(in);
1552                         }
1553                         getTxDurationCounter(freq, strength, true).readSummaryFromParcelLocked(in);
1554                     }
1555                 }
1556             }
1557 
1558             if (in.readInt() == 1) {
1559                 for (int freq = 0; freq < oldFreqCount; freq++) {
1560                     if (freq >= currFreqCount) {
1561                         // Mismatch with the summary parcel. Consume the data but don't use it.
1562                         final StopwatchTimer
1563                                 temp = new StopwatchTimer(null, null, -1, null, new TimeBase());
1564                         // Consume mPerFrequencyRxDurationMs data.
1565                         temp.readSummaryFromParcelLocked(in);
1566                         continue;
1567                     }
1568                     getRxDurationCounter(freq, true).readSummaryFromParcelLocked(in);
1569                 }
1570             }
1571         }
1572 
getTxDurationCounter( @erviceState.FrequencyRange int frequencyRange, int signalStrength, boolean make)1573         private LongSamplingCounter getTxDurationCounter(
1574                 @ServiceState.FrequencyRange int frequencyRange, int signalStrength, boolean make) {
1575             if (mPerStateTxDurationMs == null) {
1576                 if (!make) return null;
1577 
1578                 final int freqCount = getFrequencyRangeCount();
1579                 final int signalStrengthCount = perStateTimers[0].length;
1580                 final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
1581                 mPerStateTxDurationMs = new LongSamplingCounter[freqCount][signalStrengthCount];
1582                 for (int freq = 0; freq < freqCount; freq++) {
1583                     for (int strength = 0; strength < signalStrengthCount; strength++) {
1584                         mPerStateTxDurationMs[freq][strength] = new LongSamplingCounter(timeBase);
1585                     }
1586                 }
1587             }
1588             if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
1589                 Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
1590                         + ") requested in getTxDurationCounter");
1591                 return null;
1592             }
1593             if (signalStrength < 0 || signalStrength >= perStateTimers[0].length) {
1594                 Slog.w(TAG, "Unexpected signal strength (" + signalStrength
1595                         + ") requested in getTxDurationCounter");
1596                 return null;
1597             }
1598             return mPerStateTxDurationMs[frequencyRange][signalStrength];
1599         }
1600 
getRxDurationCounter( @erviceState.FrequencyRange int frequencyRange, boolean make)1601         private LongSamplingCounter getRxDurationCounter(
1602                 @ServiceState.FrequencyRange int frequencyRange, boolean make) {
1603             if (mPerFrequencyRxDurationMs == null) {
1604                 if (!make) return null;
1605 
1606                 final int freqCount = getFrequencyRangeCount();
1607                 final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
1608                 mPerFrequencyRxDurationMs = new LongSamplingCounter[freqCount];
1609                 for (int freq = 0; freq < freqCount; freq++) {
1610                     mPerFrequencyRxDurationMs[freq] = new LongSamplingCounter(timeBase);
1611                 }
1612             }
1613             if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
1614                 Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
1615                         + ") requested in getRxDurationCounter");
1616                 return null;
1617             }
1618             return mPerFrequencyRxDurationMs[frequencyRange];
1619         }
1620     }
1621 
1622     /**
1623      * Number of frequency ranges, keep in sync with {@link ServiceState.FrequencyRange}
1624      */
1625     private static final int NR_FREQUENCY_COUNT = 5;
1626 
1627     RadioAccessTechnologyBatteryStats[] mPerRatBatteryStats =
1628             new RadioAccessTechnologyBatteryStats[RADIO_ACCESS_TECHNOLOGY_COUNT];
1629 
1630     @GuardedBy("this")
getRatBatteryStatsLocked( @adioAccessTechnology int rat)1631     private RadioAccessTechnologyBatteryStats getRatBatteryStatsLocked(
1632             @RadioAccessTechnology int rat) {
1633         RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
1634         if (stats == null) {
1635             final int freqCount = rat == RADIO_ACCESS_TECHNOLOGY_NR ? NR_FREQUENCY_COUNT : 1;
1636             stats = new RadioAccessTechnologyBatteryStats(freqCount, mClock, mOnBatteryTimeBase);
1637             mPerRatBatteryStats[rat] = stats;
1638         }
1639         return stats;
1640     }
1641 
1642     final LongSamplingCounter[] mNetworkByteActivityCounters =
1643             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
1644 
1645     final LongSamplingCounter[] mNetworkPacketActivityCounters =
1646             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
1647 
1648     /**
1649      * The WiFi Overall wakelock timer
1650      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
1651      * since addition of per UID timers would not result in an accurate value due to overlapp of
1652      * per uid wakelock timers
1653      */
1654     StopwatchTimer mWifiMulticastWakelockTimer;
1655 
1656     /**
1657      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
1658      */
1659     ControllerActivityCounterImpl mWifiActivity;
1660 
1661     /**
1662      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
1663      */
1664     ControllerActivityCounterImpl mBluetoothActivity;
1665 
1666     /**
1667      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
1668      */
1669     ControllerActivityCounterImpl mModemActivity;
1670 
1671     /**
1672      * Whether the device supports WiFi controller energy reporting. This is set to true on
1673      * the first WiFi energy report. See {@link #mWifiActivity}.
1674      */
1675     boolean mHasWifiReporting = false;
1676 
1677     /**
1678      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
1679      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
1680      */
1681     boolean mHasBluetoothReporting = false;
1682 
1683     /**
1684      * Whether the device supports Modem controller energy reporting. This is set to true on
1685      * the first Modem energy report. See {@link #mModemActivity}.
1686      */
1687     boolean mHasModemReporting = false;
1688 
1689     boolean mWifiOn;
1690     StopwatchTimer mWifiOnTimer;
1691 
1692     boolean mGlobalWifiRunning;
1693     StopwatchTimer mGlobalWifiRunningTimer;
1694 
1695     int mWifiState = -1;
1696     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
1697 
1698     int mWifiSupplState = -1;
1699     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
1700 
1701     int mWifiSignalStrengthBin = -1;
1702     final StopwatchTimer[] mWifiSignalStrengthsTimer =
1703             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
1704 
1705     StopwatchTimer mWifiActiveTimer;
1706 
1707     int mBluetoothScanNesting;
1708     StopwatchTimer mBluetoothScanTimer;
1709 
1710     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1711     long mMobileRadioActiveStartTimeMs;
1712     StopwatchTimer mMobileRadioActiveTimer;
1713     StopwatchTimer mMobileRadioActivePerAppTimer;
1714     LongSamplingCounter mMobileRadioActiveAdjustedTime;
1715     LongSamplingCounter mMobileRadioActiveUnknownTime;
1716     LongSamplingCounter mMobileRadioActiveUnknownCount;
1717 
1718     /**
1719      * The soonest the Mobile Radio stats can be updated due to a mobile radio power state change
1720      * after it was last updated.
1721      */
1722     @VisibleForTesting
1723     protected static final long MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS = 1000 * 60 * 10;
1724 
1725     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1726 
1727     @GuardedBy("this")
1728     @VisibleForTesting
1729     protected @Nullable EnergyConsumerStats.Config mEnergyConsumerStatsConfig;
1730 
1731     /**
1732      * Accumulated global (generally, device-wide total) charge consumption of various consumers
1733      * while on battery.
1734      * Its '<b>custom</b> power buckets' correspond to the
1735      * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
1736      * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
1737      *
1738      * If energy consumer data is completely unavailable this will be null.
1739      */
1740     @GuardedBy("this")
1741     @VisibleForTesting
1742     @Nullable
1743     protected EnergyConsumerStats mGlobalEnergyConsumerStats;
1744     /** Bluetooth Power calculator for attributing bluetooth EnergyConsumer to uids */
1745     @Nullable BluetoothPowerCalculator mBluetoothPowerCalculator = null;
1746     /** Cpu Power calculator for attributing cpu EnergyConsumer to uids */
1747     @Nullable CpuPowerCalculator mCpuPowerCalculator = null;
1748     /** Mobile Radio Power calculator for attributing radio EnergyConsumer to uids */
1749     @Nullable MobileRadioPowerCalculator mMobileRadioPowerCalculator = null;
1750     /** Wifi Power calculator for attributing wifi EnergyConsumer to uids */
1751     @Nullable WifiPowerCalculator mWifiPowerCalculator = null;
1752 
1753     /**
1754      * These provide time bases that discount the time the device is plugged
1755      * in to power.
1756      */
1757     boolean mOnBattery;
1758     @VisibleForTesting
1759     protected boolean mOnBatteryInternal;
1760 
1761     /**
1762      * External reporting of whether the device is actually charging.
1763      */
1764     boolean mCharging = true;
1765 
1766     /*
1767      * These keep track of battery levels (1-100) at the last unplug event.
1768      */
1769     int mDischargeUnplugLevel;
1770     int mDischargePlugLevel;
1771     int mDischargeCurrentLevel;
1772     int mLowDischargeAmountSinceCharge;
1773     int mHighDischargeAmountSinceCharge;
1774     int mDischargeScreenOnUnplugLevel;
1775     int mDischargeScreenOffUnplugLevel;
1776     int mDischargeScreenDozeUnplugLevel;
1777     int mDischargeAmountScreenOn;
1778     int mDischargeAmountScreenOnSinceCharge;
1779     int mDischargeAmountScreenOff;
1780     int mDischargeAmountScreenOffSinceCharge;
1781     int mDischargeAmountScreenDoze;
1782     int mDischargeAmountScreenDozeSinceCharge;
1783 
1784     private LongSamplingCounter mDischargeScreenOffCounter;
1785     private LongSamplingCounter mDischargeScreenDozeCounter;
1786     private LongSamplingCounter mDischargeCounter;
1787     private LongSamplingCounter mDischargeLightDozeCounter;
1788     private LongSamplingCounter mDischargeDeepDozeCounter;
1789 
1790     static final int MAX_LEVEL_STEPS = 200;
1791 
1792     int mInitStepMode = 0;
1793     int mCurStepMode = 0;
1794     int mModStepMode = 0;
1795 
1796     int mLastDischargeStepLevel;
1797     int mMinDischargeStepLevel;
1798     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1799     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1800     ArrayList<PackageChange> mDailyPackageChanges;
1801 
1802     int mLastChargeStepLevel;
1803     int mMaxChargeStepLevel;
1804     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1805     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1806 
1807     static final int MAX_DAILY_ITEMS = 10;
1808 
1809     long mDailyStartTimeMs = 0;
1810     long mNextMinDailyDeadlineMs = 0;
1811     long mNextMaxDailyDeadlineMs = 0;
1812 
1813     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
1814 
1815     long mLastWriteTimeMs = 0; // Milliseconds
1816 
1817     private int mPhoneServiceState = -1;
1818     private int mPhoneServiceStateRaw = -1;
1819     private int mPhoneSimStateRaw = -1;
1820 
1821     private int mNumConnectivityChange;
1822 
1823     private int mEstimatedBatteryCapacityMah = -1;
1824 
1825     private int mLastLearnedBatteryCapacityUah = -1;
1826     private int mMinLearnedBatteryCapacityUah = -1;
1827     private int mMaxLearnedBatteryCapacityUah = -1;
1828 
1829     private long mBatteryTimeToFullSeconds = -1;
1830 
1831     private long[] mTmpCpuTimeInFreq;
1832 
1833     /**
1834      * Times spent by the system server threads handling incoming binder requests.
1835      */
1836     private LongSamplingCounterArray mBinderThreadCpuTimesUs;
1837 
1838     private final PowerProfile mPowerProfile;
1839 
1840     @VisibleForTesting
1841     @GuardedBy("this")
1842     protected final Constants mConstants;
1843 
1844     @VisibleForTesting
1845     protected final BatteryStatsConfig mBatteryStatsConfig;
1846 
1847     @GuardedBy("this")
1848     private AlarmManager mAlarmManager = null;
1849 
1850     private final AlarmManager.OnAlarmListener mLongPlugInAlarmHandler = () ->
1851             mHandler.post(() -> {
1852                 synchronized (BatteryStatsImpl.this) {
1853                     maybeResetWhilePluggedInLocked();
1854                 }
1855             });
1856 
1857     /*
1858      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
1859      * recording their times when on-battery (regardless of screen state).
1860      */
1861     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
1862     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
1863     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
1864 
1865     @Override
getRpmStats()1866     public Map<String, ? extends Timer> getRpmStats() {
1867         return mRpmStats;
1868     }
1869 
1870     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
1871     @Override
getScreenOffRpmStats()1872     public Map<String, ? extends Timer> getScreenOffRpmStats() {
1873         return mScreenOffRpmStats;
1874     }
1875 
1876     /*
1877      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
1878      */
1879     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
1880 
getKernelWakelockStats()1881     public Map<String, ? extends Timer> getKernelWakelockStats() {
1882         return mKernelWakelockStats;
1883     }
1884 
1885     @Override
getWakeLockStats()1886     public WakeLockStats getWakeLockStats() {
1887         final long realtimeMs = mClock.elapsedRealtime();
1888         List<WakeLockStats.WakeLock> uidWakeLockStats = new ArrayList<>();
1889         List<WakeLockStats.WakeLock> uidAggregatedWakeLockStats = new ArrayList<>();
1890         for (int i = mUidStats.size() - 1; i >= 0; i--) {
1891             final Uid uid = mUidStats.valueAt(i);
1892 
1893             // Converts unaggregated wakelocks.
1894             final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats =
1895                     uid.mWakelockStats.getMap();
1896             for (int j = wakelockStats.size() - 1; j >= 0; j--) {
1897                 final String name = wakelockStats.keyAt(j);
1898                 final Uid.Wakelock wakelock = (Uid.Wakelock) wakelockStats.valueAt(j);
1899                 final WakeLockStats.WakeLock wakeLockItem =
1900                         createWakeLock(uid, name, /* isAggregated= */ false, wakelock.mTimerPartial,
1901                                 realtimeMs);
1902                 if (wakeLockItem != null) {
1903                     uidWakeLockStats.add(wakeLockItem);
1904                 }
1905             }
1906 
1907             // Converts aggregated wakelocks.
1908             final WakeLockStats.WakeLock aggregatedWakeLockItem =
1909                     createWakeLock(
1910                     uid,
1911                     WakeLockStats.WakeLock.NAME_AGGREGATED,
1912                     /* isAggregated= */ true,
1913                     uid.mAggregatedPartialWakelockTimer,
1914                     realtimeMs);
1915             if (aggregatedWakeLockItem != null) {
1916                 uidAggregatedWakeLockStats.add(aggregatedWakeLockItem);
1917             }
1918         }
1919         return new WakeLockStats(uidWakeLockStats, uidAggregatedWakeLockStats);
1920     }
1921 
1922     // Returns a valid {@code WakeLockStats.WakeLock} or null.
createWakeLock( Uid uid, String name, boolean isAggregated, DualTimer timer, final long realtimeMs)1923     private WakeLockStats.WakeLock createWakeLock(
1924             Uid uid, String name, boolean isAggregated, DualTimer timer, final long realtimeMs) {
1925         if (timer == null) {
1926             return null;
1927         }
1928         // Uses the primary timer for total wakelock data and used the sub timer for background
1929         // wakelock data.
1930         final WakeLockStats.WakeLockData totalWakeLockData = createWakeLockData(timer, realtimeMs);
1931         final WakeLockStats.WakeLockData backgroundWakeLockData =
1932                 createWakeLockData(timer.getSubTimer(), realtimeMs);
1933 
1934         return WakeLockStats.WakeLock.isDataValid(totalWakeLockData, backgroundWakeLockData)
1935                 ? new WakeLockStats.WakeLock(
1936                 uid.getUid(),
1937                 name,
1938                 isAggregated,
1939                 totalWakeLockData,
1940                 backgroundWakeLockData) : null;
1941     }
1942 
1943     @NonNull
createWakeLockData( DurationTimer timer, final long realtimeMs)1944     private WakeLockStats.WakeLockData createWakeLockData(
1945             DurationTimer timer, final long realtimeMs) {
1946         if (timer == null) {
1947             return WakeLockStats.WakeLockData.EMPTY;
1948         }
1949         final long totalTimeLockHeldMs =
1950                 timer.getTotalTimeLocked(realtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
1951         if (totalTimeLockHeldMs == 0) {
1952             return WakeLockStats.WakeLockData.EMPTY;
1953         }
1954         return new WakeLockStats.WakeLockData(
1955             timer.getCountLocked(STATS_SINCE_CHARGED),
1956             totalTimeLockHeldMs,
1957             timer.isRunningLocked() ? timer.getCurrentDurationMsLocked(realtimeMs) : 0);
1958     }
1959 
1960     @Override
1961     @GuardedBy("this")
getBluetoothBatteryStats()1962     public BluetoothBatteryStats getBluetoothBatteryStats() {
1963         final long elapsedRealtimeUs = mClock.elapsedRealtime() * 1000;
1964         ArrayList<BluetoothBatteryStats.UidStats> uidStats = new ArrayList<>();
1965         for (int i = mUidStats.size() - 1; i >= 0; i--) {
1966             final Uid uid = mUidStats.valueAt(i);
1967             final Timer scanTimer = uid.getBluetoothScanTimer();
1968             final long scanTimeMs =
1969                     scanTimer != null ? scanTimer.getTotalTimeLocked(
1970                             elapsedRealtimeUs, STATS_SINCE_CHARGED) / 1000 : 0;
1971 
1972             final Timer unoptimizedScanTimer = uid.getBluetoothUnoptimizedScanTimer();
1973             final long unoptimizedScanTimeMs =
1974                     unoptimizedScanTimer != null ? unoptimizedScanTimer.getTotalTimeLocked(
1975                             elapsedRealtimeUs, STATS_SINCE_CHARGED) / 1000 : 0;
1976 
1977             final Counter scanResultCounter = uid.getBluetoothScanResultCounter();
1978             final int scanResultCount =
1979                     scanResultCounter != null ? scanResultCounter.getCountLocked(
1980                             STATS_SINCE_CHARGED) : 0;
1981 
1982             final ControllerActivityCounter counter = uid.getBluetoothControllerActivity();
1983             final long rxTimeMs =  counter != null ? counter.getRxTimeCounter().getCountLocked(
1984                     STATS_SINCE_CHARGED) : 0;
1985             final long txTimeMs =  counter != null ? counter.getTxTimeCounters()[0].getCountLocked(
1986                     STATS_SINCE_CHARGED) : 0;
1987 
1988             if (scanTimeMs != 0 || unoptimizedScanTimeMs != 0 || scanResultCount != 0
1989                     || rxTimeMs != 0 || txTimeMs != 0) {
1990                 uidStats.add(new BluetoothBatteryStats.UidStats(uid.getUid(),
1991                         scanTimeMs,
1992                         unoptimizedScanTimeMs,
1993                         scanResultCount,
1994                         rxTimeMs,
1995                         txTimeMs));
1996             }
1997         }
1998 
1999         return new BluetoothBatteryStats(uidStats);
2000     }
2001 
2002     String mLastWakeupReason = null;
2003     long mLastWakeupUptimeMs = 0;
2004     long mLastWakeupElapsedTimeMs = 0;
2005     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
2006 
getWakeupReasonStats()2007     public Map<String, ? extends Timer> getWakeupReasonStats() {
2008         return mWakeupReasonStats;
2009     }
2010 
2011     @Override
getUahDischarge(int which)2012     public long getUahDischarge(int which) {
2013         return mDischargeCounter.getCountLocked(which);
2014     }
2015 
2016     @Override
getUahDischargeScreenOff(int which)2017     public long getUahDischargeScreenOff(int which) {
2018         return mDischargeScreenOffCounter.getCountLocked(which);
2019     }
2020 
2021     @Override
getUahDischargeScreenDoze(int which)2022     public long getUahDischargeScreenDoze(int which) {
2023         return mDischargeScreenDozeCounter.getCountLocked(which);
2024     }
2025 
2026     @Override
getUahDischargeLightDoze(int which)2027     public long getUahDischargeLightDoze(int which) {
2028         return mDischargeLightDozeCounter.getCountLocked(which);
2029     }
2030 
2031     @Override
getUahDischargeDeepDoze(int which)2032     public long getUahDischargeDeepDoze(int which) {
2033         return mDischargeDeepDozeCounter.getCountLocked(which);
2034     }
2035 
2036     @Override
getEstimatedBatteryCapacity()2037     public int getEstimatedBatteryCapacity() {
2038         return mEstimatedBatteryCapacityMah;
2039     }
2040 
2041     @Override
getLearnedBatteryCapacity()2042     public int getLearnedBatteryCapacity() {
2043         return mLastLearnedBatteryCapacityUah;
2044     }
2045 
2046     @Override
getMinLearnedBatteryCapacity()2047     public int getMinLearnedBatteryCapacity() {
2048         return mMinLearnedBatteryCapacityUah;
2049     }
2050 
2051     @Override
getMaxLearnedBatteryCapacity()2052     public int getMaxLearnedBatteryCapacity() {
2053         return mMaxLearnedBatteryCapacityUah;
2054     }
2055 
2056     public static class FrameworkStatsLogger {
uidProcessStateChanged(int uid, int state)2057         public void uidProcessStateChanged(int uid, int state) {
2058             // TODO(b/155216561): It is possible for isolated uids to be in a higher
2059             // state than its parent uid. We should track the highest state within the union of host
2060             // and isolated uids rather than only the parent uid.
2061             FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
2062                     ActivityManager.processStateAmToProto(state));
2063         }
2064 
wakelockStateChanged(int uid, WorkChain wc, String name, int procState, boolean acquired, int powerManagerWakeLockLevel)2065         public void wakelockStateChanged(int uid, WorkChain wc, String name,
2066                 int procState, boolean acquired, int powerManagerWakeLockLevel) {
2067             int event = acquired
2068                     ? FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE
2069                     : FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE;
2070             if (wc != null) {
2071                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
2072                         wc.getTags(), powerManagerWakeLockLevel, name, event, procState);
2073             } else {
2074                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, uid,
2075                         null, powerManagerWakeLockLevel, name, event, procState);
2076             }
2077         }
2078 
kernelWakeupReported(long deltaUptimeUs, String lastWakeupReason, long lastWakeupElapsedTimeMs)2079         public void kernelWakeupReported(long deltaUptimeUs, String lastWakeupReason,
2080                 long lastWakeupElapsedTimeMs) {
2081             FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, lastWakeupReason,
2082                     /* duration_usec */ deltaUptimeUs, lastWakeupElapsedTimeMs);
2083         }
2084 
gpsScanStateChanged(int uid, WorkChain workChain, boolean stateOn)2085         public void gpsScanStateChanged(int uid, WorkChain workChain, boolean stateOn) {
2086             int event = stateOn
2087                     ? FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON
2088                     : FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF;
2089             if (workChain != null) {
2090                 FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
2091                         workChain.getUids(), workChain.getTags(), event);
2092             } else {
2093                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
2094                         uid, null, event);
2095             }
2096         }
2097 
batterySaverModeChanged(boolean enabled)2098         public void batterySaverModeChanged(boolean enabled) {
2099             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
2100                     enabled
2101                             ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
2102                             : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
2103         }
2104 
deviceIdlingModeStateChanged(int mode)2105         public void deviceIdlingModeStateChanged(int mode) {
2106             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, mode);
2107         }
2108 
deviceIdleModeStateChanged(int mode)2109         public void deviceIdleModeStateChanged(int mode) {
2110             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
2111         }
2112 
chargingStateChanged(int status)2113         public void chargingStateChanged(int status) {
2114             FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
2115         }
2116 
pluggedStateChanged(int plugType)2117         public void pluggedStateChanged(int plugType) {
2118             FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
2119         }
2120 
batteryLevelChanged(int level)2121         public void batteryLevelChanged(int level) {
2122             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
2123         }
2124 
phoneServiceStateChanged(int state, int simState, int strengthBin)2125         public void phoneServiceStateChanged(int state, int simState, int strengthBin) {
2126             FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
2127                     simState, strengthBin);
2128         }
2129 
phoneSignalStrengthChanged(int strengthBin)2130         public void phoneSignalStrengthChanged(int strengthBin) {
2131             FrameworkStatsLog.write(
2132                     FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
2133         }
2134 
2135         /**
2136          * Records a statsd event when the batterystats config file is written to disk.
2137          */
writeCommitSysConfigFile(String fileName, long durationMs)2138         public void writeCommitSysConfigFile(String fileName, long durationMs) {
2139             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(fileName,
2140                     durationMs);
2141         }
2142     }
2143 
2144     private final FrameworkStatsLogger mFrameworkStatsLogger;
2145 
initKernelStatsReaders()2146     private void initKernelStatsReaders() {
2147         if (!isKernelStatsAvailable()) {
2148             return;
2149         }
2150 
2151         mCpuUidUserSysTimeReader = new KernelCpuUidUserSysTimeReader(true, mClock);
2152         mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(true, mClock);
2153         mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(true, mClock);
2154         mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(true, mClock);
2155         mKernelWakelockReader = new KernelWakelockReader();
2156         if (!Flags.disableSystemServicePowerAttr()) {
2157             mSystemServerCpuThreadReader = SystemServerCpuThreadReader.create();
2158         }
2159         mKernelMemoryBandwidthStats = new KernelMemoryBandwidthStats();
2160         mTmpRailStats = new RailStats();
2161     }
2162 
2163     private class PowerStatsCollectorInjector implements CpuPowerStatsCollector.Injector,
2164             ScreenPowerStatsCollector.Injector, MobileRadioPowerStatsCollector.Injector,
2165             WifiPowerStatsCollector.Injector, BluetoothPowerStatsCollector.Injector,
2166             EnergyConsumerPowerStatsCollector.Injector, WakelockPowerStatsCollector.Injector {
2167         private PackageManager mPackageManager;
2168         private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
2169         private NetworkStatsManager mNetworkStatsManager;
2170         private TelephonyManager mTelephonyManager;
2171         private WifiManager mWifiManager;
2172         private BluetoothPowerStatsCollector.BluetoothStatsRetriever mBluetoothStatsRetriever;
2173 
2174         @SuppressLint("WifiManagerPotentialLeak")
setContext(Context context)2175         void setContext(Context context) {
2176             mPackageManager = context.getPackageManager();
2177             mConsumedEnergyRetriever = new PowerStatsCollector.ConsumedEnergyRetrieverImpl(
2178                     LocalServices.getService(PowerStatsInternal.class), () -> mBatteryVoltageMv);
2179             mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
2180             mTelephonyManager =
2181                     (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
2182             mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
2183             mBluetoothStatsRetriever = new BluetoothStatsRetrieverImpl(
2184                     context.getSystemService(BluetoothManager.class));
2185         }
2186 
2187         @Override
getHandler()2188         public Handler getHandler() {
2189             return mHandler;
2190         }
2191 
2192         @Override
getClock()2193         public Clock getClock() {
2194             return mClock;
2195         }
2196 
2197         @Override
getPowerStatsCollectionThrottlePeriod(String powerComponentName)2198         public long getPowerStatsCollectionThrottlePeriod(String powerComponentName) {
2199             return mBatteryStatsConfig.getPowerStatsThrottlePeriod(powerComponentName);
2200         }
2201 
2202         @Override
getUidResolver()2203         public PowerStatsUidResolver getUidResolver() {
2204             return mPowerStatsUidResolver;
2205         }
2206 
2207         @Override
getCpuScalingPolicies()2208         public CpuScalingPolicies getCpuScalingPolicies() {
2209             return mCpuScalingPolicies;
2210         }
2211 
2212         @Override
getPowerProfile()2213         public PowerProfile getPowerProfile() {
2214             return mPowerProfile;
2215         }
2216 
2217         @Override
getKernelCpuStatsReader()2218         public CpuPowerStatsCollector.KernelCpuStatsReader getKernelCpuStatsReader() {
2219             return new CpuPowerStatsCollector.KernelCpuStatsReader();
2220         }
2221 
2222         @Override
getPackageManager()2223         public PackageManager getPackageManager() {
2224             return mPackageManager;
2225         }
2226 
2227         @Override
getConsumedEnergyRetriever()2228         public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
2229             return mConsumedEnergyRetriever;
2230         }
2231 
2232         @Override
getScreenUsageTimeRetriever()2233         public ScreenPowerStatsCollector.ScreenUsageTimeRetriever getScreenUsageTimeRetriever() {
2234             return mScreenUsageTimeRetriever;
2235         }
2236 
2237         @Override
getDisplayCount()2238         public int getDisplayCount() {
2239             return BatteryStatsImpl.this.getDisplayCount();
2240         }
2241 
2242         @Override
getMobileNetworkStatsSupplier()2243         public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
2244             return () -> readMobileNetworkStatsLocked(mNetworkStatsManager);
2245         }
2246 
2247         @Override
getWifiNetworkStatsSupplier()2248         public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
2249             return () -> readWifiNetworkStatsLocked(mNetworkStatsManager);
2250         }
2251 
2252         @Override
getWifiStatsRetriever()2253         public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
2254             return mWifiStatsRetriever;
2255         }
2256 
2257         @Override
getTelephonyManager()2258         public TelephonyManager getTelephonyManager() {
2259             return mTelephonyManager;
2260         }
2261 
2262         @Override
getWifiManager()2263         public WifiManager getWifiManager() {
2264             return mWifiManager;
2265         }
2266 
2267         @Override
getBluetoothStatsRetriever()2268         public BluetoothPowerStatsCollector.BluetoothStatsRetriever getBluetoothStatsRetriever() {
2269             return mBluetoothStatsRetriever;
2270         }
2271 
2272         @Override
getCallDurationSupplier()2273         public LongSupplier getCallDurationSupplier() {
2274             return () -> mPhoneOnTimer.getTotalTimeLocked(mClock.elapsedRealtime() * 1000,
2275                     STATS_SINCE_CHARGED) / 1000;
2276         }
2277 
2278         @Override
getPhoneSignalScanDurationSupplier()2279         public LongSupplier getPhoneSignalScanDurationSupplier() {
2280             return () -> mPhoneSignalScanningTimer.getTotalTimeLocked(
2281                     mClock.elapsedRealtime() * 1000, STATS_SINCE_CHARGED) / 1000;
2282         }
2283 
2284         @Override
2285         public WakelockPowerStatsCollector.WakelockDurationRetriever
getWakelockDurationRetriever()2286                 getWakelockDurationRetriever() {
2287             return mWakelockDurationRetriever;
2288         }
2289 
2290         @Override
networkStatsDelta(NetworkStats stats, NetworkStats oldStats)2291         public NetworkStats networkStatsDelta(NetworkStats stats, NetworkStats oldStats) {
2292             return BatteryStatsImpl.this.networkStatsDelta(stats, oldStats);
2293         }
2294     }
2295 
2296     private final PowerStatsCollectorInjector mPowerStatsCollectorInjector =
2297             new PowerStatsCollectorInjector();
2298 
2299     /**
2300      * TimeBase observer.
2301      */
2302     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2303         void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2304         void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
2305 
2306         /**
2307          * Reset the observer's state, returns true if the timer/counter is inactive
2308          * so it can be destroyed.
2309          * @param detachIfReset detach if true, no-op if false.
2310          * @return Returns true if the timer/counter is inactive and can be destroyed.
2311          */
reset(boolean detachIfReset)2312         default boolean reset(boolean detachIfReset) {
2313             return reset(detachIfReset, SystemClock.elapsedRealtime() * 1000);
2314         }
2315 
2316         /**
2317          * @see #reset(boolean)
2318          * @param detachIfReset detach if true, no-op if false.
2319          * @param elapsedRealtimeUs the timestamp when this reset is actually reequested
2320          * @return Returns true if the timer/counter is inactive and can be destroyed.
2321          */
reset(boolean detachIfReset, long elapsedRealtimeUs)2322         boolean reset(boolean detachIfReset, long elapsedRealtimeUs);
2323 
2324         /**
2325          * Detach the observer from TimeBase.
2326          */
detach()2327         void detach();
2328     }
2329 
2330     // methods are protected not private to be VisibleForTesting
2331     public static class TimeBase {
2332         protected final Collection<TimeBaseObs> mObservers;
2333 
2334         // All below time metrics are in microseconds.
2335         protected long mUptimeUs;
2336         protected long mRealtimeUs;
2337 
2338         protected boolean mRunning;
2339 
2340         protected long mPastUptimeUs;
2341         protected long mUptimeStartUs;
2342         protected long mPastRealtimeUs;
2343         protected long mRealtimeStartUs;
2344         protected long mUnpluggedUptimeUs;
2345         protected long mUnpluggedRealtimeUs;
2346 
dump(PrintWriter pw, String prefix)2347         public void dump(PrintWriter pw, String prefix) {
2348             StringBuilder sb = new StringBuilder(128);
2349             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
2350             sb.setLength(0);
2351             sb.append(prefix);
2352                     sb.append("mUptime=");
2353                     formatTimeMs(sb, mUptimeUs / 1000);
2354             pw.println(sb.toString());
2355             sb.setLength(0);
2356             sb.append(prefix);
2357                     sb.append("mRealtime=");
2358                     formatTimeMs(sb, mRealtimeUs / 1000);
2359             pw.println(sb.toString());
2360             sb.setLength(0);
2361             sb.append(prefix);
2362                     sb.append("mPastUptime=");
2363                     formatTimeMs(sb, mPastUptimeUs / 1000); sb.append("mUptimeStart=");
2364                     formatTimeMs(sb, mUptimeStartUs / 1000);
2365                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptimeUs / 1000);
2366             pw.println(sb.toString());
2367             sb.setLength(0);
2368             sb.append(prefix);
2369                     sb.append("mPastRealtime=");
2370                     formatTimeMs(sb, mPastRealtimeUs / 1000); sb.append("mRealtimeStart=");
2371                     formatTimeMs(sb, mRealtimeStartUs / 1000);
2372                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtimeUs / 1000);
2373             pw.println(sb.toString());
2374         }
2375         /**
2376          * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
2377          * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
2378          * entries.
2379          * mObservers must have good performance on add(), remove(), also be memory efficient.
2380          * This is why we provide isLongList parameter for long and short list user cases.
2381          * @param isLongList If true, use HashSet for mObservers list.
2382          *                   If false, use ArrayList for mObservers list.
2383         */
TimeBase(boolean isLongList)2384         public TimeBase(boolean isLongList) {
2385             mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
2386         }
2387 
TimeBase()2388         public TimeBase() {
2389             this(false);
2390         }
2391 
add(TimeBaseObs observer)2392         public void add(TimeBaseObs observer) {
2393             mObservers.add(observer);
2394         }
2395 
remove(TimeBaseObs observer)2396         public void remove(TimeBaseObs observer) {
2397             mObservers.remove(observer);
2398         }
2399 
hasObserver(TimeBaseObs observer)2400         public boolean hasObserver(TimeBaseObs observer) {
2401             return mObservers.contains(observer);
2402         }
2403 
init(long uptimeUs, long elapsedRealtimeUs)2404         public void init(long uptimeUs, long elapsedRealtimeUs) {
2405             mRealtimeUs = 0;
2406             mUptimeUs = 0;
2407             mPastUptimeUs = 0;
2408             mPastRealtimeUs = 0;
2409             mUptimeStartUs = uptimeUs;
2410             mRealtimeStartUs = elapsedRealtimeUs;
2411             mUnpluggedUptimeUs = getUptime(mUptimeStartUs);
2412             mUnpluggedRealtimeUs = getRealtime(mRealtimeStartUs);
2413         }
2414 
reset(long uptimeUs, long elapsedRealtimeUs)2415         public void reset(long uptimeUs, long elapsedRealtimeUs) {
2416             if (!mRunning) {
2417                 mPastUptimeUs = 0;
2418                 mPastRealtimeUs = 0;
2419             } else {
2420                 mUptimeStartUs = uptimeUs;
2421                 mRealtimeStartUs = elapsedRealtimeUs;
2422                 // TODO: Since mUptimeStartUs was just reset and we are running, getUptime will
2423                 // just return mPastUptimeUs. Also, are we sure we don't want to reset that?
2424                 mUnpluggedUptimeUs = getUptime(uptimeUs);
2425                 // TODO: likewise.
2426                 mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
2427             }
2428         }
2429 
computeUptime(long curTimeUs, int which)2430         public long computeUptime(long curTimeUs, int which) {
2431             return mUptimeUs + getUptime(curTimeUs);
2432         }
2433 
computeRealtime(long curTimeUs, int which)2434         public long computeRealtime(long curTimeUs, int which) {
2435             return mRealtimeUs + getRealtime(curTimeUs);
2436         }
2437 
getUptime(long curTimeUs)2438         public long getUptime(long curTimeUs) {
2439             long time = mPastUptimeUs;
2440             if (mRunning) {
2441                 time += curTimeUs - mUptimeStartUs;
2442             }
2443             return time;
2444         }
2445 
getRealtime(long curTimeUs)2446         public long getRealtime(long curTimeUs) {
2447             long time = mPastRealtimeUs;
2448             if (mRunning) {
2449                 time += curTimeUs - mRealtimeStartUs;
2450             }
2451             return time;
2452         }
2453 
getUptimeStart()2454         public long getUptimeStart() {
2455             return mUptimeStartUs;
2456         }
2457 
getRealtimeStart()2458         public long getRealtimeStart() {
2459             return mRealtimeStartUs;
2460         }
2461 
isRunning()2462         public boolean isRunning() {
2463             return mRunning;
2464         }
2465 
setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs)2466         public boolean setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs) {
2467             if (mRunning != running) {
2468                 mRunning = running;
2469                 if (running) {
2470                     mUptimeStartUs = uptimeUs;
2471                     mRealtimeStartUs = elapsedRealtimeUs;
2472                     long batteryUptimeUs = mUnpluggedUptimeUs = getUptime(uptimeUs);
2473                     long batteryRealtimeUs = mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
2474                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
2475                     // Iterator object, here is an exception because mObservers' type is Collection
2476                     // instead of list.
2477                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
2478                     while (iter.hasNext()) {
2479                         iter.next().onTimeStarted(
2480                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
2481                     }
2482                 } else {
2483                     mPastUptimeUs += uptimeUs - mUptimeStartUs;
2484                     mPastRealtimeUs += elapsedRealtimeUs - mRealtimeStartUs;
2485                     long batteryUptimeUs = getUptime(uptimeUs);
2486                     long batteryRealtimeUs = getRealtime(elapsedRealtimeUs);
2487                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
2488                     // Iterator object, here is an exception because mObservers' type is Collection
2489                     // instead of list.
2490                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
2491                     while (iter.hasNext()) {
2492                         iter.next().onTimeStopped(
2493                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
2494                     }
2495                 }
2496                 return true;
2497             }
2498             return false;
2499         }
2500 
readSummaryFromParcel(Parcel in)2501         public void readSummaryFromParcel(Parcel in) {
2502             mUptimeUs = in.readLong();
2503             mRealtimeUs = in.readLong();
2504         }
2505 
writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)2506         public void writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
2507             out.writeLong(computeUptime(uptimeUs, STATS_SINCE_CHARGED));
2508             out.writeLong(computeRealtime(elapsedRealtimeUs, STATS_SINCE_CHARGED));
2509         }
2510 
readFromParcel(Parcel in)2511         public void readFromParcel(Parcel in) {
2512             mRunning = false;
2513             mUptimeUs = in.readLong();
2514             mPastUptimeUs = in.readLong();
2515             mUptimeStartUs = in.readLong();
2516             mRealtimeUs = in.readLong();
2517             mPastRealtimeUs = in.readLong();
2518             mRealtimeStartUs = in.readLong();
2519             mUnpluggedUptimeUs = in.readLong();
2520             mUnpluggedRealtimeUs = in.readLong();
2521         }
2522 
writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)2523         public void writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
2524             final long runningUptime = getUptime(uptimeUs);
2525             final long runningRealtime = getRealtime(elapsedRealtimeUs);
2526             out.writeLong(mUptimeUs);
2527             out.writeLong(runningUptime);
2528             out.writeLong(mUptimeStartUs);
2529             out.writeLong(mRealtimeUs);
2530             out.writeLong(runningRealtime);
2531             out.writeLong(mRealtimeStartUs);
2532             out.writeLong(mUnpluggedUptimeUs);
2533             out.writeLong(mUnpluggedRealtimeUs);
2534         }
2535     }
2536 
2537     /**
2538      * State for keeping track of counting information.
2539      */
2540     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
2541         final AtomicInteger mCount = new AtomicInteger();
2542         final TimeBase mTimeBase;
2543 
Counter(TimeBase timeBase, Parcel in)2544         public Counter(TimeBase timeBase, Parcel in) {
2545             mTimeBase = timeBase;
2546             mCount.set(in.readInt());
2547             timeBase.add(this);
2548         }
2549 
Counter(TimeBase timeBase)2550         public Counter(TimeBase timeBase) {
2551             mTimeBase = timeBase;
2552             timeBase.add(this);
2553         }
2554 
writeToParcel(Parcel out)2555         public void writeToParcel(Parcel out) {
2556             out.writeInt(mCount.get());
2557         }
2558 
2559         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2560         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2561         }
2562 
2563         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2564         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2565         }
2566 
2567         @Override
getCountLocked(int which)2568         public int getCountLocked(int which) {
2569             return mCount.get();
2570         }
2571 
logState(Printer pw, String prefix)2572         public void logState(Printer pw, String prefix) {
2573             pw.println(prefix + "mCount=" + mCount.get());
2574         }
2575 
2576         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()2577         public void stepAtomic() {
2578             if (mTimeBase.isRunning()) {
2579                 mCount.incrementAndGet();
2580             }
2581         }
2582 
addAtomic(int delta)2583         void addAtomic(int delta) {
2584             if (mTimeBase.isRunning()) {
2585                 mCount.addAndGet(delta);
2586             }
2587         }
2588 
2589         /**
2590          * Clear state of this counter.
2591          */
2592         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2593         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2594             mCount.set(0);
2595             if (detachIfReset) {
2596                 detach();
2597             }
2598             return true;
2599         }
2600 
2601         @Override
detach()2602         public void detach() {
2603             mTimeBase.remove(this);
2604         }
2605 
2606         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)2607         public void writeSummaryFromParcelLocked(Parcel out) {
2608             out.writeInt(mCount.get());
2609         }
2610 
2611         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)2612         public void readSummaryFromParcelLocked(Parcel in) {
2613             mCount.set(in.readInt());
2614         }
2615     }
2616 
2617     @VisibleForTesting
2618     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
2619         final TimeBase mTimeBase;
2620         public long[] mCounts;
2621 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)2622         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
2623             mTimeBase = timeBase;
2624             mCounts = in.createLongArray();
2625             timeBase.add(this);
2626         }
2627 
LongSamplingCounterArray(TimeBase timeBase)2628         public LongSamplingCounterArray(TimeBase timeBase) {
2629             mTimeBase = timeBase;
2630             timeBase.add(this);
2631         }
2632 
writeToParcel(Parcel out)2633         private void writeToParcel(Parcel out) {
2634             out.writeLongArray(mCounts);
2635         }
2636 
2637         @Override
onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs)2638         public void onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs) {
2639         }
2640 
2641         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2642         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2643         }
2644 
2645         @Override
getCountsLocked(int which)2646         public long[] getCountsLocked(int which) {
2647             return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
2648         }
2649 
2650         @Override
logState(Printer pw, String prefix)2651         public void logState(Printer pw, String prefix) {
2652             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
2653         }
2654 
addCountLocked(long[] counts)2655         public void addCountLocked(long[] counts) {
2656             addCountLocked(counts, mTimeBase.isRunning());
2657         }
2658 
addCountLocked(long[] counts, boolean isRunning)2659         public void addCountLocked(long[] counts, boolean isRunning) {
2660             if (counts == null) {
2661                 return;
2662             }
2663             if (isRunning) {
2664                 if (mCounts == null) {
2665                     mCounts = new long[counts.length];
2666                 }
2667                 for (int i = 0; i < counts.length; ++i) {
2668                     mCounts[i] += counts[i];
2669                 }
2670             }
2671         }
2672 
getSize()2673         public int getSize() {
2674             return mCounts == null ? 0 : mCounts.length;
2675         }
2676 
2677         /**
2678          * Clear state of this counter.
2679          */
2680         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2681         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2682             if (mCounts != null) {
2683                 Arrays.fill(mCounts, 0);
2684             }
2685             if (detachIfReset) {
2686                 detach();
2687             }
2688             return true;
2689         }
2690 
2691         @Override
detach()2692         public void detach() {
2693             mTimeBase.remove(this);
2694         }
2695 
writeSummaryToParcelLocked(Parcel out)2696         private void writeSummaryToParcelLocked(Parcel out) {
2697             out.writeLongArray(mCounts);
2698         }
2699 
readSummaryFromParcelLocked(Parcel in)2700         private void readSummaryFromParcelLocked(Parcel in) {
2701             mCounts = in.createLongArray();
2702         }
2703 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)2704         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
2705             if (counterArray != null) {
2706                 out.writeInt(1);
2707                 counterArray.writeToParcel(out);
2708             } else {
2709                 out.writeInt(0);
2710             }
2711         }
2712 
readFromParcel(Parcel in, TimeBase timeBase)2713         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
2714             if (in.readInt() != 0) {
2715                 return new LongSamplingCounterArray(timeBase, in);
2716             } else {
2717                 return null;
2718             }
2719         }
2720 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)2721         public static void writeSummaryToParcelLocked(Parcel out,
2722                 LongSamplingCounterArray counterArray) {
2723             if (counterArray != null) {
2724                 out.writeInt(1);
2725                 counterArray.writeSummaryToParcelLocked(out);
2726             } else {
2727                 out.writeInt(0);
2728             }
2729         }
2730 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)2731         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
2732                 TimeBase timeBase) {
2733             if (in.readInt() != 0) {
2734                 final LongSamplingCounterArray counterArray
2735                         = new LongSamplingCounterArray(timeBase);
2736                 counterArray.readSummaryFromParcelLocked(in);
2737                 return counterArray;
2738             } else {
2739                 return null;
2740             }
2741         }
2742     }
2743 
2744     private static class TimeMultiStateCounter extends LongCounter implements TimeBaseObs {
2745         private final TimeBase mTimeBase;
2746         private final LongMultiStateCounter mCounter;
2747 
TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs)2748         private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) {
2749             this(timeBase, new LongMultiStateCounter(stateCount), timestampMs);
2750         }
2751 
TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter, long timestampMs)2752         private TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter,
2753                 long timestampMs) {
2754             mTimeBase = timeBase;
2755             mCounter = counter;
2756             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
2757             timeBase.add(this);
2758         }
2759 
2760         @Nullable
readFromParcel(Parcel in, TimeBase timeBase, int stateCount, long timestampMs)2761         private static TimeMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
2762                 int stateCount, long timestampMs) {
2763             LongMultiStateCounter counter = LongMultiStateCounter.CREATOR.createFromParcel(in);
2764             if (counter.getStateCount() != stateCount) {
2765                 return null;
2766             }
2767             return new TimeMultiStateCounter(timeBase, counter, timestampMs);
2768         }
2769 
writeToParcel(Parcel out)2770         private void writeToParcel(Parcel out) {
2771             mCounter.writeToParcel(out, 0);
2772         }
2773 
2774         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2775         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2776             mCounter.setEnabled(true, elapsedRealtimeUs / 1000);
2777         }
2778 
2779         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2780         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2781             mCounter.setEnabled(false, elapsedRealtimeUs / 1000);
2782         }
2783 
getStateCount()2784         public int getStateCount() {
2785             return mCounter.getStateCount();
2786         }
2787 
setState(@atteryConsumer.ProcessState int processState, long elapsedRealtimeMs)2788         private void setState(@BatteryConsumer.ProcessState int processState,
2789                 long elapsedRealtimeMs) {
2790             mCounter.setState(processState, elapsedRealtimeMs);
2791         }
2792 
update(long value, long timestampMs)2793         private long update(long value, long timestampMs) {
2794             return mCounter.updateValue(value, timestampMs);
2795         }
2796 
increment(long increment, long timestampMs)2797         private void increment(long increment, long timestampMs) {
2798             mCounter.incrementValue(increment, timestampMs);
2799         }
2800 
2801         /**
2802          * Returns accumulated count for the specified state.
2803          */
getCountForProcessState(@atteryConsumer.ProcessState int procState)2804         public long getCountForProcessState(@BatteryConsumer.ProcessState int procState) {
2805             return mCounter.getCount(procState);
2806         }
2807 
getTotalCountLocked()2808         public long getTotalCountLocked() {
2809             return mCounter.getTotalCount();
2810         }
2811 
2812         @Override
getCountLocked(int statsType)2813         public long getCountLocked(int statsType) {
2814             return getTotalCountLocked();
2815         }
2816 
2817         @Override
logState(Printer pw, String prefix)2818         public void logState(Printer pw, String prefix) {
2819             pw.println(prefix + "mCounter=" + mCounter);
2820         }
2821 
2822         /**
2823          * Clears state of this counter.
2824          */
2825         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2826         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2827             mCounter.reset();
2828             if (detachIfReset) {
2829                 detach();
2830             }
2831             return true;
2832         }
2833 
2834         @Override
detach()2835         public void detach() {
2836             mTimeBase.remove(this);
2837         }
2838     }
2839 
2840     private static class TimeInFreqMultiStateCounter implements TimeBaseObs {
2841         private final TimeBase mTimeBase;
2842         private final LongArrayMultiStateCounter mCounter;
2843 
TimeInFreqMultiStateCounter(TimeBase timeBase, int stateCount, int cpuFreqCount, long timestampMs)2844         private TimeInFreqMultiStateCounter(TimeBase timeBase, int stateCount, int cpuFreqCount,
2845                 long timestampMs) {
2846             this(timeBase, new LongArrayMultiStateCounter(stateCount, cpuFreqCount), timestampMs);
2847         }
2848 
TimeInFreqMultiStateCounter(TimeBase timeBase, LongArrayMultiStateCounter counter, long timestampMs)2849         private TimeInFreqMultiStateCounter(TimeBase timeBase, LongArrayMultiStateCounter counter,
2850                 long timestampMs) {
2851             mTimeBase = timeBase;
2852             mCounter = counter;
2853             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
2854             timeBase.add(this);
2855         }
2856 
writeToParcel(Parcel out)2857         private void writeToParcel(Parcel out) {
2858             mCounter.writeToParcel(out, 0);
2859         }
2860 
2861         @Nullable
readFromParcel(Parcel in, TimeBase timeBase, int stateCount, int cpuFreqCount, long timestampMs)2862         private static TimeInFreqMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
2863                 int stateCount, int cpuFreqCount, long timestampMs) {
2864             // Read the object from the Parcel, whether it's usable or not
2865             LongArrayMultiStateCounter counter =
2866                     LongArrayMultiStateCounter.CREATOR.createFromParcel(in);
2867             if (counter.getStateCount() != stateCount
2868                     || counter.getArrayLength() != cpuFreqCount) {
2869                 return null;
2870             }
2871             return new TimeInFreqMultiStateCounter(timeBase, counter, timestampMs);
2872         }
2873 
2874         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2875         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2876             mCounter.setEnabled(true, elapsedRealtimeUs / 1000);
2877         }
2878 
2879         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2880         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2881             mCounter.setEnabled(false, elapsedRealtimeUs / 1000);
2882         }
2883 
getCounter()2884         public LongArrayMultiStateCounter getCounter() {
2885             return mCounter;
2886         }
2887 
getStateCount()2888         public int getStateCount() {
2889             return mCounter.getStateCount();
2890         }
2891 
setTrackingEnabled(boolean enabled, long timestampMs)2892         public void setTrackingEnabled(boolean enabled, long timestampMs) {
2893             mCounter.setEnabled(enabled && mTimeBase.isRunning(), timestampMs);
2894         }
2895 
setState(int uidRunningState, long elapsedRealtimeMs)2896         private void setState(int uidRunningState, long elapsedRealtimeMs) {
2897             mCounter.setState(uidRunningState, elapsedRealtimeMs);
2898         }
2899 
2900         /**
2901          * Returns accumulated counts for the specified state, or false if all counts are zero.
2902          */
getCountsLocked(long[] counts, int procState)2903         public boolean getCountsLocked(long[] counts, int procState) {
2904             if (counts.length != mCounter.getArrayLength()) {
2905                 return false;
2906             }
2907 
2908             return mCounter.getCounts(counts, procState);
2909         }
2910 
2911         /**
2912          * Clears state of this counter.
2913          */
2914         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2915         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2916             mCounter.reset();
2917             if (detachIfReset) {
2918                 detach();
2919             }
2920             return true;
2921         }
2922 
2923         @Override
detach()2924         public void detach() {
2925             mTimeBase.remove(this);
2926         }
2927     }
2928 
2929     @VisibleForTesting
2930     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
2931         final TimeBase mTimeBase;
2932         private long mCount;
2933 
LongSamplingCounter(TimeBase timeBase, Parcel in)2934         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
2935             mTimeBase = timeBase;
2936             mCount = in.readLong();
2937             timeBase.add(this);
2938         }
2939 
LongSamplingCounter(TimeBase timeBase)2940         public LongSamplingCounter(TimeBase timeBase) {
2941             mTimeBase = timeBase;
2942             timeBase.add(this);
2943         }
2944 
writeToParcel(Parcel out)2945         public void writeToParcel(Parcel out) {
2946             out.writeLong(mCount);
2947         }
2948 
2949         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2950         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2951         }
2952 
2953         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2954         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2955         }
2956 
getCountLocked(int which)2957         public long getCountLocked(int which) {
2958             return mCount;
2959         }
2960 
2961         @Override
getCountForProcessState(int procState)2962         public long getCountForProcessState(int procState) {
2963             if (procState == BatteryConsumer.PROCESS_STATE_ANY) {
2964                 return getCountLocked(STATS_SINCE_CHARGED);
2965             }
2966             return 0;
2967         }
2968 
2969         @Override
logState(Printer pw, String prefix)2970         public void logState(Printer pw, String prefix) {
2971             pw.println(prefix + "mCount=" + mCount);
2972         }
2973 
addCountLocked(long count)2974         public void addCountLocked(long count) {
2975             addCountLocked(count, mTimeBase.isRunning());
2976         }
2977 
addCountLocked(long count, boolean isRunning)2978         public void addCountLocked(long count, boolean isRunning) {
2979             if (isRunning) {
2980                 mCount += count;
2981             }
2982         }
2983 
2984         /**
2985          * Clear state of this counter.
2986          */
2987         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2988         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2989             mCount = 0;
2990             if (detachIfReset) {
2991                 detach();
2992             }
2993             return true;
2994         }
2995 
2996         @Override
detach()2997         public void detach() {
2998             mTimeBase.remove(this);
2999         }
3000 
writeSummaryFromParcelLocked(Parcel out)3001         public void writeSummaryFromParcelLocked(Parcel out) {
3002             out.writeLong(mCount);
3003         }
3004 
readSummaryFromParcelLocked(Parcel in)3005         public void readSummaryFromParcelLocked(Parcel in) {
3006             mCount = in.readLong();
3007         }
3008     }
3009 
3010     /**
3011      * State for keeping track of timing information.
3012      */
3013     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
3014         protected final Clock mClock;
3015         protected final int mType;
3016         protected final TimeBase mTimeBase;
3017 
3018         protected int mCount;
3019 
3020         // Times are in microseconds for better accuracy when dividing by the
3021         // lock count, and are in "battery realtime" units.
3022 
3023         /**
3024          * The total time we have accumulated since the start of the original
3025          * boot, to the last time something interesting happened in the
3026          * current run.
3027          */
3028         protected long mTotalTimeUs;
3029 
3030         /**
3031          * The total time this timer has been running until the latest mark has been set.
3032          * Subtract this from mTotalTimeUs to get the time spent running since the mark was set.
3033          */
3034         protected long mTimeBeforeMarkUs;
3035 
3036         /**
3037          * Constructs from a parcel.
3038          * @param type
3039          * @param timeBase
3040          * @param in
3041          */
Timer(Clock clock, int type, TimeBase timeBase, Parcel in)3042         public Timer(Clock clock, int type, TimeBase timeBase, Parcel in) {
3043             mClock = clock;
3044             mType = type;
3045             mTimeBase = timeBase;
3046 
3047             mCount = in.readInt();
3048             mTotalTimeUs = in.readLong();
3049             mTimeBeforeMarkUs = in.readLong();
3050             timeBase.add(this);
3051             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTimeUs);
3052         }
3053 
Timer(Clock clock, int type, TimeBase timeBase)3054         public Timer(Clock clock, int type, TimeBase timeBase) {
3055             mClock = clock;
3056             mType = type;
3057             mTimeBase = timeBase;
3058             timeBase.add(this);
3059         }
3060 
writeToParcel(Parcel out, long elapsedRealtimeUs)3061         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3062             if (DEBUG) {
3063                 Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
3064                         + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
3065                                 elapsedRealtimeUs));
3066             }
3067             out.writeInt(computeCurrentCountLocked());
3068             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
3069                         elapsedRealtimeUs));
3070             out.writeLong(mTimeBeforeMarkUs);
3071         }
3072 
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)3073         protected abstract long computeRunTimeLocked(long curBatteryRealtime,
3074                 long elapsedRealtimeUs);
3075 
computeCurrentCountLocked()3076         protected abstract int computeCurrentCountLocked();
3077 
3078         /**
3079          * Clear state of this timer.  Returns true if the timer is inactive
3080          * so can be completely dropped.
3081          */
3082         @Override
reset(boolean detachIfReset)3083         public boolean reset(boolean detachIfReset) {
3084             return reset(detachIfReset, mClock.elapsedRealtime() * 1000);
3085         }
3086 
3087         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )3088         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
3089             mTotalTimeUs = mTimeBeforeMarkUs = 0;
3090             mCount = 0;
3091             if (detachIfReset) {
3092                 detach();
3093             }
3094             return true;
3095         }
3096 
3097         @Override
detach()3098         public void detach() {
3099             mTimeBase.remove(this);
3100         }
3101 
3102         @Override
onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs, long baseRealtimeUs)3103         public void onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs,
3104                 long baseRealtimeUs) {
3105         }
3106 
3107         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3108         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3109             if (DEBUG && mType < 0) {
3110                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtimeUs
3111                         + " old mTotalTime=" + mTotalTimeUs);
3112             }
3113             mTotalTimeUs = computeRunTimeLocked(baseRealtimeUs, elapsedRealtimeUs);
3114             mCount = computeCurrentCountLocked();
3115             if (DEBUG && mType < 0) {
3116                 Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTimeUs);
3117             }
3118         }
3119 
3120         /**
3121          * Writes a possibly null Timer to a Parcel.
3122          *
3123          * @param out the Parcel to be written to.
3124          * @param timer a Timer, or null.
3125          */
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)3126         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
3127             if (timer == null) {
3128                 out.writeInt(0); // indicates null
3129                 return;
3130             }
3131             out.writeInt(1); // indicates non-null
3132             timer.writeToParcel(out, elapsedRealtimeUs);
3133         }
3134 
3135         @Override
getTotalTimeLocked(long elapsedRealtimeUs, int which)3136         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
3137             return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
3138                     elapsedRealtimeUs);
3139         }
3140 
3141         @Override
getCountLocked(int which)3142         public int getCountLocked(int which) {
3143             return computeCurrentCountLocked();
3144         }
3145 
3146         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)3147         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
3148             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
3149                     elapsedRealtimeUs);
3150             return val - mTimeBeforeMarkUs;
3151         }
3152 
3153         @Override
logState(Printer pw, String prefix)3154         public void logState(Printer pw, String prefix) {
3155             pw.println(prefix + "mCount=" + mCount);
3156             pw.println(prefix + "mTotalTime=" + mTotalTimeUs);
3157         }
3158 
3159 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)3160         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
3161             long runTimeUs = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
3162                     elapsedRealtimeUs);
3163             out.writeLong(runTimeUs);
3164             out.writeInt(computeCurrentCountLocked());
3165         }
3166 
readSummaryFromParcelLocked(Parcel in)3167         public void readSummaryFromParcelLocked(Parcel in) {
3168             // Multiply by 1000 for backwards compatibility
3169             mTotalTimeUs = in.readLong();
3170             mCount = in.readInt();
3171             // When reading the summary, we set the mark to be the latest information.
3172             mTimeBeforeMarkUs = mTotalTimeUs;
3173         }
3174     }
3175 
3176     /**
3177      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
3178      * method. The state of the timer according to its {@link TimeBase} will determine how much
3179      * of the value is recorded.
3180      *
3181      * If the value being recorded resets, {@link #endSample()} can be called in order to
3182      * account for the change. If the value passed in to {@link #update(long, int)} decreased
3183      * between calls, the {@link #endSample()} is automatically called and the new value is
3184      * expected to increase monotonically from that point on.
3185      */
3186     public static class SamplingTimer extends Timer {
3187 
3188         /**
3189          * The most recent reported count from /proc/wakelocks.
3190          */
3191         int mCurrentReportedCount;
3192 
3193         /**
3194          * The reported count from /proc/wakelocks when unplug() was last
3195          * called.
3196          */
3197         int mBaseReportedCount;
3198 
3199         /**
3200          * The most recent reported total_time from /proc/wakelocks.
3201          */
3202         long mCurrentReportedTotalTimeUs;
3203 
3204         /**
3205          * The reported total_time from /proc/wakelocks when unplug() was last
3206          * called.
3207          */
3208         long mBaseReportedTotalTimeUs;
3209 
3210         /**
3211          * Whether we are currently in a discharge cycle.
3212          */
3213         boolean mTimeBaseRunning;
3214 
3215         /**
3216          * Whether we are currently recording reported values.
3217          */
3218         boolean mTrackingReportedValues;
3219 
3220         /*
3221          * A sequence counter, incremented once for each update of the stats.
3222          */
3223         int mUpdateVersion;
3224 
3225         @VisibleForTesting
SamplingTimer(Clock clock, TimeBase timeBase, Parcel in)3226         public SamplingTimer(Clock clock, TimeBase timeBase, Parcel in) {
3227             super(clock, 0, timeBase, in);
3228             mCurrentReportedCount = in.readInt();
3229             mBaseReportedCount = in.readInt();
3230             mCurrentReportedTotalTimeUs = in.readLong();
3231             mBaseReportedTotalTimeUs = in.readLong();
3232             mTrackingReportedValues = in.readInt() == 1;
3233             mTimeBaseRunning = timeBase.isRunning();
3234         }
3235 
3236         @VisibleForTesting
SamplingTimer(Clock clock, TimeBase timeBase)3237         public SamplingTimer(Clock clock, TimeBase timeBase) {
3238             super(clock, 0, timeBase);
3239             mTrackingReportedValues = false;
3240             mTimeBaseRunning = timeBase.isRunning();
3241         }
3242 
3243         /**
3244          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
3245          * be less than the values used for a previous invocation.
3246          */
endSample()3247         public void endSample() {
3248             endSample(mClock.elapsedRealtime() * 1000);
3249         }
3250 
3251         /**
3252          * @see #endSample()
3253          */
endSample(long elapsedRealtimeUs)3254         public void endSample(long elapsedRealtimeUs) {
3255             mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs);
3256             mCount = computeCurrentCountLocked();
3257             mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0;
3258             mBaseReportedCount = mCurrentReportedCount = 0;
3259             mTrackingReportedValues = false;
3260         }
3261 
setUpdateVersion(int version)3262         public void setUpdateVersion(int version) {
3263             mUpdateVersion = version;
3264         }
3265 
getUpdateVersion()3266         public int getUpdateVersion() {
3267             return mUpdateVersion;
3268         }
3269 
3270         /**
3271          * Updates the current recorded values. These are meant to be monotonically increasing
3272          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
3273          *
3274          * If the values being recorded have been reset, the monotonically increasing requirement
3275          * will be broken. In this case, {@link #endSample()} is automatically called and
3276          * the total value of totalTimeUs and count are recorded, starting a new monotonically
3277          * increasing sample.
3278          *
3279          * @param totalTimeUs total time of sample in microseconds.
3280          * @param count total number of times the event being sampled occurred.
3281          */
update(long totalTimeUs, int count, long elapsedRealtimeUs)3282         public void update(long totalTimeUs, int count, long elapsedRealtimeUs) {
3283             update(totalTimeUs, 0, count, elapsedRealtimeUs);
3284         }
3285 
3286         /**
3287          * Updates the current recorded values. See {@link #update(long, int, long)}
3288          *
3289          * @param activeTimeUs Time that the currently active wake lock has been held.
3290          */
update(long totalTimeUs, long activeTimeUs, int count, long elapsedRealtimeUs)3291         public void update(long totalTimeUs, long activeTimeUs, int count,
3292                 long elapsedRealtimeUs) {
3293             if (mTimeBaseRunning && !mTrackingReportedValues) {
3294                 // Updating the reported value for the first time. If the wake lock is currently
3295                 // active, mark the time it was acquired as the base timestamp.
3296                 mBaseReportedTotalTimeUs = totalTimeUs - activeTimeUs;
3297                 mBaseReportedCount = activeTimeUs == 0 ? count : count - 1;
3298             }
3299 
3300             mTrackingReportedValues = true;
3301 
3302             if (totalTimeUs < mCurrentReportedTotalTimeUs || count < mCurrentReportedCount) {
3303                 endSample(elapsedRealtimeUs);
3304             }
3305 
3306             mCurrentReportedTotalTimeUs = totalTimeUs;
3307             mCurrentReportedCount = count;
3308         }
3309 
3310         /**
3311          * Adds deltaTime and deltaCount to the current sample.
3312          *
3313          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
3314          * @param deltaCount additional number of times the event being sampled occurred.
3315          */
add(long deltaTimeUs, int deltaCount)3316         public void add(long deltaTimeUs, int deltaCount) {
3317             add(deltaTimeUs, deltaCount, mClock.elapsedRealtime() * 1000);
3318         }
3319 
3320         /**
3321          * @see #add(long, int)
3322          */
add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs)3323         public void add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs) {
3324             update(mCurrentReportedTotalTimeUs + deltaTimeUs, mCurrentReportedCount + deltaCount,
3325                     elapsedRealtimeUs);
3326         }
3327 
3328         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3329         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3330             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3331             if (mTrackingReportedValues) {
3332                 mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs;
3333                 mBaseReportedCount = mCurrentReportedCount;
3334             }
3335             mTimeBaseRunning = true;
3336         }
3337 
3338         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3339         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3340             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3341             mTimeBaseRunning = false;
3342         }
3343 
3344         @Override
logState(Printer pw, String prefix)3345         public void logState(Printer pw, String prefix) {
3346             super.logState(pw, prefix);
3347             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
3348                     + " mBaseReportedCount=" + mBaseReportedCount
3349                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs
3350                     + " mBaseReportedTotalTimeUs=" + mBaseReportedTotalTimeUs);
3351         }
3352 
3353         @Override
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)3354         protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) {
3355             return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues
3356                     ? mCurrentReportedTotalTimeUs - mBaseReportedTotalTimeUs : 0);
3357         }
3358 
3359         @Override
computeCurrentCountLocked()3360         protected int computeCurrentCountLocked() {
3361             return mCount + (mTimeBaseRunning && mTrackingReportedValues
3362                     ? mCurrentReportedCount - mBaseReportedCount : 0);
3363         }
3364 
3365         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3366         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3367             super.writeToParcel(out, elapsedRealtimeUs);
3368             out.writeInt(mCurrentReportedCount);
3369             out.writeInt(mBaseReportedCount);
3370             out.writeLong(mCurrentReportedTotalTimeUs);
3371             out.writeLong(mBaseReportedTotalTimeUs);
3372             out.writeInt(mTrackingReportedValues ? 1 : 0);
3373         }
3374 
3375         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3376         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3377             super.reset(detachIfReset, elapsedRealtimeUs);
3378             mTrackingReportedValues = false;
3379             mBaseReportedTotalTimeUs = 0;
3380             mBaseReportedCount = 0;
3381             return true;
3382         }
3383     }
3384 
3385     /**
3386      * A timer that increments in batches.  It does not run for durations, but just jumps
3387      * for a pre-determined amount.
3388      */
3389     public static class BatchTimer extends Timer {
3390         final Uid mUid;
3391 
3392         /**
3393          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
3394          */
3395         long mLastAddedTimeUs;
3396 
3397         /**
3398          * The last duration that we added to the timer.  This is in microseconds.
3399          */
3400         long mLastAddedDurationUs;
3401 
3402         /**
3403          * Whether we are currently in a discharge cycle.
3404          */
3405         boolean mInDischarge;
3406 
BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase, Parcel in)3407         BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase, Parcel in) {
3408             super(clock, type, timeBase, in);
3409             mUid = uid;
3410             mLastAddedTimeUs = in.readLong();
3411             mLastAddedDurationUs = in.readLong();
3412             mInDischarge = timeBase.isRunning();
3413         }
3414 
BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase)3415         BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase) {
3416             super(clock, type, timeBase);
3417             mUid = uid;
3418             mInDischarge = timeBase.isRunning();
3419         }
3420 
3421         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3422         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3423             super.writeToParcel(out, elapsedRealtimeUs);
3424             out.writeLong(mLastAddedTimeUs);
3425             out.writeLong(mLastAddedDurationUs);
3426         }
3427 
3428         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3429         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3430             recomputeLastDuration(elapsedRealtimeUs, false);
3431             mInDischarge = false;
3432             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3433         }
3434 
3435         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3436         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3437             recomputeLastDuration(elapsedRealtimeUs, false);
3438             mInDischarge = true;
3439             // If we are still within the last added duration, then re-added whatever remains.
3440             if (mLastAddedTimeUs == elapsedRealtimeUs) {
3441                 mTotalTimeUs += mLastAddedDurationUs;
3442             }
3443             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3444         }
3445 
3446         @Override
logState(Printer pw, String prefix)3447         public void logState(Printer pw, String prefix) {
3448             super.logState(pw, prefix);
3449             pw.println(prefix + "mLastAddedTime=" + mLastAddedTimeUs
3450                     + " mLastAddedDuration=" + mLastAddedDurationUs);
3451         }
3452 
computeOverage(long curTimeUs)3453         private long computeOverage(long curTimeUs) {
3454             if (mLastAddedTimeUs > 0) {
3455                 return mLastAddedDurationUs - curTimeUs;
3456             }
3457             return 0;
3458         }
3459 
recomputeLastDuration(long curTimeUs, boolean abort)3460         private void recomputeLastDuration(long curTimeUs, boolean abort) {
3461             final long overage = computeOverage(curTimeUs);
3462             if (overage > 0) {
3463                 // Aborting before the duration ran out -- roll back the remaining
3464                 // duration.  Only do this if currently discharging; otherwise we didn't
3465                 // actually add the time.
3466                 if (mInDischarge) {
3467                     mTotalTimeUs -= overage;
3468                 }
3469                 if (abort) {
3470                     mLastAddedTimeUs = 0;
3471                 } else {
3472                     mLastAddedTimeUs = curTimeUs;
3473                     mLastAddedDurationUs -= overage;
3474                 }
3475             }
3476         }
3477 
addDuration(long durationMs, long elapsedRealtimeMs)3478         public void addDuration(long durationMs, long elapsedRealtimeMs) {
3479             final long nowUs = elapsedRealtimeMs * 1000;
3480             recomputeLastDuration(nowUs, true);
3481             mLastAddedTimeUs = nowUs;
3482             mLastAddedDurationUs = durationMs * 1000;
3483             if (mInDischarge) {
3484                 mTotalTimeUs += mLastAddedDurationUs;
3485                 mCount++;
3486             }
3487         }
3488 
abortLastDuration(long elapsedRealtimeMs)3489         public void abortLastDuration(long elapsedRealtimeMs) {
3490             final long nowUs = elapsedRealtimeMs * 1000;
3491             recomputeLastDuration(nowUs, true);
3492         }
3493 
3494         @Override
computeCurrentCountLocked()3495         protected int computeCurrentCountLocked() {
3496             return mCount;
3497         }
3498 
3499         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)3500         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
3501             final long overage = computeOverage(elapsedRealtimeUs);
3502             if (overage > 0) {
3503                 return mTotalTimeUs = overage;
3504             }
3505             return mTotalTimeUs;
3506         }
3507 
3508         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3509         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3510             recomputeLastDuration(elapsedRealtimeUs, true);
3511             boolean stillActive = mLastAddedTimeUs == elapsedRealtimeUs;
3512             super.reset(!stillActive && detachIfReset, elapsedRealtimeUs);
3513             return !stillActive;
3514         }
3515     }
3516 
3517 
3518     /**
3519      * A StopwatchTimer that also tracks the total and max individual
3520      * time spent active according to the given timebase.  Whereas
3521      * StopwatchTimer apportions the time amongst all in the pool,
3522      * the total and max durations are not apportioned.
3523      */
3524     public static class DurationTimer extends StopwatchTimer {
3525         /**
3526          * The time (in ms) that the timer was last acquired or the time base
3527          * last (re-)started. Increasing the nesting depth does not reset this time.
3528          *
3529          * -1 if the timer is currently not running or the time base is not running.
3530          *
3531          * If written to a parcel, the start time is reset, as is mNesting in the base class
3532          * StopwatchTimer.
3533          */
3534         long mStartTimeMs = -1;
3535 
3536         /**
3537          * The longest time period (in ms) that the timer has been active. Not pooled.
3538          */
3539         long mMaxDurationMs;
3540 
3541         /**
3542          * The time (in ms) that that the timer has been active since most recent
3543          * stopRunningLocked() or reset(). Not pooled.
3544          */
3545         long mCurrentDurationMs;
3546 
3547         /**
3548          * The total time (in ms) that that the timer has been active since most recent reset()
3549          * prior to the current startRunningLocked. This is the sum of all past currentDurations
3550          * (but not including the present currentDuration) since reset. Not pooled.
3551          */
3552         long mTotalDurationMs;
3553 
DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)3554         public DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3555                 TimeBase timeBase, Parcel in) {
3556             super(clock, uid, type, timerPool, timeBase, in);
3557             mMaxDurationMs = in.readLong();
3558             mTotalDurationMs = in.readLong();
3559             mCurrentDurationMs = in.readLong();
3560         }
3561 
DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)3562         public DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3563                 TimeBase timeBase) {
3564             super(clock, uid, type, timerPool, timeBase);
3565         }
3566 
3567         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3568         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3569             super.writeToParcel(out, elapsedRealtimeUs);
3570             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
3571             out.writeLong(mTotalDurationMs);
3572             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
3573         }
3574 
3575         /**
3576          * Write the summary to the parcel.
3577          *
3578          * Since the time base is probably meaningless after we come back, reading
3579          * from this will have the effect of stopping the timer. So here all we write
3580          * is the max and total durations.
3581          */
3582         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)3583         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
3584             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3585             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
3586             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
3587         }
3588 
3589         /**
3590          * Read the summary parcel.
3591          *
3592          * Has the side effect of stopping the timer.
3593          */
3594         @Override
readSummaryFromParcelLocked(Parcel in)3595         public void readSummaryFromParcelLocked(Parcel in) {
3596             super.readSummaryFromParcelLocked(in);
3597             mMaxDurationMs = in.readLong();
3598             mTotalDurationMs = in.readLong();
3599             mStartTimeMs = -1;
3600             mCurrentDurationMs = 0;
3601         }
3602 
3603         /**
3604          * The TimeBase time started (again).
3605          *
3606          * If the timer is also running, store the start time.
3607          */
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3608         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3609             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3610             if (mNesting > 0) {
3611                 mStartTimeMs = baseRealtimeUs / 1000;
3612             }
3613         }
3614 
3615         /**
3616          * The TimeBase stopped running.
3617          *
3618          * If the timer is running, add the duration into mCurrentDurationMs.
3619          */
3620         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3621         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3622             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3623             if (mNesting > 0) {
3624                 // baseRealtimeUs has already been converted to the timebase's realtime.
3625                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
3626             }
3627             mStartTimeMs = -1;
3628         }
3629 
3630         @Override
logState(Printer pw, String prefix)3631         public void logState(Printer pw, String prefix) {
3632             super.logState(pw, prefix);
3633         }
3634 
3635         @Override
startRunningLocked(long elapsedRealtimeMs)3636         public void startRunningLocked(long elapsedRealtimeMs) {
3637             super.startRunningLocked(elapsedRealtimeMs);
3638             if (mNesting == 1 && mTimeBase.isRunning()) {
3639                 // Just started
3640                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
3641             }
3642         }
3643 
3644         /**
3645          * Decrements the mNesting ref-count on this timer.
3646          *
3647          * If it actually stopped (mNesting went to 0), then possibly update
3648          * mMaxDuration if the current duration was the longest ever.
3649          */
3650         @Override
stopRunningLocked(long elapsedRealtimeMs)3651         public void stopRunningLocked(long elapsedRealtimeMs) {
3652             if (mNesting == 1) {
3653                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
3654                 mTotalDurationMs += durationMs;
3655                 if (durationMs > mMaxDurationMs) {
3656                     mMaxDurationMs = durationMs;
3657                 }
3658                 mStartTimeMs = -1;
3659                 mCurrentDurationMs = 0;
3660             }
3661             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
3662             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
3663             super.stopRunningLocked(elapsedRealtimeMs);
3664         }
3665 
3666         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3667         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3668             boolean result = super.reset(detachIfReset, elapsedRealtimeUs);
3669             mMaxDurationMs = 0;
3670             mTotalDurationMs = 0;
3671             mCurrentDurationMs = 0;
3672             if (mNesting > 0) {
3673                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeUs) / 1000;
3674             } else {
3675                 mStartTimeMs = -1;
3676             }
3677             return result;
3678         }
3679 
3680         /**
3681          * Returns the max duration that this timer has ever seen.
3682          *
3683          * Note that this time is NOT split between the timers in the timer group that
3684          * this timer is attached to.  It is the TOTAL time.
3685          */
3686         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)3687         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
3688             if (mNesting > 0) {
3689                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
3690                 if (durationMs > mMaxDurationMs) {
3691                     return durationMs;
3692                 }
3693             }
3694             return mMaxDurationMs;
3695         }
3696 
3697         /**
3698          * Returns the time since the timer was started.
3699          * Returns 0 if the timer is not currently running.
3700          *
3701          * Note that this time is NOT split between the timers in the timer group that
3702          * this timer is attached to.  It is the TOTAL time.
3703          *
3704          * Note that if running timer is parceled and unparceled, this method will return
3705          * current duration value at the time of parceling even though timer may not be
3706          * currently running.
3707          */
3708         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)3709         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
3710             long durationMs = mCurrentDurationMs;
3711             if (mNesting > 0 && mTimeBase.isRunning()) {
3712                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
3713                         - mStartTimeMs;
3714             }
3715             return durationMs;
3716         }
3717 
3718         /**
3719          * Returns the total cumulative duration that this timer has been on since reset().
3720          * If mTimerPool == null, this should be the same
3721          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
3722          *
3723          * Note that this time is NOT split between the timers in the timer group that
3724          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
3725          * the result will not be equivalent to getTotalTimeLocked.
3726          */
3727         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)3728         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
3729             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
3730         }
3731     }
3732 
3733     /**
3734      * State for keeping track of timing information.
3735      */
3736     public static class StopwatchTimer extends Timer {
3737         final Uid mUid;
3738         final ArrayList<StopwatchTimer> mTimerPool;
3739 
3740         int mNesting;
3741 
3742         /**
3743          * The last time at which we updated the timer.  If mNesting is > 0,
3744          * subtract this from the current battery time to find the amount of
3745          * time we have been running since we last computed an update.
3746          */
3747         long mUpdateTimeUs;
3748 
3749         /**
3750          * The total time at which the timer was acquired, to determine if it
3751          * was actually held for an interesting duration. If time base was not running when timer
3752          * was acquired, will be -1.
3753          */
3754         long mAcquireTimeUs = -1;
3755 
3756         long mTimeoutUs;
3757 
3758         /**
3759          * For partial wake locks, keep track of whether we are in the list
3760          * to consume CPU cycles.
3761          */
3762         @VisibleForTesting
3763         public boolean mInList;
3764 
StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)3765         public StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3766                 TimeBase timeBase, Parcel in) {
3767             super(clock, type, timeBase, in);
3768             mUid = uid;
3769             mTimerPool = timerPool;
3770             mUpdateTimeUs = in.readLong();
3771         }
3772 
StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)3773         public StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3774                 TimeBase timeBase) {
3775             super(clock, type, timeBase);
3776             mUid = uid;
3777             mTimerPool = timerPool;
3778         }
3779 
setTimeout(long timeoutUs)3780         public void setTimeout(long timeoutUs) {
3781             mTimeoutUs = timeoutUs;
3782         }
3783 
writeToParcel(Parcel out, long elapsedRealtimeUs)3784         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3785             super.writeToParcel(out, elapsedRealtimeUs);
3786             out.writeLong(mUpdateTimeUs);
3787         }
3788 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3789         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3790             if (mNesting > 0) {
3791                 if (DEBUG && mType < 0) {
3792                     Log.v(TAG, "old mUpdateTime=" + mUpdateTimeUs);
3793                 }
3794                 super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3795                 mUpdateTimeUs = baseRealtimeUs;
3796                 if (DEBUG && mType < 0) {
3797                     Log.v(TAG, "new mUpdateTime=" + mUpdateTimeUs);
3798                 }
3799             }
3800         }
3801 
logState(Printer pw, String prefix)3802         public void logState(Printer pw, String prefix) {
3803             super.logState(pw, prefix);
3804             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTimeUs
3805                     + " mAcquireTime=" + mAcquireTimeUs);
3806         }
3807 
startRunningLocked(long elapsedRealtimeMs)3808         public void startRunningLocked(long elapsedRealtimeMs) {
3809             if (mNesting++ == 0) {
3810                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3811                 mUpdateTimeUs = batteryRealtimeUs;
3812                 if (mTimerPool != null) {
3813                     // Accumulate time to all currently active timers before adding
3814                     // this new one to the pool.
3815                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
3816                     // Add this timer to the active pool
3817                     mTimerPool.add(this);
3818                 }
3819                 if (mTimeBase.isRunning()) {
3820                     // Increment the count
3821                     mCount++;
3822                     mAcquireTimeUs = mTotalTimeUs;
3823                 } else {
3824                     mAcquireTimeUs = -1;
3825                 }
3826                 if (DEBUG && mType < 0) {
3827                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTimeUs
3828                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
3829                             + " mAcquireTime=" + mAcquireTimeUs);
3830                 }
3831             }
3832         }
3833 
isRunningLocked()3834         public boolean isRunningLocked() {
3835             return mNesting > 0;
3836         }
3837 
stopRunningLocked(long elapsedRealtimeMs)3838         public void stopRunningLocked(long elapsedRealtimeMs) {
3839             // Ignore attempt to stop a timer that isn't running
3840             if (mNesting == 0) {
3841                 return;
3842             }
3843             if (--mNesting == 0) {
3844                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3845                 if (mTimerPool != null) {
3846                     // Accumulate time to all active counters, scaled by the total
3847                     // active in the pool, before taking this one out of the pool.
3848                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
3849                     // Remove this timer from the active pool
3850                     mTimerPool.remove(this);
3851                 } else {
3852                     mNesting = 1;
3853                     mTotalTimeUs = computeRunTimeLocked(batteryRealtimeUs,
3854                             elapsedRealtimeMs * 1000);
3855                     mNesting = 0;
3856                 }
3857 
3858                 if (DEBUG && mType < 0) {
3859                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTimeUs
3860                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
3861                             + " mAcquireTime=" + mAcquireTimeUs);
3862                 }
3863 
3864                 if (mAcquireTimeUs >= 0 && mTotalTimeUs == mAcquireTimeUs) {
3865                     // If there was no change in the time, then discard this
3866                     // count.  A somewhat cheezy strategy, but hey.
3867                     mCount--;
3868                 }
3869             }
3870         }
3871 
stopAllRunningLocked(long elapsedRealtimeMs)3872         public void stopAllRunningLocked(long elapsedRealtimeMs) {
3873             if (mNesting > 0) {
3874                 mNesting = 1;
3875                 stopRunningLocked(elapsedRealtimeMs);
3876             }
3877         }
3878 
3879         // Update the total time for all other running Timers with the same type as this Timer
3880         // due to a change in timer count
refreshTimersLocked(long batteryRealtimeUs, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)3881         private static long refreshTimersLocked(long batteryRealtimeUs,
3882                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
3883             long selfTimeUs = 0;
3884             final int N = pool.size();
3885             for (int i=N-1; i>= 0; i--) {
3886                 final StopwatchTimer t = pool.get(i);
3887                 long heldTimeUs = batteryRealtimeUs - t.mUpdateTimeUs;
3888                 if (heldTimeUs > 0) {
3889                     final long myTimeUs = heldTimeUs / N;
3890                     if (t == self) {
3891                         selfTimeUs = myTimeUs;
3892                     }
3893                     t.mTotalTimeUs += myTimeUs;
3894                 }
3895                 t.mUpdateTimeUs = batteryRealtimeUs;
3896             }
3897             return selfTimeUs;
3898         }
3899 
3900         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)3901         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
3902             if (mTimeoutUs > 0 && curBatteryRealtimeUs > mUpdateTimeUs + mTimeoutUs) {
3903                 curBatteryRealtimeUs = mUpdateTimeUs + mTimeoutUs;
3904             }
3905             return mTotalTimeUs + (mNesting > 0
3906                     ? (curBatteryRealtimeUs - mUpdateTimeUs)
3907                             / (mTimerPool != null && mTimerPool.size() > 0 ? mTimerPool.size() : 1)
3908                     : 0);
3909         }
3910 
3911         @Override
computeCurrentCountLocked()3912         protected int computeCurrentCountLocked() {
3913             return mCount;
3914         }
3915 
3916         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3917         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3918             boolean canDetach = mNesting <= 0;
3919             super.reset(canDetach && detachIfReset, elapsedRealtimeUs);
3920             if (mNesting > 0) {
3921                 mUpdateTimeUs = mTimeBase.getRealtime(elapsedRealtimeUs);
3922             }
3923             // To ensure mCount isn't decreased to -1 if timer is stopped later.
3924             mAcquireTimeUs = -1;
3925             return canDetach;
3926         }
3927 
3928         @Override
detach()3929         public void detach() {
3930             super.detach();
3931             if (mTimerPool != null) {
3932                 mTimerPool.remove(this);
3933             }
3934         }
3935 
3936         @Override
readSummaryFromParcelLocked(Parcel in)3937         public void readSummaryFromParcelLocked(Parcel in) {
3938             super.readSummaryFromParcelLocked(in);
3939             mNesting = 0;
3940         }
3941 
3942         /**
3943          * Set the mark so that we can query later for the total time the timer has
3944          * accumulated since this point. The timer can be running or not.
3945          *
3946          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
3947          */
setMark(long elapsedRealtimeMs)3948         public void setMark(long elapsedRealtimeMs) {
3949             final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3950             if (mNesting > 0) {
3951                 // We are running.
3952                 if (mTimerPool != null) {
3953                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, this);
3954                 } else {
3955                     mTotalTimeUs += batteryRealtimeUs - mUpdateTimeUs;
3956                     mUpdateTimeUs = batteryRealtimeUs;
3957                 }
3958             }
3959             mTimeBeforeMarkUs = mTotalTimeUs;
3960         }
3961     }
3962 
3963     /**
3964      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
3965      * TimeBase is effectively a subset of the other.
3966      */
3967     public static class DualTimer extends DurationTimer {
3968         // This class both is a DurationTimer and also holds a second DurationTimer.
3969         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
3970         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
3971         // STATS_SINCE_CHARGED).
3972         // mSubTimer typically tracks only part of the total time, such as background time, as
3973         // determined by a subTimeBase. It is NOT pooled.
3974         private final DurationTimer mSubTimer;
3975 
3976         /**
3977          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
3978          * The main timer (this) is based on the given timeBase and timerPool.
3979          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
3980          * the main timer is.
3981          */
DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)3982         public DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3983                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
3984             super(clock, uid, type, timerPool, timeBase, in);
3985             mSubTimer = new DurationTimer(clock, uid, type, null, subTimeBase, in);
3986         }
3987 
3988         /**
3989          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
3990          * The main timer (this) is based on the given timeBase and timerPool.
3991          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
3992          * the main timer is.
3993          */
DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)3994         public DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3995                 TimeBase timeBase, TimeBase subTimeBase) {
3996             super(clock, uid, type, timerPool, timeBase);
3997             mSubTimer = new DurationTimer(clock, uid, type, null, subTimeBase);
3998         }
3999 
4000         /** Get the secondary timer. */
4001         @Override
getSubTimer()4002         public DurationTimer getSubTimer() {
4003             return mSubTimer;
4004         }
4005 
4006         @Override
startRunningLocked(long elapsedRealtimeMs)4007         public void startRunningLocked(long elapsedRealtimeMs) {
4008             super.startRunningLocked(elapsedRealtimeMs);
4009             mSubTimer.startRunningLocked(elapsedRealtimeMs);
4010         }
4011 
4012         @Override
stopRunningLocked(long elapsedRealtimeMs)4013         public void stopRunningLocked(long elapsedRealtimeMs) {
4014             super.stopRunningLocked(elapsedRealtimeMs);
4015             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
4016         }
4017 
4018         @Override
stopAllRunningLocked(long elapsedRealtimeMs)4019         public void stopAllRunningLocked(long elapsedRealtimeMs) {
4020             super.stopAllRunningLocked(elapsedRealtimeMs);
4021             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
4022         }
4023 
4024         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)4025         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
4026             boolean active = false;
4027             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
4028             active |= !mSubTimer.reset(false, elapsedRealtimeUs);
4029             active |= !super.reset(detachIfReset, elapsedRealtimeUs);
4030             return !active;
4031         }
4032 
4033         @Override
detach()4034         public void detach() {
4035             mSubTimer.detach();
4036             super.detach();
4037         }
4038 
4039         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)4040         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
4041             super.writeToParcel(out, elapsedRealtimeUs);
4042             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
4043         }
4044 
4045         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)4046         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
4047             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
4048             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
4049         }
4050 
4051         @Override
readSummaryFromParcelLocked(Parcel in)4052         public void readSummaryFromParcelLocked(Parcel in) {
4053             super.readSummaryFromParcelLocked(in);
4054             mSubTimer.readSummaryFromParcelLocked(in);
4055         }
4056     }
4057 
4058 
4059     public abstract class OverflowArrayMap<T> {
4060         private static final String OVERFLOW_NAME = "*overflow*";
4061 
4062         final int mUid;
4063         final ArrayMap<String, T> mMap = new ArrayMap<>();
4064         T mCurOverflow;
4065         ArrayMap<String, MutableInt> mActiveOverflow;
4066         long mLastOverflowTimeMs;
4067         long mLastOverflowFinishTimeMs;
4068         long mLastClearTimeMs;
4069         long mLastCleanupTimeMs;
4070 
OverflowArrayMap(int uid)4071         public OverflowArrayMap(int uid) {
4072             mUid = uid;
4073         }
4074 
getMap()4075         public ArrayMap<String, T> getMap() {
4076             return mMap;
4077         }
4078 
clear()4079         public void clear() {
4080             mLastClearTimeMs = SystemClock.elapsedRealtime();
4081             mMap.clear();
4082             mCurOverflow = null;
4083             mActiveOverflow = null;
4084         }
4085 
add(String name, T obj)4086         public void add(String name, T obj) {
4087             if (name == null) {
4088                 name = "";
4089             }
4090             mMap.put(name, obj);
4091             if (OVERFLOW_NAME.equals(name)) {
4092                 mCurOverflow = obj;
4093             }
4094         }
4095 
cleanup(long elapsedRealtimeMs)4096         public void cleanup(long elapsedRealtimeMs) {
4097             mLastCleanupTimeMs = elapsedRealtimeMs;
4098             if (mActiveOverflow != null) {
4099                 if (mActiveOverflow.size() == 0) {
4100                     mActiveOverflow = null;
4101                 }
4102             }
4103             if (mActiveOverflow == null) {
4104                 // There is no currently active overflow, so we should no longer have
4105                 // an overflow entry.
4106                 if (mMap.containsKey(OVERFLOW_NAME)) {
4107                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
4108                             + mMap.get(OVERFLOW_NAME));
4109                     mMap.remove(OVERFLOW_NAME);
4110                 }
4111                 mCurOverflow = null;
4112             } else {
4113                 // There is currently active overflow, so we should still have an overflow entry.
4114                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
4115                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
4116                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
4117                 }
4118             }
4119         }
4120 
startObject(String name, long elapsedRealtimeMs)4121         public T startObject(String name, long elapsedRealtimeMs) {
4122             if (name == null) {
4123                 name = "";
4124             }
4125             T obj = mMap.get(name);
4126             if (obj != null) {
4127                 return obj;
4128             }
4129 
4130             // No object exists for the given name, but do we currently have it
4131             // running as part of the overflow?
4132             if (mActiveOverflow != null) {
4133                 MutableInt over = mActiveOverflow.get(name);
4134                 if (over != null) {
4135                     // We are already actively counting this name in the overflow object.
4136                     obj = mCurOverflow;
4137                     if (obj == null) {
4138                         // Shouldn't be here, but we'll try to recover.
4139                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
4140                         obj = mCurOverflow = instantiateObject();
4141                         mMap.put(OVERFLOW_NAME, obj);
4142                     }
4143                     over.value++;
4144                     return obj;
4145                 }
4146             }
4147 
4148             // No object exists for given name nor in the overflow; we need to make
4149             // a new one.
4150             final int N = mMap.size();
4151             if (N >= MAX_WAKELOCKS_PER_UID) {
4152                 // Went over the limit on number of objects to track; this one goes
4153                 // in to the overflow.
4154                 obj = mCurOverflow;
4155                 if (obj == null) {
4156                     // Need to start overflow now...
4157                     obj = mCurOverflow = instantiateObject();
4158                     mMap.put(OVERFLOW_NAME, obj);
4159                 }
4160                 if (mActiveOverflow == null) {
4161                     mActiveOverflow = new ArrayMap<>();
4162                 }
4163                 mActiveOverflow.put(name, new MutableInt(1));
4164                 mLastOverflowTimeMs = elapsedRealtimeMs;
4165                 return obj;
4166             }
4167 
4168             // Normal case where we just need to make a new object.
4169             obj = instantiateObject();
4170             mMap.put(name, obj);
4171             return obj;
4172         }
4173 
stopObject(String name, long elapsedRealtimeMs)4174         public T stopObject(String name, long elapsedRealtimeMs) {
4175             if (name == null) {
4176                 name = "";
4177             }
4178             T obj = mMap.get(name);
4179             if (obj != null) {
4180                 return obj;
4181             }
4182 
4183             // No object exists for the given name, but do we currently have it
4184             // running as part of the overflow?
4185             if (mActiveOverflow != null) {
4186                 MutableInt over = mActiveOverflow.get(name);
4187                 if (over != null) {
4188                     // We are already actively counting this name in the overflow object.
4189                     obj = mCurOverflow;
4190                     if (obj != null) {
4191                         over.value--;
4192                         if (over.value <= 0) {
4193                             mActiveOverflow.remove(name);
4194                             mLastOverflowFinishTimeMs = elapsedRealtimeMs;
4195                         }
4196                         return obj;
4197                     }
4198                 }
4199             }
4200 
4201             // Huh, they are stopping an active operation but we can't find one!
4202             // That's not good.
4203             StringBuilder sb = new StringBuilder();
4204             sb.append("Unable to find object for ");
4205             sb.append(name);
4206             sb.append(" in uid ");
4207             sb.append(mUid);
4208             sb.append(" mapsize=");
4209             sb.append(mMap.size());
4210             sb.append(" activeoverflow=");
4211             sb.append(mActiveOverflow);
4212             sb.append(" curoverflow=");
4213             sb.append(mCurOverflow);
4214             long now = elapsedRealtimeMs;
4215             if (mLastOverflowTimeMs != 0) {
4216                 sb.append(" lastOverflowTime=");
4217                 TimeUtils.formatDuration(mLastOverflowTimeMs - now, sb);
4218             }
4219             if (mLastOverflowFinishTimeMs != 0) {
4220                 sb.append(" lastOverflowFinishTime=");
4221                 TimeUtils.formatDuration(mLastOverflowFinishTimeMs - now, sb);
4222             }
4223             if (mLastClearTimeMs != 0) {
4224                 sb.append(" lastClearTime=");
4225                 TimeUtils.formatDuration(mLastClearTimeMs - now, sb);
4226             }
4227             if (mLastCleanupTimeMs != 0) {
4228                 sb.append(" lastCleanupTime=");
4229                 TimeUtils.formatDuration(mLastCleanupTimeMs - now, sb);
4230             }
4231             Slog.wtf(TAG, sb.toString());
4232             return null;
4233         }
4234 
instantiateObject()4235         public abstract T instantiateObject();
4236     }
4237 
4238     @SuppressWarnings("ParcelableCreator")
4239     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
4240             implements Parcelable {
4241         private final Clock mClock;
4242         private final TimeBase mTimeBase;
4243         private int mNumTxStates;
4244         private int mProcessState;
4245         private TimeMultiStateCounter mIdleTimeMillis;
4246         private final LongSamplingCounter mScanTimeMillis;
4247         private final LongSamplingCounter mSleepTimeMillis;
4248         private TimeMultiStateCounter mRxTimeMillis;
4249         private TimeMultiStateCounter[] mTxTimeMillis;
4250         private final LongSamplingCounter mPowerDrainMaMs;
4251         private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs;
4252 
ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates)4253         public ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates) {
4254             mClock = clock;
4255             mTimeBase = timeBase;
4256             mNumTxStates = numTxStates;
4257             mScanTimeMillis = new LongSamplingCounter(timeBase);
4258             mSleepTimeMillis = new LongSamplingCounter(timeBase);
4259             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
4260             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase);
4261         }
4262 
readSummaryFromParcel(Parcel in)4263         public void readSummaryFromParcel(Parcel in) {
4264             mIdleTimeMillis = readTimeMultiStateCounter(in, mTimeBase);
4265             mScanTimeMillis.readSummaryFromParcelLocked(in);
4266             mSleepTimeMillis.readSummaryFromParcelLocked(in);
4267             mRxTimeMillis = readTimeMultiStateCounter(in, mTimeBase);
4268             mTxTimeMillis = readTimeMultiStateCounters(in, mTimeBase, mNumTxStates);
4269 
4270             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
4271             mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in);
4272         }
4273 
4274         @Override
describeContents()4275         public int describeContents() {
4276             return 0;
4277         }
4278 
writeSummaryToParcel(Parcel dest)4279         public void writeSummaryToParcel(Parcel dest) {
4280             writeTimeMultiStateCounter(dest, mIdleTimeMillis);
4281             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
4282             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
4283             writeTimeMultiStateCounter(dest, mRxTimeMillis);
4284             writeTimeMultiStateCounters(dest, mTxTimeMillis);
4285             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
4286             mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest);
4287         }
4288 
4289         @Override
writeToParcel(Parcel dest, int flags)4290         public void writeToParcel(Parcel dest, int flags) {
4291             writeTimeMultiStateCounter(dest, mIdleTimeMillis);
4292             mScanTimeMillis.writeToParcel(dest);
4293             mSleepTimeMillis.writeToParcel(dest);
4294             writeTimeMultiStateCounter(dest, mRxTimeMillis);
4295             writeTimeMultiStateCounters(dest, mTxTimeMillis);
4296             mPowerDrainMaMs.writeToParcel(dest);
4297             mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
4298         }
4299 
readTimeMultiStateCounter(Parcel in, TimeBase timeBase)4300         private TimeMultiStateCounter readTimeMultiStateCounter(Parcel in, TimeBase timeBase) {
4301             if (in.readBoolean()) {
4302                 return TimeMultiStateCounter.readFromParcel(in, timeBase,
4303                         BatteryConsumer.PROCESS_STATE_COUNT, mClock.elapsedRealtime());
4304             }
4305             return null;
4306         }
4307 
writeTimeMultiStateCounter(Parcel dest, TimeMultiStateCounter counter)4308         private void writeTimeMultiStateCounter(Parcel dest, TimeMultiStateCounter counter) {
4309             if (counter != null) {
4310                 dest.writeBoolean(true);
4311                 counter.writeToParcel(dest);
4312             } else {
4313                 dest.writeBoolean(false);
4314             }
4315         }
4316 
readTimeMultiStateCounters(Parcel in, TimeBase timeBase, int expectedNumCounters)4317         private TimeMultiStateCounter[] readTimeMultiStateCounters(Parcel in, TimeBase timeBase,
4318                 int expectedNumCounters) {
4319             if (in.readBoolean()) {
4320                 final int numCounters = in.readInt();
4321                 boolean valid = (numCounters == expectedNumCounters);
4322                 // Need to read counters out of the Parcel, even if all or some of them are
4323                 // invalid.
4324                 TimeMultiStateCounter[] counters = new TimeMultiStateCounter[numCounters];
4325                 for (int i = 0; i < numCounters; i++) {
4326                     final TimeMultiStateCounter counter = TimeMultiStateCounter.readFromParcel(in,
4327                             timeBase, BatteryConsumer.PROCESS_STATE_COUNT,
4328                             mClock.elapsedRealtime());
4329                     if (counter != null) {
4330                         counters[i] = counter;
4331                     } else {
4332                         valid = false;
4333                     }
4334                 }
4335                 if (valid) {
4336                     return counters;
4337                 }
4338             }
4339             return null;
4340         }
4341 
writeTimeMultiStateCounters(Parcel dest, TimeMultiStateCounter[] counters)4342         private void writeTimeMultiStateCounters(Parcel dest, TimeMultiStateCounter[] counters) {
4343             if (counters != null) {
4344                 dest.writeBoolean(true);
4345                 dest.writeInt(counters.length);
4346                 for (TimeMultiStateCounter counter : counters) {
4347                     counter.writeToParcel(dest);
4348                 }
4349             } else {
4350                 dest.writeBoolean(false);
4351             }
4352         }
4353 
reset(boolean detachIfReset, long elapsedRealtimeUs)4354         public void reset(boolean detachIfReset, long elapsedRealtimeUs) {
4355             resetIfNotNull(mIdleTimeMillis, detachIfReset, elapsedRealtimeUs);
4356             mScanTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
4357             mSleepTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
4358             resetIfNotNull(mRxTimeMillis, detachIfReset, elapsedRealtimeUs);
4359             resetIfNotNull(mTxTimeMillis, detachIfReset, elapsedRealtimeUs);
4360             mPowerDrainMaMs.reset(detachIfReset, elapsedRealtimeUs);
4361             mMonitoredRailChargeConsumedMaMs.reset(detachIfReset, elapsedRealtimeUs);
4362         }
4363 
detach()4364         public void detach() {
4365             detachIfNotNull(mIdleTimeMillis);
4366             mScanTimeMillis.detach();
4367             mSleepTimeMillis.detach();
4368             detachIfNotNull(mRxTimeMillis);
4369             detachIfNotNull(mTxTimeMillis);
4370             mPowerDrainMaMs.detach();
4371             mMonitoredRailChargeConsumedMaMs.detach();
4372         }
4373 
4374         /**
4375          * @return a LongSamplingCounter, measuring time spent in the idle state in
4376          * milliseconds.
4377          */
4378         @Override
getIdleTimeCounter()4379         public LongCounter getIdleTimeCounter() {
4380             if (mIdleTimeMillis == null) {
4381                 return ZERO_LONG_COUNTER;
4382             }
4383             return mIdleTimeMillis;
4384         }
4385 
getOrCreateIdleTimeCounter()4386         private TimeMultiStateCounter getOrCreateIdleTimeCounter() {
4387             if (mIdleTimeMillis == null) {
4388                 mIdleTimeMillis = createTimeMultiStateCounter();
4389             }
4390             return mIdleTimeMillis;
4391         }
4392 
4393         /**
4394          * @return a LongSamplingCounter, measuring time spent in the scan state in
4395          * milliseconds.
4396          */
4397         @Override
getScanTimeCounter()4398         public LongSamplingCounter getScanTimeCounter() {
4399             return mScanTimeMillis;
4400         }
4401 
4402         /**
4403          * @return a LongSamplingCounter, measuring time spent in the sleep state in
4404          * milliseconds.
4405          */
4406         @Override
getSleepTimeCounter()4407         public LongSamplingCounter getSleepTimeCounter() {
4408             return mSleepTimeMillis;
4409         }
4410 
4411         /**
4412          * @return a LongSamplingCounter, measuring time spent in the receive state in
4413          * milliseconds.
4414          */
4415         @Override
getRxTimeCounter()4416         public LongCounter getRxTimeCounter() {
4417             if (mRxTimeMillis == null) {
4418                 return ZERO_LONG_COUNTER;
4419             }
4420             return mRxTimeMillis;
4421         }
4422 
getOrCreateRxTimeCounter()4423         private TimeMultiStateCounter getOrCreateRxTimeCounter() {
4424             if (mRxTimeMillis == null) {
4425                 mRxTimeMillis = createTimeMultiStateCounter();
4426             }
4427             return mRxTimeMillis;
4428         }
4429 
4430         /**
4431          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
4432          * milliseconds.
4433          */
4434         @Override
getTxTimeCounters()4435         public LongCounter[] getTxTimeCounters() {
4436             if (mTxTimeMillis == null) {
4437                 return ZERO_LONG_COUNTER_ARRAY;
4438             }
4439             return mTxTimeMillis;
4440         }
4441 
getOrCreateTxTimeCounters()4442         private TimeMultiStateCounter[] getOrCreateTxTimeCounters() {
4443             if (mTxTimeMillis == null) {
4444                 mTxTimeMillis = new TimeMultiStateCounter[mNumTxStates];
4445                 for (int i = 0; i < mNumTxStates; i++) {
4446                     mTxTimeMillis[i] = createTimeMultiStateCounter();
4447                 }
4448             }
4449             return mTxTimeMillis;
4450         }
4451 
createTimeMultiStateCounter()4452         private TimeMultiStateCounter createTimeMultiStateCounter() {
4453             final long timestampMs = mClock.elapsedRealtime();
4454             TimeMultiStateCounter counter = new TimeMultiStateCounter(mTimeBase,
4455                     BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
4456             counter.setState(mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
4457                     timestampMs);
4458             counter.update(0, timestampMs);
4459             return counter;
4460         }
4461 
4462         /**
4463          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
4464          */
4465         @Override
getPowerCounter()4466         public LongSamplingCounter getPowerCounter() {
4467             return mPowerDrainMaMs;
4468         }
4469 
4470         /**
4471          * @return a LongSamplingCounter, measuring actual monitored rail energy consumed
4472          * milli-ampere milli-seconds (mAmS).
4473          */
4474         @Override
getMonitoredRailChargeConsumedMaMs()4475         public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() {
4476             return mMonitoredRailChargeConsumedMaMs;
4477         }
4478 
setState(int processState, long elapsedTimeMs)4479         private void setState(int processState, long elapsedTimeMs) {
4480             mProcessState = processState;
4481             if (mIdleTimeMillis != null) {
4482                 mIdleTimeMillis.setState(processState, elapsedTimeMs);
4483             }
4484             if (mRxTimeMillis != null) {
4485                 mRxTimeMillis.setState(processState, elapsedTimeMs);
4486             }
4487             if (mTxTimeMillis != null) {
4488                 for (int i = 0; i < mTxTimeMillis.length; i++) {
4489                     mTxTimeMillis[i].setState(processState, elapsedTimeMs);
4490                 }
4491             }
4492         }
4493     }
4494 
4495     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)4496     public SamplingTimer getRpmTimerLocked(String name) {
4497         SamplingTimer rpmt = mRpmStats.get(name);
4498         if (rpmt == null) {
4499             rpmt = new SamplingTimer(mClock, mOnBatteryTimeBase);
4500             mRpmStats.put(name, rpmt);
4501         }
4502         return rpmt;
4503     }
4504 
4505     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)4506     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
4507         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
4508         if (rpmt == null) {
4509             rpmt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
4510             mScreenOffRpmStats.put(name, rpmt);
4511         }
4512         return rpmt;
4513     }
4514 
4515     /*
4516      * Get the wakeup reason counter, and create a new one if one
4517      * doesn't already exist.
4518      */
getWakeupReasonTimerLocked(String name)4519     public SamplingTimer getWakeupReasonTimerLocked(String name) {
4520         SamplingTimer timer = mWakeupReasonStats.get(name);
4521         if (timer == null) {
4522             timer = new SamplingTimer(mClock, mOnBatteryTimeBase);
4523             mWakeupReasonStats.put(name, timer);
4524         }
4525         return timer;
4526     }
4527 
4528     /*
4529      * Get the KernelWakelockTimer associated with name, and create a new one if one
4530      * doesn't already exist.
4531      */
getKernelWakelockTimerLocked(String name)4532     public SamplingTimer getKernelWakelockTimerLocked(String name) {
4533         SamplingTimer kwlt = mKernelWakelockStats.get(name);
4534         if (kwlt == null) {
4535             kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
4536             mKernelWakelockStats.put(name, kwlt);
4537         }
4538         return kwlt;
4539     }
4540 
getKernelMemoryTimerLocked(long bucket)4541     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
4542         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
4543         if (kmt == null) {
4544             kmt = new SamplingTimer(mClock, mOnBatteryTimeBase);
4545             mKernelMemoryStats.put(bucket, kmt);
4546         }
4547         return kmt;
4548     }
4549 
4550     @GuardedBy("this")
4551     @Override
commitCurrentHistoryBatchLocked()4552     public void commitCurrentHistoryBatchLocked() {
4553         mHistory.commitCurrentHistoryBatchLocked();
4554     }
4555 
4556     @GuardedBy("this")
createFakeHistoryEvents(long numEvents)4557     public void createFakeHistoryEvents(long numEvents) {
4558         final long elapsedRealtimeMs = mClock.elapsedRealtime();
4559         final long uptimeMs = mClock.uptimeMillis();
4560         for(long i = 0; i < numEvents; i++) {
4561             noteLongPartialWakelockStart("name1", "historyName1", 1000,
4562                     elapsedRealtimeMs, uptimeMs);
4563             noteLongPartialWakelockFinish("name1", "historyName1", 1000,
4564                     elapsedRealtimeMs, uptimeMs);
4565         }
4566     }
4567 
4568     @GuardedBy("this")
recordHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)4569     public void recordHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
4570             String name, int uid) {
4571         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
4572     }
4573 
4574     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs, long realtimeUs)4575     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs,
4576             long realtimeUs) {
4577         final boolean screenOff = !Display.isOnState(screenState);
4578         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
4579         final boolean updateOnBatteryScreenOffTimeBase =
4580                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
4581 
4582         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
4583             if (updateOnBatteryScreenOffTimeBase) {
4584                 updateKernelWakelocksLocked(realtimeUs);
4585                 updateBatteryPropertiesLocked();
4586             }
4587             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
4588             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
4589             // improved, remove the surrounding if{}.
4590             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
4591                 // if either OnBattery or OnBatteryScreenOfftimebase changes.
4592                 updateRpmStatsLocked(realtimeUs);
4593             }
4594             if (DEBUG_ENERGY_CPU) {
4595                 Slog.d(TAG, "Updating cpu time because screen is now "
4596                         + Display.stateToString(screenState)
4597                         + " and battery is " + (unplugged ? "on" : "off"));
4598             }
4599 
4600             mOnBatteryTimeBase.setRunning(unplugged, uptimeUs, realtimeUs);
4601             if (updateOnBatteryTimeBase) {
4602                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4603                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptimeUs, realtimeUs);
4604                 }
4605             }
4606             if (updateOnBatteryScreenOffTimeBase) {
4607                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff,
4608                         uptimeUs, realtimeUs);
4609                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4610                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptimeUs, realtimeUs);
4611                 }
4612             }
4613         }
4614     }
4615 
4616     @GuardedBy("this")
updateBatteryPropertiesLocked()4617     protected void updateBatteryPropertiesLocked() {
4618         try {
4619             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
4620                     ServiceManager.getService("batteryproperties"));
4621             if (registrar != null) {
4622                 registrar.scheduleUpdate();
4623             }
4624         } catch (RemoteException e) {
4625             // Ignore.
4626         }
4627     }
4628 
onIsolatedUidAdded(int isolatedUid, int parentUid)4629     private void onIsolatedUidAdded(int isolatedUid, int parentUid) {
4630         long realtime = mClock.elapsedRealtime();
4631         long uptime = mClock.uptimeMillis();
4632         synchronized (this) {
4633             getUidStatsLocked(parentUid, realtime, uptime).addIsolatedUid(isolatedUid);
4634         }
4635     }
4636 
onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid)4637     private void onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid) {
4638         long realtime = mClock.elapsedRealtime();
4639         mPowerStatsUidResolver.retainIsolatedUid(isolatedUid);
4640         synchronized (this) {
4641             mPendingRemovedUids.add(new UidToRemove(isolatedUid, realtime));
4642         }
4643         if (mExternalSync != null) {
4644             mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
4645         }
4646     }
4647 
onAfterIsolatedUidRemoved(int isolatedUid, int parentUid)4648     private void onAfterIsolatedUidRemoved(int isolatedUid, int parentUid) {
4649         long realtime = mClock.elapsedRealtime();
4650         long uptime = mClock.uptimeMillis();
4651         synchronized (this) {
4652             getUidStatsLocked(parentUid, realtime, uptime).removeIsolatedUid(isolatedUid);
4653         }
4654     }
4655 
4656     /**
4657      * Isolated uid should only be removed after all wakelocks associated with the uid are stopped
4658      * and the cpu time-in-state has been read one last time for the uid.
4659      */
4660     @GuardedBy("this")
releaseIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs)4661     public void releaseIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs) {
4662         mPowerStatsUidResolver.releaseIsolatedUid(isolatedUid);
4663     }
4664 
mapUid(int uid)4665     private int mapUid(int uid) {
4666         if (Process.isSdkSandboxUid(uid)) {
4667             return Process.getAppUidForSdkSandboxUid(uid);
4668         }
4669         return mPowerStatsUidResolver.mapUid(uid);
4670     }
4671 
mapIsolatedUid(int uid)4672     private int mapIsolatedUid(int uid) {
4673         return mPowerStatsUidResolver.mapUid(uid);
4674     }
4675 
4676     @GuardedBy("this")
noteEventLocked(int code, String name, int uid, long elapsedRealtimeMs, long uptimeMs)4677     public void noteEventLocked(int code, String name, int uid,
4678             long elapsedRealtimeMs, long uptimeMs) {
4679         uid = mapUid(uid);
4680         if (!mActiveEvents.updateState(code, name, uid, 0)) {
4681             return;
4682         }
4683         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
4684     }
4685 
4686     @GuardedBy("this")
noteCurrentTimeChangedLocked(long currentTimeMs, long elapsedRealtimeMs, long uptimeMs)4687     public void noteCurrentTimeChangedLocked(long currentTimeMs,
4688             long elapsedRealtimeMs, long uptimeMs) {
4689         mHistory.recordCurrentTimeChange(elapsedRealtimeMs, uptimeMs, currentTimeMs);
4690         adjustStartClockTime(currentTimeMs);
4691     }
4692 
adjustStartClockTime(long currentTimeMs)4693     private void adjustStartClockTime(long currentTimeMs) {
4694         mStartClockTimeMs =
4695                 currentTimeMs - (mClock.elapsedRealtime() - (mRealtimeStartUs / 1000));
4696     }
4697 
4698     @GuardedBy("this")
noteProcessStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4699     public void noteProcessStartLocked(String name, int uid,
4700             long elapsedRealtimeMs, long uptimeMs) {
4701         uid = mapUid(uid);
4702         if (isOnBattery()) {
4703             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4704             u.getProcessStatsLocked(name).incStartsLocked();
4705         }
4706         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
4707             return;
4708         }
4709         if (!mRecordAllHistory) {
4710             return;
4711         }
4712         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
4713     }
4714 
4715     @GuardedBy("this")
noteProcessCrashLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4716     public void noteProcessCrashLocked(String name, int uid,
4717             long elapsedRealtimeMs, long uptimeMs) {
4718         uid = mapUid(uid);
4719         if (isOnBattery()) {
4720             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4721             u.getProcessStatsLocked(name).incNumCrashesLocked();
4722         }
4723     }
4724 
4725     @GuardedBy("this")
noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4726     public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4727         uid = mapUid(uid);
4728         if (isOnBattery()) {
4729             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4730             u.getProcessStatsLocked(name).incNumAnrsLocked();
4731         }
4732     }
4733 
4734     @GuardedBy("this")
noteUidProcessStateLocked(int uid, int state)4735     public void noteUidProcessStateLocked(int uid, int state) {
4736         noteUidProcessStateLocked(uid, state, mClock.elapsedRealtime(), mClock.uptimeMillis());
4737     }
4738 
4739     @GuardedBy("this")
4740     @SuppressWarnings("GuardedBy")   // errorprone false positive on u.updateUidProcessStateLocked
noteUidProcessStateLocked(int uid, int state, long elapsedRealtimeMs, long uptimeMs)4741     public void noteUidProcessStateLocked(int uid, int state,
4742             long elapsedRealtimeMs, long uptimeMs) {
4743         int parentUid = mapUid(uid);
4744         if (uid != parentUid) {
4745             if (Process.isIsolated(uid)) {
4746                 // Isolated UIDs process state is already rolled up into parent, so no need to track
4747                 // Otherwise the parent's process state will get downgraded incorrectly
4748                 return;
4749             }
4750         }
4751         mFrameworkStatsLogger.uidProcessStateChanged(uid, state);
4752         getUidStatsLocked(parentUid, elapsedRealtimeMs, uptimeMs)
4753                 .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs);
4754     }
4755 
4756     @GuardedBy("this")
noteProcessFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4757     public void noteProcessFinishLocked(String name, int uid,
4758             long elapsedRealtimeMs, long uptimeMs) {
4759         uid = mapUid(uid);
4760         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4761             return;
4762         }
4763         if (!mRecordAllHistory) {
4764             return;
4765         }
4766         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH, name, uid);
4767     }
4768 
4769     @GuardedBy("this")
noteSyncStartLocked(String name, int uid)4770     public void noteSyncStartLocked(String name, int uid) {
4771         noteSyncStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4772     }
4773 
4774     @GuardedBy("this")
noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4775     public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4776         uid = mapUid(uid);
4777         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4778                 .noteStartSyncLocked(name, elapsedRealtimeMs);
4779         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4780             return;
4781         }
4782         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
4783     }
4784 
4785     @GuardedBy("this")
noteSyncFinishLocked(String name, int uid)4786     public void noteSyncFinishLocked(String name, int uid) {
4787         noteSyncFinishLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4788     }
4789 
4790     @GuardedBy("this")
noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4791     public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4792         uid = mapUid(uid);
4793         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4794                 .noteStopSyncLocked(name, elapsedRealtimeMs);
4795         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4796             return;
4797         }
4798         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH, name, uid);
4799     }
4800 
4801     @GuardedBy("this")
noteJobStartLocked(String name, int uid)4802     public void noteJobStartLocked(String name, int uid) {
4803         noteJobStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4804     }
4805 
4806     @GuardedBy("this")
noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4807     public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4808         uid = mapUid(uid);
4809         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4810                 .noteStartJobLocked(name, elapsedRealtimeMs);
4811         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4812             return;
4813         }
4814         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
4815     }
4816 
4817     @GuardedBy("this")
noteJobFinishLocked(String name, int uid, int stopReason)4818     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4819         noteJobFinishLocked(name, uid, stopReason,
4820                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4821     }
4822 
4823     @GuardedBy("this")
noteJobFinishLocked(String name, int uid, int stopReason, long elapsedRealtimeMs, long uptimeMs)4824     public void noteJobFinishLocked(String name, int uid, int stopReason,
4825             long elapsedRealtimeMs, long uptimeMs) {
4826         uid = mapUid(uid);
4827         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4828                 .noteStopJobLocked(name, elapsedRealtimeMs, stopReason);
4829         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4830             return;
4831         }
4832         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
4833     }
4834 
4835     @GuardedBy("this")
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast, long elapsedRealtimeMs, long uptimeMs)4836     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast,
4837             long elapsedRealtimeMs, long uptimeMs) {
4838         uid = mapUid(uid);
4839         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4840                 .noteJobsDeferredLocked(numDeferred, sinceLast);
4841     }
4842 
4843     @GuardedBy("this")
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4844     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4845         noteAlarmStartLocked(name, workSource, uid,
4846                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4847     }
4848 
4849     @GuardedBy("this")
noteAlarmStartLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4850     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid,
4851             long elapsedRealtimeMs, long uptimeMs) {
4852         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid,
4853                 elapsedRealtimeMs, uptimeMs);
4854     }
4855 
4856     @GuardedBy("this")
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)4857     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4858         noteAlarmFinishLocked(name, workSource, uid,
4859                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4860     }
4861 
4862     @GuardedBy("this")
noteAlarmFinishLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4863     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid,
4864             long elapsedRealtimeMs, long uptimeMs) {
4865         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid,
4866                 elapsedRealtimeMs, uptimeMs);
4867     }
4868 
4869     @GuardedBy("this")
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4870     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4871             int uid, long elapsedRealtimeMs, long uptimeMs) {
4872         if (!mRecordAllHistory) {
4873             return;
4874         }
4875 
4876         if (workSource != null) {
4877             for (int i = 0; i < workSource.size(); ++i) {
4878                 uid = mapUid(workSource.getUid(i));
4879                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4880                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4881                 }
4882             }
4883 
4884             List<WorkChain> workChains = workSource.getWorkChains();
4885             if (workChains != null) {
4886                 for (int i = 0; i < workChains.size(); ++i) {
4887                     uid = mapUid(workChains.get(i).getAttributionUid());
4888                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4889                         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4890                     }
4891                 }
4892             }
4893         } else {
4894             uid = mapUid(uid);
4895 
4896             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4897                 mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4898             }
4899         }
4900     }
4901 
4902     @GuardedBy("this")
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)4903     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4904             String tag) {
4905         noteWakupAlarmLocked(packageName, uid, workSource, tag,
4906                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4907     }
4908 
4909     @GuardedBy("this")
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag, long elapsedRealtimeMs, long uptimeMs)4910     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4911             String tag, long elapsedRealtimeMs, long uptimeMs) {
4912         if (workSource != null) {
4913             for (int i = 0; i < workSource.size(); ++i) {
4914                 uid = workSource.getUid(i);
4915                 final String workSourceName = workSource.getPackageName(i);
4916 
4917                 if (isOnBattery()) {
4918                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4919                             workSourceName != null ? workSourceName : packageName,
4920                             elapsedRealtimeMs, uptimeMs);
4921                     pkg.noteWakeupAlarmLocked(tag);
4922                 }
4923             }
4924 
4925             List<WorkChain> workChains = workSource.getWorkChains();
4926             if (workChains != null) {
4927                 for (int i = 0; i < workChains.size(); ++i) {
4928                     final WorkChain wc = workChains.get(i);
4929                     uid = wc.getAttributionUid();
4930 
4931                     if (isOnBattery()) {
4932                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4933                                 elapsedRealtimeMs, uptimeMs);
4934                         pkg.noteWakeupAlarmLocked(tag);
4935                     }
4936                 }
4937             }
4938         } else {
4939             if (isOnBattery()) {
4940                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4941                         elapsedRealtimeMs, uptimeMs);
4942                 pkg.noteWakeupAlarmLocked(tag);
4943             }
4944         }
4945     }
4946 
requestWakelockCpuUpdate()4947     private void requestWakelockCpuUpdate() {
4948         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4949     }
4950 
requestImmediateCpuUpdate()4951     private void requestImmediateCpuUpdate() {
4952         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4953     }
4954 
4955     @GuardedBy("this")
setRecordAllHistoryLocked(boolean enabled)4956     public void setRecordAllHistoryLocked(boolean enabled) {
4957         mRecordAllHistory = enabled;
4958         if (!enabled) {
4959             // Clear out any existing state.
4960             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4961             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4962             // Record the currently running processes as stopping, now that we are no
4963             // longer tracking them.
4964             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4965                     HistoryItem.EVENT_PROC);
4966             if (active != null) {
4967                 long mSecRealtime = mClock.elapsedRealtime();
4968                 final long mSecUptime = mClock.uptimeMillis();
4969                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4970                     SparseIntArray uids = ent.getValue();
4971                     for (int j=0; j<uids.size(); j++) {
4972                         mHistory.recordEvent(mSecRealtime, mSecUptime,
4973                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4974                     }
4975                 }
4976             }
4977         } else {
4978             // Record the currently running processes as starting, now that we are tracking them.
4979             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4980                     HistoryItem.EVENT_PROC);
4981             if (active != null) {
4982                 long mSecRealtime = mClock.elapsedRealtime();
4983                 final long mSecUptime = mClock.uptimeMillis();
4984                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4985                     SparseIntArray uids = ent.getValue();
4986                     for (int j=0; j<uids.size(); j++) {
4987                         mHistory.recordEvent(mSecRealtime, mSecUptime, HistoryItem.EVENT_PROC_START,
4988                                 ent.getKey(), uids.keyAt(j));
4989                     }
4990                 }
4991             }
4992         }
4993     }
4994 
setNoAutoReset(boolean enabled)4995     public void setNoAutoReset(boolean enabled) {
4996         mNoAutoReset = enabled;
4997     }
4998 
4999     @GuardedBy("this")
setPretendScreenOff(boolean pretendScreenOff)5000     public void setPretendScreenOff(boolean pretendScreenOff) {
5001         if (mPretendScreenOff != pretendScreenOff) {
5002             mPretendScreenOff = pretendScreenOff;
5003             final int primaryScreenState = mPerDisplayBatteryStats[0].screenState;
5004             noteScreenStateLocked(0, primaryScreenState);
5005         }
5006     }
5007 
5008     @GuardedBy("this")
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging)5009     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5010             int type, boolean unimportantForLogging) {
5011         noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging,
5012                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5013     }
5014 
5015     @GuardedBy("this")
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)5016     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5017             int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) {
5018         final int mappedUid = mapUid(uid);
5019         if (type == WAKE_TYPE_PARTIAL) {
5020             // Only care about partial wake locks, since full wake locks
5021             // will be canceled when the user puts the screen to sleep.
5022             if (historyName == null) {
5023                 historyName = name;
5024             }
5025             if (mRecordAllHistory) {
5026                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
5027                         mappedUid, 0)) {
5028                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
5029                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, mappedUid);
5030                 }
5031             }
5032             if (mWakeLockNesting == 0) {
5033                 mWakeLockImportant = !unimportantForLogging;
5034                 mHistory.recordWakelockStartEvent(elapsedRealtimeMs, uptimeMs, historyName,
5035                         mappedUid);
5036             } else if (!mWakeLockImportant && !unimportantForLogging) {
5037                 if (mHistory.maybeUpdateWakelockTag(elapsedRealtimeMs, uptimeMs, historyName,
5038                         mappedUid)) {
5039                     mWakeLockImportant = true;
5040                 }
5041             }
5042             mWakeLockNesting++;
5043         }
5044         if (mappedUid >= 0) {
5045             if (mappedUid != uid) {
5046                 // Prevent the isolated uid mapping from being removed while the wakelock is
5047                 // being held.
5048                 mPowerStatsUidResolver.retainIsolatedUid(uid);
5049             }
5050             if (mOnBatteryScreenOffTimeBase.isRunning()) {
5051                 // We only update the cpu time when a wake lock is acquired if the screen is off.
5052                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
5053                 if (DEBUG_ENERGY_CPU) {
5054                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
5055                 }
5056                 requestWakelockCpuUpdate();
5057             }
5058 
5059             Uid uidStats = getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs);
5060             uidStats.noteStartWakeLocked(pid, name, type, elapsedRealtimeMs);
5061             if (!mMoveWscLoggingToNotifierEnabled) {
5062                 mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name,
5063                         uidStats.mProcessState, true /* acquired */,
5064                         getPowerManagerWakeLockLevel(type));
5065             }
5066             if (mPowerManagerFlags.isFrameworkWakelockInfoEnabled()) {
5067                 mFrameworkEvents.noteStartWakeLock(
5068                         mapIsolatedUid(uid), name, getPowerManagerWakeLockLevel(type), uptimeMs);
5069             }
5070         }
5071     }
5072 
5073     @GuardedBy("this")
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type)5074     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5075             int type) {
5076         noteStopWakeLocked(uid, pid, wc, name, historyName, type,
5077                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5078     }
5079 
5080     @GuardedBy("this")
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)5081     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5082             int type, long elapsedRealtimeMs, long uptimeMs) {
5083         final int mappedUid = mapUid(uid);
5084         if (type == WAKE_TYPE_PARTIAL) {
5085             mWakeLockNesting--;
5086             if (historyName == null) {
5087                 historyName = name;
5088             }
5089             if (mRecordAllHistory) {
5090                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
5091                         mappedUid, 0)) {
5092                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
5093                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid);
5094                 }
5095             }
5096             if (mWakeLockNesting == 0) {
5097                 mHistory.recordWakelockStopEvent(elapsedRealtimeMs, uptimeMs, historyName,
5098                         mappedUid);
5099             }
5100         }
5101         if (mappedUid >= 0) {
5102             if (mOnBatteryScreenOffTimeBase.isRunning()) {
5103                 if (DEBUG_ENERGY_CPU) {
5104                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
5105                 }
5106                 requestWakelockCpuUpdate();
5107             }
5108 
5109             Uid uidStats = getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs);
5110             uidStats.noteStopWakeLocked(pid, name, type, elapsedRealtimeMs);
5111 
5112             if (!mMoveWscLoggingToNotifierEnabled) {
5113                 mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name,
5114                         uidStats.mProcessState, false/* acquired */,
5115                         getPowerManagerWakeLockLevel(type));
5116             }
5117             if (mPowerManagerFlags.isFrameworkWakelockInfoEnabled()) {
5118                 mFrameworkEvents.noteStopWakeLock(
5119                         mapIsolatedUid(uid), name, getPowerManagerWakeLockLevel(type), uptimeMs);
5120             }
5121 
5122             if (mappedUid != uid) {
5123                 // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
5124                 releaseIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
5125             }
5126         }
5127     }
5128 
5129     /**
5130      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
5131      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
5132      * These are estimations, since batterystats loses some of the original data.
5133      * TODO: Delete this. Instead, FrameworkStatsLog.write should be called from
5134      * PowerManager's Notifier.
5135      */
getPowerManagerWakeLockLevel(int batteryStatsWakelockType)5136     private int getPowerManagerWakeLockLevel(int batteryStatsWakelockType) {
5137         switch (batteryStatsWakelockType) {
5138             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
5139             case BatteryStats.WAKE_TYPE_PARTIAL:
5140                 return PowerManager.PARTIAL_WAKE_LOCK;
5141 
5142             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
5143             case BatteryStats.WAKE_TYPE_FULL:
5144                 return PowerManager.FULL_WAKE_LOCK;
5145 
5146             case BatteryStats.WAKE_TYPE_DRAW:
5147                 return PowerManager.DRAW_WAKE_LOCK;
5148 
5149             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
5150             case BatteryStats.WAKE_TYPE_WINDOW:
5151                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
5152                 return -1;
5153 
5154             default:
5155                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + batteryStatsWakelockType);
5156                 return -1;
5157         }
5158     }
5159 
5160     @GuardedBy("this")
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)5161     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
5162             String historyName, int type, boolean unimportantForLogging,
5163             long elapsedRealtimeMs, long uptimeMs) {
5164         final int N = ws.size();
5165         for (int i=0; i<N; i++) {
5166             noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
5167                     unimportantForLogging, elapsedRealtimeMs, uptimeMs);
5168         }
5169 
5170         List<WorkChain> wcs = ws.getWorkChains();
5171         if (wcs != null) {
5172             for (int i = 0; i < wcs.size(); ++i) {
5173                 final WorkChain wc = wcs.get(i);
5174                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
5175                         unimportantForLogging, elapsedRealtimeMs, uptimeMs);
5176             }
5177         }
5178     }
5179 
5180     @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)5181     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
5182             String historyName, int type, WorkSource newWs, int newPid, String newName,
5183             String newHistoryName, int newType, boolean newUnimportantForLogging,
5184             long elapsedRealtimeMs, long uptimeMs) {
5185         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
5186 
5187         // For correct semantics, we start the need worksources first, so that we won't
5188         // make inappropriate history items as if all wake locks went away and new ones
5189         // appeared.  This is okay because tracking of wake locks allows nesting.
5190         //
5191         // First the starts :
5192         final int NN = newWs.size();
5193         for (int i=0; i<NN; i++) {
5194             noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
5195                     newUnimportantForLogging, elapsedRealtimeMs, uptimeMs);
5196         }
5197         if (wcs != null) {
5198             List<WorkChain> newChains = wcs[0];
5199             if (newChains != null) {
5200                 for (int i = 0; i < newChains.size(); ++i) {
5201                     final WorkChain newChain = newChains.get(i);
5202                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
5203                             newHistoryName, newType, newUnimportantForLogging, elapsedRealtimeMs,
5204                             uptimeMs);
5205                 }
5206             }
5207         }
5208 
5209         // Then the stops :
5210         final int NO = ws.size();
5211         for (int i=0; i<NO; i++) {
5212             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
5213                     uptimeMs);
5214         }
5215         if (wcs != null) {
5216             List<WorkChain> goneChains = wcs[1];
5217             if (goneChains != null) {
5218                 for (int i = 0; i < goneChains.size(); ++i) {
5219                     final WorkChain goneChain = goneChains.get(i);
5220                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
5221                             historyName, type, elapsedRealtimeMs, uptimeMs);
5222                 }
5223             }
5224         }
5225     }
5226 
5227     @GuardedBy("this")
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)5228     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
5229             String historyName, int type, long elapsedRealtimeMs, long uptimeMs) {
5230         final int N = ws.size();
5231         for (int i=0; i<N; i++) {
5232             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
5233                     uptimeMs);
5234         }
5235 
5236         List<WorkChain> wcs = ws.getWorkChains();
5237         if (wcs != null) {
5238             for (int i = 0; i < wcs.size(); ++i) {
5239                 final WorkChain wc = wcs.get(i);
5240                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
5241                         elapsedRealtimeMs, uptimeMs);
5242             }
5243         }
5244     }
5245 
5246     @GuardedBy("this")
noteLongPartialWakelockStart(String name, String historyName, int uid)5247     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
5248         noteLongPartialWakelockStart(name, historyName, uid,
5249                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5250     }
5251 
5252     @GuardedBy("this")
noteLongPartialWakelockStart(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5253     public void noteLongPartialWakelockStart(String name, String historyName, int uid,
5254             long elapsedRealtimeMs, long uptimeMs) {
5255         noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
5256     }
5257 
5258     @GuardedBy("this")
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)5259     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
5260             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
5261         final int N = workSource.size();
5262         for (int i = 0; i < N; ++i) {
5263             final int uid = mapUid(workSource.getUid(i));
5264             noteLongPartialWakeLockStartInternal(name, historyName, uid,
5265                     elapsedRealtimeMs, uptimeMs);
5266         }
5267 
5268         final List<WorkChain> workChains = workSource.getWorkChains();
5269         if (workChains != null) {
5270             for (int i = 0; i < workChains.size(); ++i) {
5271                 final WorkChain workChain = workChains.get(i);
5272                 final int uid = workChain.getAttributionUid();
5273                 noteLongPartialWakeLockStartInternal(name, historyName, uid,
5274                         elapsedRealtimeMs, uptimeMs);
5275             }
5276         }
5277     }
5278 
5279     @GuardedBy("this")
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5280     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid,
5281             long elapsedRealtimeMs, long uptimeMs) {
5282         final int mappedUid = mapUid(uid);
5283         if (historyName == null) {
5284             historyName = name;
5285         }
5286         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName,
5287                 mappedUid, 0)) {
5288             return;
5289         }
5290         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
5291                 historyName, mappedUid);
5292         if (mappedUid != uid) {
5293             // Prevent the isolated uid mapping from being removed while the wakelock is
5294             // being held.
5295             mPowerStatsUidResolver.retainIsolatedUid(uid);
5296         }
5297     }
5298 
5299     @GuardedBy("this")
noteLongPartialWakelockFinish(String name, String historyName, int uid)5300     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
5301         noteLongPartialWakelockFinish(name, historyName, uid,
5302                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5303     }
5304 
5305     @GuardedBy("this")
noteLongPartialWakelockFinish(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5306     public void noteLongPartialWakelockFinish(String name, String historyName, int uid,
5307             long elapsedRealtimeMs, long uptimeMs) {
5308         noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
5309     }
5310 
5311     @GuardedBy("this")
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)5312     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
5313             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
5314         final int N = workSource.size();
5315         for (int i = 0; i < N; ++i) {
5316             final int uid = mapUid(workSource.getUid(i));
5317             noteLongPartialWakeLockFinishInternal(name, historyName, uid,
5318                     elapsedRealtimeMs, uptimeMs);
5319         }
5320 
5321         final List<WorkChain> workChains = workSource.getWorkChains();
5322         if (workChains != null) {
5323             for (int i = 0; i < workChains.size(); ++i) {
5324                 final WorkChain workChain = workChains.get(i);
5325                 final int uid = workChain.getAttributionUid();
5326                 noteLongPartialWakeLockFinishInternal(name, historyName, uid,
5327                         elapsedRealtimeMs, uptimeMs);
5328             }
5329         }
5330     }
5331 
5332     @GuardedBy("this")
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5333     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid,
5334             long elapsedRealtimeMs, long uptimeMs) {
5335         final int mappedUid = mapUid(uid);
5336         if (historyName == null) {
5337             historyName = name;
5338         }
5339         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName,
5340                 mappedUid, 0)) {
5341             return;
5342         }
5343         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
5344                 historyName, mappedUid);
5345         if (mappedUid != uid) {
5346             // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
5347             releaseIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
5348         }
5349     }
5350 
5351     @GuardedBy("this")
noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs)5352     public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
5353         if (mLastWakeupReason != null) {
5354             long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs;
5355             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
5356             timer.add(deltaUptimeMs * 1000, 1, elapsedRealtimeMs); // time in in microseconds
5357             mFrameworkStatsLogger.kernelWakeupReported(deltaUptimeMs * 1000, mLastWakeupReason,
5358                     mLastWakeupElapsedTimeMs);
5359         }
5360         mHistory.recordWakeupEvent(elapsedRealtimeMs, uptimeMs, reason);
5361         mLastWakeupReason = reason;
5362         mLastWakeupUptimeMs = uptimeMs;
5363         mLastWakeupElapsedTimeMs = elapsedRealtimeMs;
5364     }
5365 
5366     @GuardedBy("this")
startAddingCpuStatsLocked()5367     public boolean startAddingCpuStatsLocked() {
5368         mExternalSync.cancelCpuSyncDueToWakelockChange();
5369         return mOnBatteryInternal;
5370     }
5371 
5372     @GuardedBy("this")
addCpuStatsLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs)5373     public void addCpuStatsLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
5374             int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
5375             int statSoftIrqTimeMs, int statIdleTimeMs) {
5376         mStepDetailsProvider.addCpuStats(totalUTimeMs, totalSTimeMs, statUserTimeMs,
5377                 statSystemTimeMs, statIOWaitTimeMs, statIrqTimeMs,
5378                 statSoftIrqTimeMs, statIdleTimeMs);
5379     }
5380 
5381     /**
5382      * Called after {@link #addCpuStatsLocked} has been invoked for all active apps.
5383      */
5384     @GuardedBy("this")
finishAddingCpuStatsLocked()5385     public void finishAddingCpuStatsLocked() {
5386         mStepDetailsProvider.finishAddingCpuLocked();
5387     }
5388 
noteProcessDiedLocked(int uid, int pid)5389     public void noteProcessDiedLocked(int uid, int pid) {
5390         uid = mapUid(uid);
5391         Uid u = mUidStats.get(uid);
5392         if (u != null) {
5393             u.mPids.remove(pid);
5394         }
5395     }
5396 
reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs)5397     public void reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs) {
5398         uid = mapUid(uid);
5399         Uid u = mUidStats.get(uid);
5400         if (u != null) {
5401             u.reportExcessiveCpuLocked(proc, overTimeMs, usedTimeMs);
5402         }
5403     }
5404 
5405     @GuardedBy("this")
noteStartSensorLocked(int uid, int sensor)5406     public void noteStartSensorLocked(int uid, int sensor) {
5407         noteStartSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
5408     }
5409 
5410     @GuardedBy("this")
noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)5411     public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
5412         uid = mapUid(uid);
5413         mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5414                 HistoryItem.STATE_SENSOR_ON_FLAG, uid, "sensor:0x" + Integer.toHexString(sensor));
5415         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5416                 .noteStartSensor(sensor, elapsedRealtimeMs);
5417     }
5418 
5419     @GuardedBy("this")
noteStopSensorLocked(int uid, int sensor)5420     public void noteStopSensorLocked(int uid, int sensor) {
5421         noteStopSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
5422     }
5423 
5424     @GuardedBy("this")
noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)5425     public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
5426         uid = mapUid(uid);
5427         mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5428                 HistoryItem.STATE_SENSOR_ON_FLAG, uid, "sensor:0x" + Integer.toHexString(sensor));
5429         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5430                 .noteStopSensor(sensor, elapsedRealtimeMs);
5431     }
5432 
5433     int mGpsNesting;
5434 
5435     @GuardedBy("this")
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)5436     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
5437         noteGpsChangedLocked(oldWs, newWs, mClock.elapsedRealtime(), mClock.uptimeMillis());
5438     }
5439 
5440     @GuardedBy("this")
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)5441     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs,
5442             long elapsedRealtimeMs, long uptimeMs) {
5443         for (int i = 0; i < newWs.size(); ++i) {
5444             noteStartGpsLocked(newWs.getUid(i), null, elapsedRealtimeMs, uptimeMs);
5445         }
5446 
5447         for (int i = 0; i < oldWs.size(); ++i) {
5448             noteStopGpsLocked((oldWs.getUid(i)), null, elapsedRealtimeMs, uptimeMs);
5449         }
5450 
5451         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
5452         if (wcs != null) {
5453             if (wcs[0] != null) {
5454                 final List<WorkChain> newChains = wcs[0];
5455                 for (int i = 0; i < newChains.size(); ++i) {
5456                     noteStartGpsLocked(-1, newChains.get(i), elapsedRealtimeMs, uptimeMs);
5457                 }
5458             }
5459 
5460             if (wcs[1] != null) {
5461                 final List<WorkChain> goneChains = wcs[1];
5462                 for (int i = 0; i < goneChains.size(); ++i) {
5463                     noteStopGpsLocked(-1, goneChains.get(i), elapsedRealtimeMs, uptimeMs);
5464                 }
5465             }
5466         }
5467     }
5468 
5469     @GuardedBy("this")
noteStartGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)5470     private void noteStartGpsLocked(int uid, WorkChain workChain,
5471             long elapsedRealtimeMs, long uptimeMs) {
5472         if (workChain != null) {
5473             uid = workChain.getAttributionUid();
5474         }
5475         final int mappedUid = mapUid(uid);
5476         if (mGpsNesting == 0) {
5477             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5478                     HistoryItem.STATE_GPS_ON_FLAG, uid, "gnss");
5479             if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_GNSS)) {
5480                 mGnssPowerStatsCollector.schedule();
5481             }
5482         }
5483         mGpsNesting++;
5484 
5485         mFrameworkStatsLogger.gpsScanStateChanged(mapIsolatedUid(uid), workChain, /* on */true);
5486 
5487         getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
5488     }
5489 
5490     @GuardedBy("this")
noteStopGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)5491     private void noteStopGpsLocked(int uid, WorkChain workChain,
5492             long elapsedRealtimeMs, long uptimeMs) {
5493         if (workChain != null) {
5494             uid = workChain.getAttributionUid();
5495         }
5496         final int mappedUid = mapUid(uid);
5497         mGpsNesting--;
5498         if (mGpsNesting == 0) {
5499             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5500                     HistoryItem.STATE_GPS_ON_FLAG, uid, "gnss");
5501             mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs,
5502                     HistoryItem.GNSS_SIGNAL_QUALITY_NONE);
5503             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
5504             mGpsSignalQualityBin = -1;
5505             if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_GNSS)) {
5506                 mGnssPowerStatsCollector.schedule();
5507             }
5508         }
5509 
5510         mFrameworkStatsLogger.gpsScanStateChanged(mapIsolatedUid(uid), workChain, /* on */ false);
5511 
5512         getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
5513     }
5514 
5515     @GuardedBy("this")
noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs)5516     public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) {
5517         if (mGpsNesting == 0) {
5518             return;
5519         }
5520         if (signalLevel < 0 || signalLevel >= mGpsSignalQualityTimer.length) {
5521             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
5522             return;
5523         }
5524         if (mGpsSignalQualityBin != signalLevel) {
5525             if (mGpsSignalQualityBin >= 0) {
5526                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtimeMs);
5527             }
5528             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
5529                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
5530             }
5531             mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs, signalLevel);
5532             mGpsSignalQualityBin = signalLevel;
5533         }
5534     }
5535 
getScreenStateTag( int display, int state, @Display.StateReason int reason)5536     private static String getScreenStateTag(
5537             int display, int state, @Display.StateReason int reason) {
5538         return String.format(
5539                 "display=%d state=%s reason=%s",
5540                 display, Display.stateToString(state), Display.stateReasonToString(reason));
5541     }
5542 
5543     @GuardedBy("this")
noteScreenStateLocked(int display, int state)5544     public void noteScreenStateLocked(int display, int state) {
5545         noteScreenStateLocked(display, state, Display.STATE_REASON_UNKNOWN,
5546                 mClock.elapsedRealtime(), mClock.uptimeMillis(), mClock.currentTimeMillis());
5547     }
5548 
5549     @GuardedBy("this")
noteScreenStateLocked(int display, int displayState, @Display.StateReason int displayStateReason, long elapsedRealtimeMs, long uptimeMs, long currentTimeMs)5550     public void noteScreenStateLocked(int display, int displayState,
5551             @Display.StateReason int displayStateReason, long elapsedRealtimeMs, long uptimeMs,
5552             long currentTimeMs) {
5553         if (Flags.batteryStatsScreenStateEvent()) {
5554             mHistory.recordEvent(
5555                     elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_DISPLAY_STATE_CHANGED,
5556                     getScreenStateTag(display, displayState, displayStateReason),
5557                     Process.INVALID_UID);
5558         }
5559         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
5560         // original 4 are mapped to one of the originals.
5561         if (displayState > MAX_TRACKED_SCREEN_STATE) {
5562             if (Display.isOnState(displayState)) {
5563                 displayState = Display.STATE_ON;
5564             } else if (Display.isDozeState(displayState)) {
5565                 if (Display.isSuspendedState(displayState)) {
5566                     displayState = Display.STATE_DOZE_SUSPEND;
5567                 } else {
5568                     displayState = Display.STATE_DOZE;
5569                 }
5570             } else if (Display.isOffState(displayState)) {
5571                 displayState = Display.STATE_OFF;
5572             } else {
5573                 Slog.wtf(TAG, "Unknown screen state (not mapped): " + displayState);
5574                 displayState = Display.STATE_UNKNOWN;
5575             }
5576         }
5577         // As of this point, displayState should be mapped to one of:
5578         //  - Display.STATE_ON,
5579         //  - Display.STATE_DOZE
5580         //  - Display.STATE_DOZE_SUSPEND
5581         //  - Display.STATE_OFF
5582         //  - Display.STATE_UNKNOWN
5583 
5584         int state;
5585         int overallBin = mScreenBrightnessBin;
5586         int externalUpdateFlag = 0;
5587         boolean shouldScheduleSync = false;
5588         final int numDisplay = mPerDisplayBatteryStats.length;
5589         if (display < 0 || display >= numDisplay) {
5590             Slog.wtf(TAG, "Unexpected note screen state for display " + display + " (only "
5591                     + mPerDisplayBatteryStats.length + " displays exist...)");
5592             return;
5593         }
5594         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5595         final int oldDisplayState = displayStats.screenState;
5596 
5597         if (oldDisplayState == displayState) {
5598             // Nothing changed
5599             state = mScreenState;
5600         } else {
5601             displayStats.screenState = displayState;
5602 
5603             // Stop timer for previous display state.
5604             switch (oldDisplayState) {
5605                 case Display.STATE_ON:
5606                     displayStats.screenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5607                     final int bin = displayStats.screenBrightnessBin;
5608                     if (bin >= 0) {
5609                         displayStats.screenBrightnessTimers[bin].stopRunningLocked(
5610                                 elapsedRealtimeMs);
5611                     }
5612                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5613                     shouldScheduleSync = true;
5614                     break;
5615                 case Display.STATE_DOZE:
5616                     // Transition from doze to doze suspend can be ignored.
5617                     if (displayState == Display.STATE_DOZE_SUSPEND) break;
5618                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5619                     shouldScheduleSync = true;
5620                     break;
5621                 case Display.STATE_DOZE_SUSPEND:
5622                     // Transition from doze suspend to doze can be ignored.
5623                     if (displayState == Display.STATE_DOZE) break;
5624                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5625                     shouldScheduleSync = true;
5626                     break;
5627                 case Display.STATE_OFF:
5628                     shouldScheduleSync = true;
5629                     break;
5630                 case Display.STATE_UNKNOWN:
5631                     // Not tracked by timers.
5632                     break;
5633                 default:
5634                     Slog.wtf(TAG,
5635                             "Attempted to stop timer for unexpected display state " + display);
5636             }
5637 
5638             // Start timer for new display state.
5639             switch (displayState) {
5640                 case Display.STATE_ON:
5641                     displayStats.screenOnTimer.startRunningLocked(elapsedRealtimeMs);
5642                     final int bin = displayStats.screenBrightnessBin;
5643                     if (bin >= 0) {
5644                         displayStats.screenBrightnessTimers[bin].startRunningLocked(
5645                                 elapsedRealtimeMs);
5646                     }
5647                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5648                     shouldScheduleSync = true;
5649                     break;
5650                 case Display.STATE_DOZE:
5651                     // Transition from doze suspend to doze can be ignored.
5652                     if (oldDisplayState == Display.STATE_DOZE_SUSPEND) break;
5653                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5654                     shouldScheduleSync = true;
5655                     break;
5656                 case Display.STATE_DOZE_SUSPEND:
5657                     // Transition from doze to doze suspend can be ignored.
5658                     if (oldDisplayState == Display.STATE_DOZE) break;
5659                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5660                     shouldScheduleSync = true;
5661                     break;
5662                 case Display.STATE_OFF:
5663                     shouldScheduleSync = true;
5664                     break;
5665                 case Display.STATE_UNKNOWN:
5666                     // Not tracked by timers.
5667                     break;
5668                 default:
5669                     Slog.wtf(TAG,
5670                             "Attempted to start timer for unexpected display state " + displayState
5671                                     + " for display " + display);
5672             }
5673 
5674             if (shouldScheduleSync
5675                     && mGlobalEnergyConsumerStats != null
5676                     && mGlobalEnergyConsumerStats.isStandardBucketSupported(
5677                     EnergyConsumerStats.POWER_BUCKET_SCREEN_ON)) {
5678                 // Display energy consumption stats is available. Prepare to schedule an
5679                 // external sync.
5680                 externalUpdateFlag |= ExternalStatsSync.UPDATE_DISPLAY;
5681             }
5682 
5683             // Reevaluate most important display screen state.
5684             state = Display.STATE_UNKNOWN;
5685             for (int i = 0; i < numDisplay; i++) {
5686                 final int tempState = mPerDisplayBatteryStats[i].screenState;
5687                 if (tempState == Display.STATE_ON
5688                         || state == Display.STATE_ON) {
5689                     state = Display.STATE_ON;
5690                 } else if (tempState == Display.STATE_DOZE
5691                         || state == Display.STATE_DOZE) {
5692                     state = Display.STATE_DOZE;
5693                 } else if (tempState == Display.STATE_DOZE_SUSPEND
5694                         || state == Display.STATE_DOZE_SUSPEND) {
5695                     state = Display.STATE_DOZE_SUSPEND;
5696                 } else if (tempState == Display.STATE_OFF
5697                         || state == Display.STATE_OFF) {
5698                     state = Display.STATE_OFF;
5699                 }
5700             }
5701         }
5702 
5703         final boolean batteryRunning = mOnBatteryTimeBase.isRunning();
5704         final boolean batteryScreenOffRunning = mOnBatteryScreenOffTimeBase.isRunning();
5705 
5706         state = mPretendScreenOff ? Display.STATE_OFF : state;
5707         if (mScreenState != state) {
5708             recordDailyStatsIfNeededLocked(true, currentTimeMs);
5709             final int oldState = mScreenState;
5710             mScreenState = state;
5711             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
5712                     + ", newState=" + Display.stateToString(state));
5713 
5714             if (state != Display.STATE_UNKNOWN) {
5715                 int stepState = state-1;
5716                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
5717                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
5718                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
5719                 } else {
5720                     Slog.wtf(TAG, "Unexpected screen state: " + state);
5721                 }
5722             }
5723 
5724             int startStates = 0;
5725             int stopStates = 0;
5726             if (Display.isDozeState(state) && !Display.isDozeState(oldState)) {
5727                 startStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
5728                 mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5729             } else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) {
5730                 stopStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
5731                 mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5732             }
5733             if (Display.isOnState(state)) {
5734                 startStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
5735                 mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
5736                 if (mScreenBrightnessBin >= 0) {
5737                     mScreenBrightnessTimer[mScreenBrightnessBin]
5738                             .startRunningLocked(elapsedRealtimeMs);
5739                 }
5740             } else if (Display.isOnState(oldState)) {
5741                 stopStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
5742                 mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5743                 if (mScreenBrightnessBin >= 0) {
5744                     mScreenBrightnessTimer[mScreenBrightnessBin]
5745                             .stopRunningLocked(elapsedRealtimeMs);
5746                 }
5747             }
5748             if (startStates != 0 || stopStates != 0) {
5749                 mHistory.recordStateChangeEvent(elapsedRealtimeMs, uptimeMs, startStates,
5750                         stopStates);
5751             }
5752 
5753             // Per screen state Cpu stats needed. Prepare to schedule an external sync.
5754             externalUpdateFlag |= ExternalStatsSync.UPDATE_CPU;
5755             shouldScheduleSync = true;
5756 
5757             if (Display.isOnState(state)) {
5758                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
5759                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
5760                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
5761                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
5762                         elapsedRealtimeMs, uptimeMs);
5763             } else if (Display.isOnState(oldState)) {
5764                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
5765                         elapsedRealtimeMs, uptimeMs);
5766                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
5767                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
5768             }
5769             // Update discharge amounts.
5770             if (mOnBatteryInternal) {
5771                 updateDischargeScreenLevelsLocked(oldState, state);
5772             }
5773         }
5774 
5775         // Changing display states might have changed the screen used to determine the overall
5776         // brightness.
5777         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
5778 
5779         if (shouldScheduleSync) {
5780             if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_SCREEN)) {
5781                 mScreenPowerStatsCollector.onScreenStateChange();
5782             } else {
5783                 final int numDisplays = mPerDisplayBatteryStats.length;
5784                 final int[] displayStates = new int[numDisplays];
5785                 for (int i = 0; i < numDisplays; i++) {
5786                     displayStates[i] = mPerDisplayBatteryStats[i].screenState;
5787                 }
5788                 mExternalSync.scheduleSyncDueToScreenStateChange(externalUpdateFlag,
5789                         batteryRunning, batteryScreenOffRunning, state, displayStates);
5790             }
5791         }
5792     }
5793 
5794     /**
5795      * Note screen brightness change for a display.
5796      */
5797     @GuardedBy("this")
noteScreenBrightnessLocked(int display, int brightness)5798     public void noteScreenBrightnessLocked(int display, int brightness) {
5799         noteScreenBrightnessLocked(display, brightness, mClock.elapsedRealtime(),
5800                 mClock.uptimeMillis());
5801     }
5802 
5803 
5804     /**
5805      * Note screen brightness change for a display.
5806      */
5807     @GuardedBy("this")
noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs, long uptimeMs)5808     public void noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs,
5809             long uptimeMs) {
5810         // Bin the brightness.
5811         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
5812         if (bin < 0) bin = 0;
5813         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
5814 
5815         final int overallBin;
5816 
5817         final int numDisplays = mPerDisplayBatteryStats.length;
5818         if (display < 0 || display >= numDisplays) {
5819             Slog.wtf(TAG, "Unexpected note screen brightness for display " + display + " (only "
5820                     + mPerDisplayBatteryStats.length + " displays exist...)");
5821             return;
5822         }
5823 
5824         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5825         final int oldBin = displayStats.screenBrightnessBin;
5826         if (oldBin == bin) {
5827             // Nothing changed
5828             overallBin = mScreenBrightnessBin;
5829         } else {
5830             displayStats.screenBrightnessBin = bin;
5831             if (displayStats.screenState == Display.STATE_ON) {
5832                 if (oldBin >= 0) {
5833                     displayStats.screenBrightnessTimers[oldBin].stopRunningLocked(
5834                             elapsedRealtimeMs);
5835                 }
5836                 displayStats.screenBrightnessTimers[bin].startRunningLocked(
5837                         elapsedRealtimeMs);
5838             }
5839             overallBin = evaluateOverallScreenBrightnessBinLocked();
5840         }
5841 
5842         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
5843     }
5844 
5845     @GuardedBy("this")
evaluateOverallScreenBrightnessBinLocked()5846     private int evaluateOverallScreenBrightnessBinLocked() {
5847         int overallBin = -1;
5848         final int numDisplays = getDisplayCount();
5849         for (int display = 0; display < numDisplays; display++) {
5850             final int displayBrightnessBin;
5851             if (mPerDisplayBatteryStats[display].screenState == Display.STATE_ON) {
5852                 displayBrightnessBin = mPerDisplayBatteryStats[display].screenBrightnessBin;
5853             } else {
5854                 displayBrightnessBin = -1;
5855             }
5856             if (displayBrightnessBin > overallBin) {
5857                 overallBin = displayBrightnessBin;
5858             }
5859         }
5860         return overallBin;
5861     }
5862 
5863     @GuardedBy("this")
maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs, long uptimeMs)5864     private void maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs,
5865             long uptimeMs) {
5866         if (mScreenBrightnessBin != overallBin) {
5867             if (overallBin >= 0) {
5868                 mHistory.recordScreenBrightnessEvent(elapsedRealtimeMs, uptimeMs, overallBin);
5869             }
5870             if (mScreenState == Display.STATE_ON) {
5871                 if (mScreenBrightnessBin >= 0) {
5872                     mScreenBrightnessTimer[mScreenBrightnessBin]
5873                             .stopRunningLocked(elapsedRealtimeMs);
5874                 }
5875                 if (overallBin >= 0) {
5876                     mScreenBrightnessTimer[overallBin]
5877                             .startRunningLocked(elapsedRealtimeMs);
5878                 }
5879             }
5880             mScreenBrightnessBin = overallBin;
5881         }
5882     }
5883 
5884     @GuardedBy("this")
noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event, long elapsedRealtimeMs, long uptimeMs)5885     public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event,
5886             long elapsedRealtimeMs, long uptimeMs) {
5887         if (mOnBatteryInternal) {
5888             uid = mapUid(uid);
5889             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event);
5890         }
5891     }
5892 
5893     @GuardedBy("this")
noteWakeUpLocked(String reason, int reasonUid, long elapsedRealtimeMs, long uptimeMs)5894     public void noteWakeUpLocked(String reason, int reasonUid,
5895             long elapsedRealtimeMs, long uptimeMs) {
5896         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, reason,
5897                 reasonUid);
5898     }
5899 
5900     @GuardedBy("this")
noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs)5901     public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) {
5902         if (mInteractive != interactive) {
5903             mInteractive = interactive;
5904             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
5905             if (interactive) {
5906                 mInteractiveTimer.startRunningLocked(elapsedRealtimeMs);
5907             } else {
5908                 mInteractiveTimer.stopRunningLocked(elapsedRealtimeMs);
5909             }
5910         }
5911     }
5912 
5913     @GuardedBy("this")
noteConnectivityChangedLocked(int type, String extra, long elapsedRealtimeMs, long uptimeMs)5914     public void noteConnectivityChangedLocked(int type, String extra,
5915             long elapsedRealtimeMs, long uptimeMs) {
5916         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
5917                 extra, type);
5918         mNumConnectivityChange++;
5919     }
5920 
5921     @GuardedBy("this")
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5922     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
5923             final long uptimeMillis, int uid) {
5924         uid = mapUid(uid);
5925         mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5926                 uid);
5927         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
5928     }
5929 
5930     /**
5931      * Updates the radio power state and returns true if an external stats collection should occur.
5932      */
5933     @GuardedBy("this")
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)5934     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
5935         return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
5936                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5937     }
5938 
5939     @GuardedBy("this")
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)5940     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid,
5941             long elapsedRealtimeMs, long uptimeMs) {
5942         if (mMobileRadioPowerState != powerState) {
5943             long realElapsedRealtimeMs;
5944             final boolean active = isActiveRadioPowerState(powerState);
5945             if (active) {
5946                 if (uid > 0) {
5947                     noteMobileRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
5948                 }
5949 
5950                 mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
5951                 mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5952                         HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
5953             } else {
5954                 realElapsedRealtimeMs = timestampNs / (1000*1000);
5955                 long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
5956                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
5957                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
5958                             + " is before start time " + lastUpdateTimeMs);
5959                     realElapsedRealtimeMs = elapsedRealtimeMs;
5960                 } else if (realElapsedRealtimeMs < elapsedRealtimeMs) {
5961                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
5962                             - realElapsedRealtimeMs);
5963                 }
5964                 mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5965                         HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
5966             }
5967             mMobileRadioPowerState = powerState;
5968 
5969             // Inform current RatBatteryStats that the modem active state might have changed.
5970             getRatBatteryStatsLocked(mActiveRat).noteActive(active, elapsedRealtimeMs);
5971 
5972             if (active) {
5973                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs);
5974                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs);
5975             } else {
5976                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
5977                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
5978 
5979                 if (mMobileRadioPowerStatsCollector.isEnabled()) {
5980                     mMobileRadioPowerStatsCollector.schedule();
5981                 } else {
5982                     // Check if modem Activity info has been collected recently, don't bother
5983                     // triggering another update.
5984                     if (mLastModemActivityInfo == null
5985                             || elapsedRealtimeMs >= mLastModemActivityInfo.getTimestampMillis()
5986                             + MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS) {
5987                         mExternalSync.scheduleSync("modem-data",
5988                                 BatteryExternalStatsWorker.UPDATE_RADIO);
5989                         return true;
5990                     }
5991                 }
5992             }
5993         }
5994         return false;
5995     }
5996 
isActiveRadioPowerState(int powerState)5997     private static boolean isActiveRadioPowerState(int powerState) {
5998         return powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5999                 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
6000     }
6001 
6002     /**
6003      * Toggles the power save mode state.
6004      */
6005     @GuardedBy("this")
notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs, long uptimeMs)6006     public void notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs,
6007             long uptimeMs) {
6008         if (mPowerSaveModeEnabled != enabled) {
6009             notePowerSaveModeLocked(enabled, elapsedRealtimeMs, uptimeMs);
6010         } else {
6011             // Log an initial value for BATTERY_SAVER_MODE_STATE_CHANGED in order to
6012             // allow the atom to read all future state changes.
6013             mFrameworkStatsLogger.batterySaverModeChanged(enabled);
6014         }
6015     }
6016 
6017     @GuardedBy("this")
notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs)6018     public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs) {
6019         if (mPowerSaveModeEnabled != enabled) {
6020             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
6021             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
6022             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
6023             mPowerSaveModeEnabled = enabled;
6024             if (enabled) {
6025                 mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6026                         HistoryItem.STATE2_POWER_SAVE_FLAG);
6027                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
6028             } else {
6029                 mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6030                         HistoryItem.STATE2_POWER_SAVE_FLAG);
6031                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
6032             }
6033             mFrameworkStatsLogger.batterySaverModeChanged(enabled);
6034         }
6035     }
6036 
6037     @GuardedBy("this")
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid, long elapsedRealtimeMs, long uptimeMs)6038     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid,
6039             long elapsedRealtimeMs, long uptimeMs) {
6040         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
6041         if (mDeviceIdling && !nowIdling && activeReason == null) {
6042             // We don't go out of general idling mode until explicitly taken out of
6043             // device idle through going active or significant motion.
6044             nowIdling = true;
6045         }
6046         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
6047         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
6048             // We don't go out of general light idling mode until explicitly taken out of
6049             // device idle through going active or significant motion.
6050             nowLightIdling = true;
6051         }
6052         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
6053             mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
6054                     activeReason, activeUid);
6055         }
6056         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
6057             int statsmode;
6058             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
6059             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
6060             else                     statsmode = DEVICE_IDLE_MODE_OFF;
6061             mFrameworkStatsLogger.deviceIdlingModeStateChanged(statsmode);
6062         }
6063         if (mDeviceIdling != nowIdling) {
6064             mDeviceIdling = nowIdling;
6065             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
6066             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
6067             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
6068             if (nowIdling) {
6069                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtimeMs);
6070             } else {
6071                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
6072             }
6073         }
6074         if (mDeviceLightIdling != nowLightIdling) {
6075             mDeviceLightIdling = nowLightIdling;
6076             if (nowLightIdling) {
6077                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtimeMs);
6078             } else {
6079                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
6080             }
6081         }
6082         if (mDeviceIdleMode != mode) {
6083             mHistory.recordDeviceIdleEvent(elapsedRealtimeMs, uptimeMs, mode);
6084             long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
6085             mLastIdleTimeStartMs = elapsedRealtimeMs;
6086             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
6087                 if (lastDuration > mLongestLightIdleTimeMs) {
6088                     mLongestLightIdleTimeMs = lastDuration;
6089                 }
6090                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtimeMs);
6091             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
6092                 if (lastDuration > mLongestFullIdleTimeMs) {
6093                     mLongestFullIdleTimeMs = lastDuration;
6094                 }
6095                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtimeMs);
6096             }
6097             if (mode == DEVICE_IDLE_MODE_LIGHT) {
6098                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtimeMs);
6099             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
6100                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtimeMs);
6101             }
6102             mDeviceIdleMode = mode;
6103             mFrameworkStatsLogger.deviceIdleModeStateChanged(mode);
6104         }
6105     }
6106 
6107     @GuardedBy("this")
notePackageInstalledLocked(String pkgName, long versionCode, long elapsedRealtimeMs, long uptimeMs)6108     public void notePackageInstalledLocked(String pkgName, long versionCode,
6109             long elapsedRealtimeMs, long uptimeMs) {
6110         // XXX need to figure out what to do with long version codes.
6111         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
6112                 pkgName, (int)versionCode);
6113         PackageChange pc = new PackageChange();
6114         pc.mPackageName = pkgName;
6115         pc.mUpdate = true;
6116         pc.mVersionCode = versionCode;
6117         addPackageChange(pc);
6118     }
6119 
6120     @GuardedBy("this")
notePackageUninstalledLocked(String pkgName, long elapsedRealtimeMs, long uptimeMs)6121     public void notePackageUninstalledLocked(String pkgName,
6122             long elapsedRealtimeMs, long uptimeMs) {
6123         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
6124                 pkgName, 0);
6125         PackageChange pc = new PackageChange();
6126         pc.mPackageName = pkgName;
6127         pc.mUpdate = true;
6128         addPackageChange(pc);
6129     }
6130 
addPackageChange(PackageChange pc)6131     private void addPackageChange(PackageChange pc) {
6132         if (mDailyPackageChanges == null) {
6133             mDailyPackageChanges = new ArrayList<>();
6134         }
6135         mDailyPackageChanges.add(pc);
6136     }
6137 
6138     @GuardedBy("this")
stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs)6139     void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
6140         for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
6141             if (i == except) {
6142                 continue;
6143             }
6144             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
6145                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtimeMs);
6146             }
6147         }
6148     }
6149 
6150     @GuardedBy("this")
notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs)6151     public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
6152         if (!mPhoneOn) {
6153             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6154                     HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
6155             mPhoneOn = true;
6156             mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
6157             if (mConstants.PHONE_ON_EXTERNAL_STATS_COLLECTION) {
6158                 scheduleSyncExternalStatsLocked("phone-on", ExternalStatsSync.UPDATE_RADIO);
6159                 mMobileRadioPowerStatsCollector.schedule();
6160             }
6161         }
6162     }
6163 
6164     @GuardedBy("this")
notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs)6165     public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
6166         if (mPhoneOn) {
6167             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6168                     HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
6169             mPhoneOn = false;
6170             mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
6171             scheduleSyncExternalStatsLocked("phone-off", ExternalStatsSync.UPDATE_RADIO);
6172             mMobileRadioPowerStatsCollector.schedule();
6173         }
6174     }
6175 
6176     @GuardedBy("this")
registerUsbStateReceiver(Context context)6177     private void registerUsbStateReceiver(Context context) {
6178         final IntentFilter usbStateFilter = new IntentFilter();
6179         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
6180         context.registerReceiver(new BroadcastReceiver() {
6181             @Override
6182             public void onReceive(Context context, Intent intent) {
6183                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
6184                 synchronized (BatteryStatsImpl.this) {
6185                     noteUsbConnectionStateLocked(state, mClock.elapsedRealtime(),
6186                             mClock.uptimeMillis());
6187                 }
6188             }
6189         }, usbStateFilter);
6190         synchronized (this) {
6191             if (mUsbDataState == USB_DATA_UNKNOWN) {
6192                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
6193                 final boolean initState = usbState != null && usbState.getBooleanExtra(
6194                         UsbManager.USB_CONNECTED, false);
6195                 noteUsbConnectionStateLocked(initState, mClock.elapsedRealtime(),
6196                         mClock.uptimeMillis());
6197             }
6198         }
6199     }
6200 
6201     @GuardedBy("this")
noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs, long uptimeMs)6202     private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs,
6203             long uptimeMs) {
6204         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
6205         if (mUsbDataState != newState) {
6206             mUsbDataState = newState;
6207             if (connected) {
6208                 mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6209                         HistoryItem.STATE2_USB_DATA_LINK_FLAG);
6210             } else {
6211                 mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6212                         HistoryItem.STATE2_USB_DATA_LINK_FLAG);
6213             }
6214         }
6215     }
6216 
6217     @GuardedBy("this")
stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)6218     void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
6219         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
6220             if (i == except) {
6221                 continue;
6222             }
6223             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
6224                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
6225             }
6226         }
6227     }
6228 
6229     @GuardedBy("this")
updateAllPhoneStateLocked(int state, int simState, int strengthBin, long elapsedRealtimeMs, long uptimeMs)6230     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin,
6231             long elapsedRealtimeMs, long uptimeMs) {
6232         boolean scanning = false;
6233         boolean newHistory = false;
6234         int addStateFlag = 0;
6235         int removeStateFlag = 0;
6236         int newState = -1;
6237         int newSignalStrength = -1;
6238 
6239         mPhoneServiceStateRaw = state;
6240         mPhoneSimStateRaw = simState;
6241         mPhoneSignalStrengthBinRaw = strengthBin;
6242 
6243         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
6244             // In this case we will always be STATE_OUT_OF_SERVICE, so need
6245             // to infer that we are scanning from other data.
6246             if (state == ServiceState.STATE_OUT_OF_SERVICE
6247                     && strengthBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
6248                 state = ServiceState.STATE_IN_SERVICE;
6249             }
6250         }
6251 
6252         // If the phone is powered off, stop all timers.
6253         if (state == ServiceState.STATE_POWER_OFF) {
6254             strengthBin = -1;
6255 
6256         // If we are in service, make sure the correct signal string timer is running.
6257         } else if (state == ServiceState.STATE_IN_SERVICE) {
6258             // Bin will be changed below.
6259 
6260         // If we're out of service, we are in the lowest signal strength
6261         // bin and have the scanning bit set.
6262         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
6263             scanning = true;
6264             strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
6265             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
6266                 addStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
6267                 newHistory = true;
6268                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs);
6269                 mFrameworkStatsLogger.phoneServiceStateChanged(state, simState, strengthBin);
6270             }
6271         }
6272 
6273         if (!scanning) {
6274             // If we are no longer scanning, then stop the scanning timer.
6275             if (mPhoneSignalScanningTimer.isRunningLocked()) {
6276                 removeStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
6277                 newHistory = true;
6278                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
6279                 mFrameworkStatsLogger.phoneServiceStateChanged(state, simState, strengthBin);
6280             }
6281         }
6282 
6283         if (mPhoneServiceState != state) {
6284             newState = state;
6285             newHistory = true;
6286             mPhoneServiceState = state;
6287         }
6288 
6289         if (mPhoneSignalStrengthBin != strengthBin) {
6290             if (mPhoneSignalStrengthBin >= 0) {
6291                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
6292                         elapsedRealtimeMs);
6293             }
6294             if (strengthBin >= 0) {
6295                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
6296                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
6297                 }
6298                 newSignalStrength = strengthBin;
6299                 newHistory = true;
6300                 mFrameworkStatsLogger.phoneSignalStrengthChanged(strengthBin);
6301             } else {
6302                 stopAllPhoneSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
6303             }
6304             mPhoneSignalStrengthBin = strengthBin;
6305         }
6306 
6307         if (newHistory) {
6308             mHistory.recordPhoneStateChangeEvent(elapsedRealtimeMs, uptimeMs,
6309                     addStateFlag, removeStateFlag, newState, newSignalStrength);
6310         }
6311     }
6312 
6313     @GuardedBy("this")
notePhoneStateLocked(int state, int simState, long elapsedRealtimeMs, long uptimeMs)6314     public void notePhoneStateLocked(int state, int simState,
6315             long elapsedRealtimeMs, long uptimeMs) {
6316         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw,
6317                 elapsedRealtimeMs, uptimeMs);
6318     }
6319 
6320     @GuardedBy("this")
notePhoneSignalStrengthLocked(SignalStrength signalStrength, long elapsedRealtimeMs, long uptimeMs)6321     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
6322             long elapsedRealtimeMs, long uptimeMs) {
6323         final int overallSignalStrength = signalStrength.getLevel();
6324         final SparseIntArray perRatSignalStrength = new SparseIntArray(
6325                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT);
6326 
6327         // Extract signal strength level for each RAT.
6328         final List<CellSignalStrength> cellSignalStrengths =
6329                 signalStrength.getCellSignalStrengths();
6330         final int size = cellSignalStrengths.size();
6331         for (int i = 0; i < size; i++) {
6332             CellSignalStrength cellSignalStrength = cellSignalStrengths.get(i);
6333             // Map each CellSignalStrength to a BatteryStats.RadioAccessTechnology
6334             final int ratType;
6335             final int level;
6336             if (cellSignalStrength instanceof CellSignalStrengthNr) {
6337                 ratType = RADIO_ACCESS_TECHNOLOGY_NR;
6338                 level = cellSignalStrength.getLevel();
6339             } else if (cellSignalStrength instanceof CellSignalStrengthLte) {
6340                 ratType = RADIO_ACCESS_TECHNOLOGY_LTE;
6341                 level = cellSignalStrength.getLevel();
6342             } else {
6343                 ratType = RADIO_ACCESS_TECHNOLOGY_OTHER;
6344                 level = cellSignalStrength.getLevel();
6345             }
6346 
6347             // According to SignalStrength#getCellSignalStrengths(), multiple of the same
6348             // cellSignalStrength can be present. Just take the highest level one for each RAT.
6349             if (perRatSignalStrength.get(ratType, -1) < level) {
6350                 perRatSignalStrength.put(ratType, level);
6351             }
6352         }
6353 
6354         notePhoneSignalStrengthLocked(overallSignalStrength, perRatSignalStrength,
6355                 elapsedRealtimeMs, uptimeMs);
6356     }
6357 
6358     /**
6359      * Note phone signal strength change, including per RAT signal strength.
6360      *
6361      * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
6362      * @param perRatSignalStrength signal strength of available RATs
6363      */
6364     @GuardedBy("this")
notePhoneSignalStrengthLocked(int signalStrength, SparseIntArray perRatSignalStrength)6365     public void notePhoneSignalStrengthLocked(int signalStrength,
6366             SparseIntArray perRatSignalStrength) {
6367         notePhoneSignalStrengthLocked(signalStrength, perRatSignalStrength,
6368                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6369     }
6370 
6371     /**
6372      * Note phone signal strength change, including per RAT signal strength.
6373      *
6374      * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
6375      * @param perRatSignalStrength signal strength of available RATs
6376      */
6377     @GuardedBy("this")
notePhoneSignalStrengthLocked(int signalStrength, SparseIntArray perRatSignalStrength, long elapsedRealtimeMs, long uptimeMs)6378     public void notePhoneSignalStrengthLocked(int signalStrength,
6379             SparseIntArray perRatSignalStrength,
6380             long elapsedRealtimeMs, long uptimeMs) {
6381         // Note each RAT's signal strength.
6382         final int size = perRatSignalStrength.size();
6383         for (int i = 0; i < size; i++) {
6384             final int rat = perRatSignalStrength.keyAt(i);
6385             final int ratSignalStrength = perRatSignalStrength.valueAt(i);
6386             getRatBatteryStatsLocked(rat).noteSignalStrength(ratSignalStrength, elapsedRealtimeMs);
6387         }
6388         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, signalStrength,
6389                 elapsedRealtimeMs, uptimeMs);
6390     }
6391 
6392     @GuardedBy("this")
notePhoneDataConnectionStateLocked(@etworkType int dataType, boolean hasData, @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState, @ServiceState.FrequencyRange int nrFrequency)6393     public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
6394             @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState,
6395             @ServiceState.FrequencyRange int nrFrequency) {
6396         notePhoneDataConnectionStateLocked(dataType, hasData, serviceType, nrState, nrFrequency,
6397                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6398     }
6399 
6400     @GuardedBy("this")
notePhoneDataConnectionStateLocked(@etworkType int dataType, boolean hasData, @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState, @ServiceState.FrequencyRange int nrFrequency, long elapsedRealtimeMs, long uptimeMs)6401     public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
6402             @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState,
6403             @ServiceState.FrequencyRange int nrFrequency, long elapsedRealtimeMs, long uptimeMs) {
6404         // BatteryStats uses 0 to represent no network type.
6405         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
6406         // Unknown is included in DATA_CONNECTION_OTHER.
6407         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
6408         if (hasData) {
6409             if (dataType > 0 && dataType <= NUM_ALL_NETWORK_TYPES) {
6410                 bin = dataType;
6411             } else {
6412                 switch (serviceType) {
6413                     case ServiceState.STATE_OUT_OF_SERVICE:
6414                         bin = DATA_CONNECTION_OUT_OF_SERVICE;
6415                         break;
6416                     case ServiceState.STATE_EMERGENCY_ONLY:
6417                         bin = DATA_CONNECTION_EMERGENCY_SERVICE;
6418                         break;
6419                     default:
6420                         bin = DATA_CONNECTION_OTHER;
6421                         break;
6422                 }
6423             }
6424         }
6425 
6426 
6427 
6428         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
6429         if (mPhoneDataConnectionType != bin) {
6430             mHistory.recordDataConnectionTypeChangeEvent(elapsedRealtimeMs, uptimeMs, bin);
6431             if (mPhoneDataConnectionType >= 0) {
6432                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
6433                         elapsedRealtimeMs);
6434             }
6435             mPhoneDataConnectionType = bin;
6436             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs);
6437         }
6438 
6439         if (mNrState != nrState) {
6440             mHistory.recordNrStateChangeEvent(elapsedRealtimeMs, uptimeMs, nrState);
6441             mNrState = nrState;
6442         }
6443 
6444         final boolean newNrNsaActive = isNrNsa(bin, nrState);
6445         final boolean nrNsaActive = mNrNsaTimer.isRunningLocked();
6446         if (newNrNsaActive != nrNsaActive) {
6447             if (newNrNsaActive) {
6448                 mNrNsaTimer.startRunningLocked(elapsedRealtimeMs);
6449             } else {
6450                 mNrNsaTimer.stopRunningLocked(elapsedRealtimeMs);
6451             }
6452         }
6453 
6454         final int newRat = mapNetworkTypeToRadioAccessTechnology(bin, nrState);
6455         if (newRat == RADIO_ACCESS_TECHNOLOGY_NR) {
6456             // Note possible frequency change for the NR RAT.
6457             getRatBatteryStatsLocked(newRat).noteFrequencyRange(nrFrequency, elapsedRealtimeMs);
6458         }
6459         if (mActiveRat != newRat) {
6460             getRatBatteryStatsLocked(mActiveRat).noteActive(false, elapsedRealtimeMs);
6461             mActiveRat = newRat;
6462         }
6463         final boolean modemActive = mMobileRadioActiveTimer.isRunningLocked();
6464         getRatBatteryStatsLocked(newRat).noteActive(modemActive, elapsedRealtimeMs);
6465     }
6466 
6467     /**
6468      * Non-standalone (NSA) mode for 5G NR will have an LTE network type. If NR state is
6469      * connected while on an LTE network, the device is in NR NSA mode.
6470      */
isNrNsa(@etworkType int dataType, @NetworkRegistrationInfo.NRState int nrState)6471     private static boolean isNrNsa(@NetworkType int dataType,
6472             @NetworkRegistrationInfo.NRState int nrState) {
6473         return dataType == TelephonyManager.NETWORK_TYPE_LTE
6474                 && nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED;
6475     }
6476 
6477     @RadioAccessTechnology
mapNetworkTypeToRadioAccessTechnology(@etworkType int dataType, @NetworkRegistrationInfo.NRState int nrState)6478     private static int mapNetworkTypeToRadioAccessTechnology(@NetworkType int dataType,
6479             @NetworkRegistrationInfo.NRState int nrState) {
6480         if (isNrNsa(dataType, nrState)) {
6481             // Treat an NR NSA connection as RADIO_ACCESS_TECHNOLOGY_NR
6482             return RADIO_ACCESS_TECHNOLOGY_NR;
6483         }
6484 
6485         switch (dataType) {
6486             case TelephonyManager.NETWORK_TYPE_NR:
6487                 return RADIO_ACCESS_TECHNOLOGY_NR;
6488             case TelephonyManager.NETWORK_TYPE_LTE:
6489                 return RADIO_ACCESS_TECHNOLOGY_LTE;
6490             case TelephonyManager.NETWORK_TYPE_UNKNOWN: //fallthrough
6491             case TelephonyManager.NETWORK_TYPE_GPRS: //fallthrough
6492             case TelephonyManager.NETWORK_TYPE_EDGE: //fallthrough
6493             case TelephonyManager.NETWORK_TYPE_UMTS: //fallthrough
6494             case TelephonyManager.NETWORK_TYPE_CDMA: //fallthrough
6495             case TelephonyManager.NETWORK_TYPE_EVDO_0: //fallthrough
6496             case TelephonyManager.NETWORK_TYPE_EVDO_A: //fallthrough
6497             case TelephonyManager.NETWORK_TYPE_1xRTT: //fallthrough
6498             case TelephonyManager.NETWORK_TYPE_HSDPA: //fallthrough
6499             case TelephonyManager.NETWORK_TYPE_HSUPA: //fallthrough
6500             case TelephonyManager.NETWORK_TYPE_HSPA: //fallthrough
6501             case TelephonyManager.NETWORK_TYPE_IDEN: //fallthrough
6502             case TelephonyManager.NETWORK_TYPE_EVDO_B: //fallthrough
6503             case TelephonyManager.NETWORK_TYPE_EHRPD: //fallthrough
6504             case TelephonyManager.NETWORK_TYPE_HSPAP: //fallthrough
6505             case TelephonyManager.NETWORK_TYPE_GSM: //fallthrough
6506             case TelephonyManager.NETWORK_TYPE_TD_SCDMA: //fallthrough
6507             case TelephonyManager.NETWORK_TYPE_IWLAN: //fallthrough
6508                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6509             default:
6510                 Slog.w(TAG, "Unhandled NetworkType (" + dataType + "), mapping to OTHER");
6511                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6512         }
6513     }
6514 
6515     @GuardedBy("this")
noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs)6516     public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
6517         if (!mWifiOn) {
6518             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6519                     HistoryItem.STATE2_WIFI_ON_FLAG);
6520             mWifiOn = true;
6521             mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
6522             if (mWifiPowerStatsCollector.isEnabled()) {
6523                 mWifiPowerStatsCollector.schedule();
6524             } else {
6525                 scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
6526             }
6527         }
6528     }
6529 
6530     @GuardedBy("this")
noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs)6531     public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
6532         if (mWifiOn) {
6533             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6534                     HistoryItem.STATE2_WIFI_ON_FLAG);
6535             mWifiOn = false;
6536             mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
6537             if (mWifiPowerStatsCollector.isEnabled()) {
6538                 mWifiPowerStatsCollector.schedule();
6539             } else {
6540                 scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
6541             }
6542         }
6543     }
6544 
6545     @GuardedBy("this")
noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6546     public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6547         uid = mapUid(uid);
6548         if (mAudioOnNesting == 0) {
6549             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6550                     HistoryItem.STATE_AUDIO_ON_FLAG, uid, "audio");
6551             mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
6552         }
6553         mAudioOnNesting++;
6554         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_AUDIO)) {
6555             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6556                     .noteAudioTurnedOnLocked(elapsedRealtimeMs);
6557         }
6558     }
6559 
6560     @GuardedBy("this")
noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6561     public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6562         if (mAudioOnNesting == 0) {
6563             return;
6564         }
6565         uid = mapUid(uid);
6566         if (--mAudioOnNesting == 0) {
6567             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6568                     HistoryItem.STATE_AUDIO_ON_FLAG, uid, "audio");
6569             mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
6570         }
6571         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_AUDIO)) {
6572             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6573                     .noteAudioTurnedOffLocked(elapsedRealtimeMs);
6574         }
6575     }
6576 
6577     @GuardedBy("this")
noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6578     public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6579         uid = mapUid(uid);
6580         if (mVideoOnNesting == 0) {
6581             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6582                     HistoryItem.STATE2_VIDEO_ON_FLAG, uid, "video");
6583             mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
6584         }
6585         mVideoOnNesting++;
6586         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_VIDEO)) {
6587             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6588                     .noteVideoTurnedOnLocked(elapsedRealtimeMs);
6589         }
6590     }
6591 
6592     @GuardedBy("this")
noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6593     public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6594         if (mVideoOnNesting == 0) {
6595             return;
6596         }
6597         uid = mapUid(uid);
6598         if (--mVideoOnNesting == 0) {
6599             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6600                     HistoryItem.STATE2_VIDEO_ON_FLAG, uid, "video");
6601             mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
6602         }
6603         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_VIDEO)) {
6604             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6605                     .noteVideoTurnedOffLocked(elapsedRealtimeMs);
6606         }
6607     }
6608 
6609     @GuardedBy("this")
noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs)6610     public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
6611         if (mAudioOnNesting > 0) {
6612             mAudioOnNesting = 0;
6613             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6614                     HistoryItem.STATE_AUDIO_ON_FLAG);
6615             mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6616             for (int i=0; i<mUidStats.size(); i++) {
6617                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6618                 uid.noteResetAudioLocked(elapsedRealtimeMs);
6619             }
6620         }
6621     }
6622 
6623     @GuardedBy("this")
noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs)6624     public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
6625         if (mVideoOnNesting > 0) {
6626             mVideoOnNesting = 0;
6627             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6628                     HistoryItem.STATE2_VIDEO_ON_FLAG);
6629             mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6630             for (int i=0; i<mUidStats.size(); i++) {
6631                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6632                 uid.noteResetVideoLocked(elapsedRealtimeMs);
6633             }
6634         }
6635     }
6636 
6637     @GuardedBy("this")
noteActivityResumedLocked(int uid)6638     public void noteActivityResumedLocked(int uid) {
6639         noteActivityResumedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6640     }
6641 
6642     @GuardedBy("this")
noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6643     public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6644         uid = mapUid(uid);
6645         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6646                 .noteActivityResumedLocked(elapsedRealtimeMs);
6647     }
6648 
6649     @GuardedBy("this")
noteActivityPausedLocked(int uid)6650     public void noteActivityPausedLocked(int uid) {
6651         noteActivityPausedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6652     }
6653 
6654     @GuardedBy("this")
noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6655     public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6656         uid = mapUid(uid);
6657         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6658                 .noteActivityPausedLocked(elapsedRealtimeMs);
6659     }
6660 
6661     @GuardedBy("this")
noteVibratorOnLocked(int uid, long durationMillis, long elapsedRealtimeMs, long uptimeMs)6662     public void noteVibratorOnLocked(int uid, long durationMillis,
6663             long elapsedRealtimeMs, long uptimeMs) {
6664         uid = mapUid(uid);
6665         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6666                 .noteVibratorOnLocked(durationMillis, elapsedRealtimeMs);
6667     }
6668 
6669     @GuardedBy("this")
noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6670     public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6671         uid = mapUid(uid);
6672         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6673                 .noteVibratorOffLocked(elapsedRealtimeMs);
6674     }
6675 
6676     @GuardedBy("this")
noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6677     public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6678         uid = mapUid(uid);
6679         if (mFlashlightOnNesting++ == 0) {
6680             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6681                     HistoryItem.STATE2_FLASHLIGHT_FLAG, uid, "flashlight");
6682             mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
6683         }
6684         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)) {
6685             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6686                     .noteFlashlightTurnedOnLocked(elapsedRealtimeMs);
6687         }
6688     }
6689 
6690     @GuardedBy("this")
noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6691     public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6692         if (mFlashlightOnNesting == 0) {
6693             return;
6694         }
6695         uid = mapUid(uid);
6696         if (--mFlashlightOnNesting == 0) {
6697             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6698                     HistoryItem.STATE2_FLASHLIGHT_FLAG, uid, "flashlight");
6699             mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
6700         }
6701         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)) {
6702             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6703                     .noteFlashlightTurnedOffLocked(elapsedRealtimeMs);
6704         }
6705     }
6706 
6707     @GuardedBy("this")
noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6708     public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6709         uid = mapUid(uid);
6710         if (mCameraOnNesting++ == 0) {
6711             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6712                     HistoryItem.STATE2_CAMERA_FLAG, uid, "camera");
6713             mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
6714         }
6715         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6716                 .noteCameraTurnedOnLocked(elapsedRealtimeMs);
6717 
6718         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CAMERA)) {
6719             mCameraPowerStatsCollector.schedule();
6720         } else {
6721             scheduleSyncExternalStatsLocked("camera-on", ExternalStatsSync.UPDATE_CAMERA);
6722         }
6723     }
6724 
6725     @GuardedBy("this")
noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6726     public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6727         if (mCameraOnNesting == 0) {
6728             return;
6729         }
6730         uid = mapUid(uid);
6731         if (--mCameraOnNesting == 0) {
6732             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6733                     HistoryItem.STATE2_CAMERA_FLAG, uid, "camera");
6734             mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
6735         }
6736         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6737                 .noteCameraTurnedOffLocked(elapsedRealtimeMs);
6738 
6739         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CAMERA)) {
6740             mCameraPowerStatsCollector.schedule();
6741         } else {
6742             scheduleSyncExternalStatsLocked("camera-off", ExternalStatsSync.UPDATE_CAMERA);
6743         }
6744     }
6745 
6746     @GuardedBy("this")
noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs)6747     public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
6748         if (mCameraOnNesting > 0) {
6749             mCameraOnNesting = 0;
6750             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6751                     HistoryItem.STATE2_CAMERA_FLAG);
6752             mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6753             for (int i=0; i<mUidStats.size(); i++) {
6754                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6755                 uid.noteResetCameraLocked(elapsedRealtimeMs);
6756             }
6757         }
6758 
6759         scheduleSyncExternalStatsLocked("camera-reset", ExternalStatsSync.UPDATE_CAMERA);
6760     }
6761 
6762     @GuardedBy("this")
noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs)6763     public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
6764         if (mFlashlightOnNesting > 0) {
6765             mFlashlightOnNesting = 0;
6766             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6767                     HistoryItem.STATE2_FLASHLIGHT_FLAG);
6768             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6769             for (int i=0; i<mUidStats.size(); i++) {
6770                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6771                 uid.noteResetFlashlightLocked(elapsedRealtimeMs);
6772             }
6773         }
6774     }
6775 
6776     @GuardedBy("this")
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6777     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
6778             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
6779         if (workChain != null) {
6780             uid = workChain.getAttributionUid();
6781         }
6782         uid = mapUid(uid);
6783         if (mBluetoothScanNesting == 0) {
6784             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6785                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6786             mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
6787         }
6788         mBluetoothScanNesting++;
6789         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6790                 .noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized);
6791     }
6792 
6793     @GuardedBy("this")
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)6794     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
6795         noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
6796                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6797     }
6798 
6799     @GuardedBy("this")
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6800     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
6801             long elapsedRealtimeMs, long uptimeMs) {
6802         final int N = ws.size();
6803         for (int i = 0; i < N; i++) {
6804             noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized,
6805                     elapsedRealtimeMs, uptimeMs);
6806         }
6807 
6808         final List<WorkChain> workChains = ws.getWorkChains();
6809         if (workChains != null) {
6810             for (int i = 0; i < workChains.size(); ++i) {
6811                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized,
6812                         elapsedRealtimeMs, uptimeMs);
6813             }
6814         }
6815     }
6816 
6817     @GuardedBy("this")
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6818     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
6819             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
6820         if (workChain != null) {
6821             uid = workChain.getAttributionUid();
6822         }
6823         uid = mapUid(uid);
6824         mBluetoothScanNesting--;
6825         if (mBluetoothScanNesting == 0) {
6826             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6827                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6828             mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
6829         }
6830         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6831                 .noteBluetoothScanStoppedLocked(elapsedRealtimeMs, isUnoptimized);
6832     }
6833 
6834     @GuardedBy("this")
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)6835     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
6836         noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
6837                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6838     }
6839 
6840     @GuardedBy("this")
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6841     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
6842             long elapsedRealtimeMs, long uptimeMs) {
6843         final int N = ws.size();
6844         for (int i = 0; i < N; i++) {
6845             noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized,
6846                     elapsedRealtimeMs, uptimeMs);
6847         }
6848 
6849         final List<WorkChain> workChains = ws.getWorkChains();
6850         if (workChains != null) {
6851             for (int i = 0; i < workChains.size(); ++i) {
6852                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized,
6853                         elapsedRealtimeMs, uptimeMs);
6854             }
6855         }
6856     }
6857 
6858     @GuardedBy("this")
noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs)6859     public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
6860         if (mBluetoothScanNesting > 0) {
6861             mBluetoothScanNesting = 0;
6862             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6863                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6864             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
6865             for (int i=0; i<mUidStats.size(); i++) {
6866                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6867                 uid.noteResetBluetoothScanLocked(elapsedRealtimeMs);
6868             }
6869         }
6870     }
6871 
6872     @GuardedBy("this")
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)6873     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
6874         noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
6875                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6876     }
6877 
6878     @GuardedBy("this")
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults, long elapsedRealtimeMs, long uptimeMs)6879     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults,
6880             long elapsedRealtimeMs, long uptimeMs) {
6881         final int N = ws.size();
6882         for (int i = 0; i < N; i++) {
6883             int uid = mapUid(ws.getUid(i));
6884             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6885                     .noteBluetoothScanResultsLocked(numNewResults);
6886         }
6887 
6888         final List<WorkChain> workChains = ws.getWorkChains();
6889         if (workChains != null) {
6890             for (int i = 0; i < workChains.size(); ++i) {
6891                 final WorkChain wc = workChains.get(i);
6892                 int uid = mapUid(wc.getAttributionUid());
6893                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6894                         .noteBluetoothScanResultsLocked(numNewResults);
6895             }
6896         }
6897     }
6898 
retrieveBluetoothScanTimesLocked( BluetoothPowerStatsCollector.BluetoothStatsRetriever.Callback callback)6899     private void retrieveBluetoothScanTimesLocked(
6900             BluetoothPowerStatsCollector.BluetoothStatsRetriever.Callback callback) {
6901         long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
6902         for (int i = mUidStats.size() - 1; i >= 0; i--) {
6903             Uid uidStats = mUidStats.valueAt(i);
6904             if (uidStats.mBluetoothScanTimer == null) {
6905                 continue;
6906             }
6907 
6908             long scanTimeUs = mBluetoothScanTimer.getTotalTimeLocked(elapsedTimeUs,
6909                     STATS_SINCE_CHARGED);
6910             if (scanTimeUs != 0) {
6911                 int uid = mUidStats.keyAt(i);
6912                 callback.onBluetoothScanTime(uid, (scanTimeUs + 500) / 1000);
6913             }
6914         }
6915     }
6916 
6917     @GuardedBy("this")
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)6918     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
6919             final long uptimeMillis, int uid) {
6920         uid = mapUid(uid);
6921         mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
6922                 uid);
6923         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
6924     }
6925 
6926     @GuardedBy("this")
noteWifiRadioPowerState(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)6927     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid,
6928             long elapsedRealtimeMs, long uptimeMs) {
6929         if (mWifiRadioPowerState != powerState) {
6930             final boolean active =
6931                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
6932                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
6933             if (active) {
6934                 if (uid > 0) {
6935                     noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
6936                 }
6937                 mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6938                         HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
6939                 mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
6940             } else {
6941                 mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6942                         HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
6943                 mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000));
6944             }
6945             mWifiRadioPowerState = powerState;
6946         }
6947     }
6948 
6949     @GuardedBy("this")
noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6950     public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6951         if (!mGlobalWifiRunning) {
6952             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6953                     HistoryItem.STATE2_WIFI_RUNNING_FLAG);
6954             mGlobalWifiRunning = true;
6955             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
6956             int N = ws.size();
6957             for (int i=0; i<N; i++) {
6958                 int uid = mapUid(ws.getUid(i));
6959                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6960                         .noteWifiRunningLocked(elapsedRealtimeMs);
6961             }
6962 
6963             List<WorkChain> workChains = ws.getWorkChains();
6964             if (workChains != null) {
6965                 for (int i = 0; i < workChains.size(); ++i) {
6966                     int uid = mapUid(workChains.get(i).getAttributionUid());
6967                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6968                             .noteWifiRunningLocked(elapsedRealtimeMs);
6969                 }
6970             }
6971             if (mWifiPowerStatsCollector.isEnabled()) {
6972                 mWifiPowerStatsCollector.schedule();
6973             } else {
6974                 scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
6975             }
6976         } else {
6977             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
6978         }
6979     }
6980 
6981     @GuardedBy("this")
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)6982     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs,
6983             long elapsedRealtimeMs, long uptimeMs) {
6984         if (mGlobalWifiRunning) {
6985             int N = oldWs.size();
6986             for (int i=0; i<N; i++) {
6987                 int uid = mapUid(oldWs.getUid(i));
6988                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6989                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6990             }
6991 
6992             List<WorkChain> workChains = oldWs.getWorkChains();
6993             if (workChains != null) {
6994                 for (int i = 0; i < workChains.size(); ++i) {
6995                     int uid = mapUid(workChains.get(i).getAttributionUid());
6996                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6997                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6998                 }
6999             }
7000 
7001             N = newWs.size();
7002             for (int i=0; i<N; i++) {
7003                 int uid = mapUid(newWs.getUid(i));
7004                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7005                         .noteWifiRunningLocked(elapsedRealtimeMs);
7006             }
7007 
7008             workChains = newWs.getWorkChains();
7009             if (workChains != null) {
7010                 for (int i = 0; i < workChains.size(); ++i) {
7011                     int uid = mapUid(workChains.get(i).getAttributionUid());
7012                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7013                             .noteWifiRunningLocked(elapsedRealtimeMs);
7014                 }
7015             }
7016         } else {
7017             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
7018         }
7019     }
7020 
7021     @GuardedBy("this")
noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7022     public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
7023         if (mGlobalWifiRunning) {
7024             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
7025                     HistoryItem.STATE2_WIFI_RUNNING_FLAG);
7026             mGlobalWifiRunning = false;
7027             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
7028             int N = ws.size();
7029             for (int i=0; i<N; i++) {
7030                 int uid = mapUid(ws.getUid(i));
7031                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7032                         .noteWifiStoppedLocked(elapsedRealtimeMs);
7033             }
7034 
7035             List<WorkChain> workChains = ws.getWorkChains();
7036             if (workChains != null) {
7037                 for (int i = 0; i < workChains.size(); ++i) {
7038                     int uid = mapUid(workChains.get(i).getAttributionUid());
7039                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7040                             .noteWifiStoppedLocked(elapsedRealtimeMs);
7041                 }
7042             }
7043 
7044             if (mWifiPowerStatsCollector.isEnabled()) {
7045                 mWifiPowerStatsCollector.schedule();
7046             } else {
7047                 scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
7048             }
7049         } else {
7050             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
7051         }
7052     }
7053 
7054     @GuardedBy("this")
noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs)7055     public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) {
7056         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
7057         if (mWifiState != wifiState) {
7058             if (mWifiState >= 0) {
7059                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtimeMs);
7060             }
7061             mWifiState = wifiState;
7062             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs);
7063             if (mWifiPowerStatsCollector.isEnabled()) {
7064                 mWifiPowerStatsCollector.schedule();
7065             } else {
7066                 scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
7067             }
7068         }
7069     }
7070 
7071     @GuardedBy("this")
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth, long elapsedRealtimeMs, long uptimeMs)7072     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth,
7073             long elapsedRealtimeMs, long uptimeMs) {
7074         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
7075         if (mWifiSupplState != supplState) {
7076             if (mWifiSupplState >= 0) {
7077                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtimeMs);
7078             }
7079             mWifiSupplState = supplState;
7080             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
7081             mHistory.recordWifiSupplicantStateChangeEvent(elapsedRealtimeMs, uptimeMs, supplState);
7082         }
7083     }
7084 
7085     @GuardedBy("this")
stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)7086     void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
7087         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7088             if (i == except) {
7089                 continue;
7090             }
7091             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
7092                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
7093             }
7094         }
7095     }
7096 
7097     @GuardedBy("this")
noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs)7098     public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) {
7099         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
7100         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
7101         if (mWifiSignalStrengthBin != strengthBin) {
7102             if (mWifiSignalStrengthBin >= 0) {
7103                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
7104                         elapsedRealtimeMs);
7105             }
7106             if (strengthBin >= 0) {
7107                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
7108                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
7109                 }
7110                 mHistory.recordWifiSignalStrengthChangeEvent(elapsedRealtimeMs, uptimeMs,
7111                         strengthBin);
7112             } else {
7113                 stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
7114             }
7115             mWifiSignalStrengthBin = strengthBin;
7116         }
7117     }
7118 
7119     private int mWifiFullLockNesting = 0;
7120 
7121     @GuardedBy("this")
noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7122     public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7123         if (mWifiFullLockNesting == 0) {
7124             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
7125                     HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
7126         }
7127         mWifiFullLockNesting++;
7128         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7129                 .noteFullWifiLockAcquiredLocked(elapsedRealtimeMs);
7130     }
7131 
7132     @GuardedBy("this")
noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7133     public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7134         mWifiFullLockNesting--;
7135         if (mWifiFullLockNesting == 0) {
7136             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
7137                     HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
7138         }
7139         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7140                 .noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
7141     }
7142 
7143     int mWifiScanNesting = 0;
7144 
7145     @GuardedBy("this")
noteWifiScanStartedLocked(int uid)7146     public void noteWifiScanStartedLocked(int uid) {
7147         noteWifiScanStartedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7148     }
7149 
7150     @GuardedBy("this")
noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7151     public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7152         if (mWifiScanNesting == 0) {
7153             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
7154                     HistoryItem.STATE_WIFI_SCAN_FLAG);
7155         }
7156         mWifiScanNesting++;
7157         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7158                 .noteWifiScanStartedLocked(elapsedRealtimeMs);
7159     }
7160 
7161     @GuardedBy("this")
noteWifiScanStoppedLocked(int uid)7162     public void noteWifiScanStoppedLocked(int uid) {
7163         noteWifiScanStoppedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7164     }
7165 
7166     @GuardedBy("this")
noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7167     public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7168         mWifiScanNesting--;
7169         if (mWifiScanNesting == 0) {
7170             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
7171                     HistoryItem.STATE_WIFI_SCAN_FLAG);
7172         }
7173         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7174                 .noteWifiScanStoppedLocked(elapsedRealtimeMs);
7175     }
7176 
noteWifiBatchedScanStartedLocked(int uid, int csph, long elapsedRealtimeMs, long uptimeMs)7177     public void noteWifiBatchedScanStartedLocked(int uid, int csph,
7178             long elapsedRealtimeMs, long uptimeMs) {
7179         uid = mapUid(uid);
7180         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7181                 .noteWifiBatchedScanStartedLocked(csph, elapsedRealtimeMs);
7182     }
7183 
noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7184     public void noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7185         uid = mapUid(uid);
7186         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7187                 .noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs);
7188     }
7189 
retrieveWifiScanTimesLocked( WifiPowerStatsCollector.WifiStatsRetriever.Callback callback)7190     private void retrieveWifiScanTimesLocked(
7191             WifiPowerStatsCollector.WifiStatsRetriever.Callback callback) {
7192         long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
7193         for (int i = mUidStats.size() - 1; i >= 0; i--) {
7194             int uid = mUidStats.keyAt(i);
7195             Uid uidStats = mUidStats.valueAt(i);
7196             long scanTimeUs = uidStats.getWifiScanTime(elapsedTimeUs, STATS_SINCE_CHARGED);
7197             long batchScanTimeUs = 0;
7198             for (int bucket = 0; bucket < NUM_WIFI_BATCHED_SCAN_BINS; bucket++) {
7199                 batchScanTimeUs += uidStats.getWifiBatchedScanTime(bucket, elapsedTimeUs,
7200                         STATS_SINCE_CHARGED);
7201             }
7202             if (scanTimeUs != 0 || batchScanTimeUs != 0) {
7203                 callback.onWifiScanTime(uid, (scanTimeUs + 500) / 1000,
7204                         (batchScanTimeUs + 500) / 1000);
7205             }
7206         }
7207     }
7208 
7209     private int mWifiMulticastNesting = 0;
7210 
7211     @GuardedBy("this")
noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7212     public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7213         uid = mapUid(uid);
7214         if (mWifiMulticastNesting == 0) {
7215             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
7216                     HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
7217             // Start Wifi Multicast overall timer
7218             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
7219                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
7220             }
7221         }
7222         mWifiMulticastNesting++;
7223         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7224                 .noteWifiMulticastEnabledLocked(elapsedRealtimeMs);
7225     }
7226 
7227     @GuardedBy("this")
noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7228     public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7229         uid = mapUid(uid);
7230         mWifiMulticastNesting--;
7231         if (mWifiMulticastNesting == 0) {
7232             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
7233                     HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
7234 
7235             // Stop Wifi Multicast overall timer
7236             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
7237                 if (DEBUG) Slog.v(TAG, "Multicast Overall Timer Stopped");
7238                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
7239             }
7240         }
7241         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7242                 .noteWifiMulticastDisabledLocked(elapsedRealtimeMs);
7243     }
7244 
7245     @GuardedBy("this")
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7246     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws,
7247             long elapsedRealtimeMs, long uptimeMs) {
7248         int N = ws.size();
7249         for (int i=0; i<N; i++) {
7250             final int uid = mapUid(ws.getUid(i));
7251             noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
7252         }
7253 
7254         final List<WorkChain> workChains = ws.getWorkChains();
7255         if (workChains != null) {
7256             for (int i = 0; i < workChains.size(); ++i) {
7257                 final WorkChain workChain = workChains.get(i);
7258                 final int uid = mapUid(workChain.getAttributionUid());
7259                 noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
7260             }
7261         }
7262     }
7263 
7264     @GuardedBy("this")
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7265     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws,
7266             long elapsedRealtimeMs, long uptimeMs) {
7267         int N = ws.size();
7268         for (int i=0; i<N; i++) {
7269             final int uid = mapUid(ws.getUid(i));
7270             noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
7271         }
7272 
7273         final List<WorkChain> workChains = ws.getWorkChains();
7274         if (workChains != null) {
7275             for (int i = 0; i < workChains.size(); ++i) {
7276                 final WorkChain workChain = workChains.get(i);
7277                 final int uid = mapUid(workChain.getAttributionUid());
7278                 noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
7279             }
7280         }
7281     }
7282 
7283     @GuardedBy("this")
noteWifiScanStartedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7284     public void noteWifiScanStartedFromSourceLocked(WorkSource ws,
7285             long elapsedRealtimeMs, long uptimeMs) {
7286         int N = ws.size();
7287         for (int i=0; i<N; i++) {
7288             final int uid = mapUid(ws.getUid(i));
7289             noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
7290         }
7291 
7292         final List<WorkChain> workChains = ws.getWorkChains();
7293         if (workChains != null) {
7294             for (int i = 0; i < workChains.size(); ++i) {
7295                 final WorkChain workChain = workChains.get(i);
7296                 final int uid = mapUid(workChain.getAttributionUid());
7297                 noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
7298             }
7299         }
7300     }
7301 
7302     @GuardedBy("this")
noteWifiScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7303     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws,
7304             long elapsedRealtimeMs, long uptimeMs) {
7305         int N = ws.size();
7306         for (int i=0; i<N; i++) {
7307             final int uid = mapUid(ws.getUid(i));
7308             noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
7309         }
7310 
7311         final List<WorkChain> workChains = ws.getWorkChains();
7312         if (workChains != null) {
7313             for (int i = 0; i < workChains.size(); ++i) {
7314                 final WorkChain workChain = workChains.get(i);
7315                 final int uid = mapUid(workChain.getAttributionUid());
7316                 noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
7317             }
7318         }
7319     }
7320 
7321     @GuardedBy("this")
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph, long elapsedRealtimeMs, long uptimeMs)7322     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph,
7323             long elapsedRealtimeMs, long uptimeMs) {
7324         int N = ws.size();
7325         for (int i=0; i<N; i++) {
7326             noteWifiBatchedScanStartedLocked(ws.getUid(i), csph, elapsedRealtimeMs, uptimeMs);
7327         }
7328 
7329         final List<WorkChain> workChains = ws.getWorkChains();
7330         if (workChains != null) {
7331             for (int i = 0; i < workChains.size(); ++i) {
7332                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph,
7333                         elapsedRealtimeMs, uptimeMs);
7334             }
7335         }
7336     }
7337 
7338     @GuardedBy("this")
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7339     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws,
7340             long elapsedRealtimeMs, long uptimeMs) {
7341         int N = ws.size();
7342         for (int i=0; i<N; i++) {
7343             noteWifiBatchedScanStoppedLocked(ws.getUid(i), elapsedRealtimeMs, uptimeMs);
7344         }
7345 
7346         final List<WorkChain> workChains = ws.getWorkChains();
7347         if (workChains != null) {
7348             for (int i = 0; i < workChains.size(); ++i) {
7349                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid(),
7350                         elapsedRealtimeMs, uptimeMs);
7351             }
7352         }
7353     }
7354 
includeInStringArray(String[] array, String str)7355     private static String[] includeInStringArray(String[] array, String str) {
7356         if (ArrayUtils.indexOf(array, str) >= 0) {
7357             return array;
7358         }
7359         String[] newArray = new String[array.length+1];
7360         System.arraycopy(array, 0, newArray, 0, array.length);
7361         newArray[array.length] = str;
7362         return newArray;
7363     }
7364 
excludeFromStringArray(String[] array, String str)7365     private static String[] excludeFromStringArray(String[] array, String str) {
7366         int index = ArrayUtils.indexOf(array, str);
7367         if (index >= 0) {
7368             String[] newArray = new String[array.length-1];
7369             if (index > 0) {
7370                 System.arraycopy(array, 0, newArray, 0, index);
7371             }
7372             if (index < array.length-1) {
7373                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
7374             }
7375             return newArray;
7376         }
7377         return array;
7378     }
7379 
7380     /** @hide */
noteNetworkInterfaceForTransports(String iface, int[] transportTypes)7381     public void noteNetworkInterfaceForTransports(String iface, int[] transportTypes) {
7382         if (TextUtils.isEmpty(iface)) return;
7383         final int displayTransport = getDisplayTransport(transportTypes);
7384 
7385         synchronized (mModemNetworkLock) {
7386             if (displayTransport == TRANSPORT_CELLULAR) {
7387                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
7388                 if (DEBUG) {
7389                     Slog.d(TAG, "Note mobile iface " + iface + ": "
7390                             + Arrays.toString(mModemIfaces));
7391                 }
7392             } else {
7393                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
7394                 if (DEBUG) {
7395                     Slog.d(TAG, "Note non-mobile iface " + iface + ": "
7396                             + Arrays.toString(mModemIfaces));
7397                 }
7398             }
7399         }
7400 
7401         synchronized (mWifiNetworkLock) {
7402             if (displayTransport == TRANSPORT_WIFI) {
7403                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
7404                 if (DEBUG) {
7405                     Slog.d(TAG, "Note wifi iface " + iface + ": " + Arrays.toString(mWifiIfaces));
7406                 }
7407             } else {
7408                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
7409                 if (DEBUG) {
7410                     Slog.d(TAG, "Note non-wifi iface " + iface + ": "
7411                             + Arrays.toString(mWifiIfaces));
7412                 }
7413             }
7414         }
7415     }
7416 
7417     /**
7418      * Records timing data related to an incoming Binder call in order to attribute
7419      * the power consumption to the calling app.
7420      */
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)7421     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
7422             Collection<BinderCallsStats.CallStat> callStats) {
7423         noteBinderCallStats(workSourceUid, incrementalCallCount, callStats,
7424                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7425     }
7426 
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats, long elapsedRealtimeMs, long uptimeMs)7427     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
7428             Collection<BinderCallsStats.CallStat> callStats,
7429             long elapsedRealtimeMs, long uptimeMs) {
7430         synchronized (this) {
7431             getUidStatsLocked(workSourceUid, elapsedRealtimeMs, uptimeMs)
7432                     .noteBinderCallStatsLocked(incrementalCallCount, callStats);
7433         }
7434     }
7435 
7436     /**
7437      * Takes note of native IDs of threads taking incoming binder calls. The CPU time
7438      * of these threads is attributed to the apps making those binder calls.
7439      */
noteBinderThreadNativeIds(int[] binderThreadNativeTids)7440     public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) {
7441         mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids);
7442     }
7443 
7444     /**
7445      * Estimates the proportion of system server CPU activity handling incoming binder calls
7446      * that can be attributed to each app
7447      */
7448     @VisibleForTesting
updateSystemServiceCallStats()7449     public void updateSystemServiceCallStats() {
7450         // Start off by computing the average duration of recorded binder calls,
7451         // regardless of which binder or transaction. We will use this as a fallback
7452         // for calls that were not sampled at all.
7453         int totalRecordedCallCount = 0;
7454         long totalRecordedCallTimeMicros = 0;
7455         for (int i = 0; i < mUidStats.size(); i++) {
7456             Uid uid = mUidStats.valueAt(i);
7457             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
7458             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
7459                 BinderCallStats stats = binderCallStats.valueAt(j);
7460                 totalRecordedCallCount += stats.recordedCallCount;
7461                 totalRecordedCallTimeMicros += stats.recordedCpuTimeMicros;
7462             }
7463         }
7464 
7465         long totalSystemServiceTimeMicros = 0;
7466 
7467         // For every UID, use recorded durations of sampled binder calls to estimate
7468         // the total time the system server spent handling requests from this UID.
7469         for (int i = 0; i < mUidStats.size(); i++) {
7470             Uid uid = mUidStats.valueAt(i);
7471 
7472             long totalTimeForUidUs = 0;
7473             int totalCallCountForUid = 0;
7474             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
7475             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
7476                 BinderCallStats stats = binderCallStats.valueAt(j);
7477                 totalCallCountForUid += stats.callCount;
7478                 if (stats.recordedCallCount > 0) {
7479                     totalTimeForUidUs +=
7480                             stats.callCount * stats.recordedCpuTimeMicros / stats.recordedCallCount;
7481                 } else if (totalRecordedCallCount > 0) {
7482                     totalTimeForUidUs +=
7483                             stats.callCount * totalRecordedCallTimeMicros / totalRecordedCallCount;
7484                 }
7485             }
7486 
7487             if (totalCallCountForUid < uid.mBinderCallCount && totalRecordedCallCount > 0) {
7488                 // Estimate remaining calls, which were not tracked because of binder call
7489                 // stats sampling
7490                 totalTimeForUidUs +=
7491                         (uid.mBinderCallCount - totalCallCountForUid) * totalRecordedCallTimeMicros
7492                                 / totalRecordedCallCount;
7493             }
7494 
7495             uid.mSystemServiceTimeUs = totalTimeForUidUs;
7496             totalSystemServiceTimeMicros += totalTimeForUidUs;
7497         }
7498 
7499         for (int i = 0; i < mUidStats.size(); i++) {
7500             Uid uid = mUidStats.valueAt(i);
7501             if (totalSystemServiceTimeMicros > 0) {
7502                 uid.mProportionalSystemServiceUsage =
7503                         (double) uid.mSystemServiceTimeUs / totalSystemServiceTimeMicros;
7504             } else {
7505                 uid.mProportionalSystemServiceUsage = 0;
7506             }
7507         }
7508     }
7509 
getWifiIfaces()7510     public String[] getWifiIfaces() {
7511         synchronized (mWifiNetworkLock) {
7512             return mWifiIfaces;
7513         }
7514     }
7515 
getMobileIfaces()7516     public String[] getMobileIfaces() {
7517         synchronized (mModemNetworkLock) {
7518             return mModemIfaces;
7519         }
7520     }
7521 
getScreenOnTime(long elapsedRealtimeUs, int which)7522     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
7523         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7524     }
7525 
getScreenOnCount(int which)7526     @Override public int getScreenOnCount(int which) {
7527         return mScreenOnTimer.getCountLocked(which);
7528     }
7529 
getScreenDozeTime(long elapsedRealtimeUs, int which)7530     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
7531         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7532     }
7533 
getScreenDozeCount(int which)7534     @Override public int getScreenDozeCount(int which) {
7535         return mScreenDozeTimer.getCountLocked(which);
7536     }
7537 
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)7538     @Override public long getScreenBrightnessTime(int brightnessBin,
7539             long elapsedRealtimeUs, int which) {
7540         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
7541                 elapsedRealtimeUs, which);
7542     }
7543 
getScreenBrightnessTimer(int brightnessBin)7544     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
7545         return mScreenBrightnessTimer[brightnessBin];
7546     }
7547 
7548     @Override
getDisplayCount()7549     public int getDisplayCount() {
7550         return mPerDisplayBatteryStats.length;
7551     }
7552 
7553     @Override
getDisplayScreenOnTime(int display, long elapsedRealtimeUs)7554     public long getDisplayScreenOnTime(int display, long elapsedRealtimeUs) {
7555         return mPerDisplayBatteryStats[display].screenOnTimer.getTotalTimeLocked(elapsedRealtimeUs,
7556                 STATS_SINCE_CHARGED);
7557     }
7558 
7559     @Override
getDisplayScreenDozeTime(int display, long elapsedRealtimeUs)7560     public long getDisplayScreenDozeTime(int display, long elapsedRealtimeUs) {
7561         return mPerDisplayBatteryStats[display].screenDozeTimer.getTotalTimeLocked(
7562                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
7563     }
7564 
7565     @Override
getDisplayScreenBrightnessTime(int display, int brightnessBin, long elapsedRealtimeUs)7566     public long getDisplayScreenBrightnessTime(int display, int brightnessBin,
7567             long elapsedRealtimeUs) {
7568         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
7569         return displayStats.screenBrightnessTimers[brightnessBin].getTotalTimeLocked(
7570                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
7571     }
7572 
getInteractiveTime(long elapsedRealtimeUs, int which)7573     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
7574         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7575     }
7576 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)7577     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
7578         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7579     }
7580 
getPowerSaveModeEnabledCount(int which)7581     @Override public int getPowerSaveModeEnabledCount(int which) {
7582         return mPowerSaveModeEnabledTimer.getCountLocked(which);
7583     }
7584 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)7585     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
7586             int which) {
7587         switch (mode) {
7588             case DEVICE_IDLE_MODE_LIGHT:
7589                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7590             case DEVICE_IDLE_MODE_DEEP:
7591                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7592         }
7593         return 0;
7594     }
7595 
getDeviceIdleModeCount(int mode, int which)7596     @Override public int getDeviceIdleModeCount(int mode, int which) {
7597         switch (mode) {
7598             case DEVICE_IDLE_MODE_LIGHT:
7599                 return mDeviceIdleModeLightTimer.getCountLocked(which);
7600             case DEVICE_IDLE_MODE_DEEP:
7601                 return mDeviceIdleModeFullTimer.getCountLocked(which);
7602         }
7603         return 0;
7604     }
7605 
getLongestDeviceIdleModeTime(int mode)7606     @Override public long getLongestDeviceIdleModeTime(int mode) {
7607         switch (mode) {
7608             case DEVICE_IDLE_MODE_LIGHT:
7609                 return mLongestLightIdleTimeMs;
7610             case DEVICE_IDLE_MODE_DEEP:
7611                 return mLongestFullIdleTimeMs;
7612         }
7613         return 0;
7614     }
7615 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)7616     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
7617         switch (mode) {
7618             case DEVICE_IDLE_MODE_LIGHT:
7619                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7620             case DEVICE_IDLE_MODE_DEEP:
7621                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7622         }
7623         return 0;
7624     }
7625 
getDeviceIdlingCount(int mode, int which)7626     @Override public int getDeviceIdlingCount(int mode, int which) {
7627         switch (mode) {
7628             case DEVICE_IDLE_MODE_LIGHT:
7629                 return mDeviceLightIdlingTimer.getCountLocked(which);
7630             case DEVICE_IDLE_MODE_DEEP:
7631                 return mDeviceIdlingTimer.getCountLocked(which);
7632         }
7633         return 0;
7634     }
7635 
getNumConnectivityChange(int which)7636     @Override public int getNumConnectivityChange(int which) {
7637         return mNumConnectivityChange;
7638     }
7639 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)7640     @Override public long getGpsSignalQualityTime(int strengthBin,
7641             long elapsedRealtimeUs, int which) {
7642         if (strengthBin < 0 || strengthBin >= mGpsSignalQualityTimer.length) {
7643             return 0;
7644         }
7645         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
7646                 elapsedRealtimeUs, which);
7647     }
7648 
getGpsBatteryDrainMaMs()7649     @Override public long getGpsBatteryDrainMaMs() {
7650         final double opVolt = mPowerProfile.getAveragePower(
7651             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
7652         if (opVolt == 0) {
7653             return 0;
7654         }
7655         double energyUsedMaMs = 0.0;
7656         final int which = STATS_SINCE_CHARGED;
7657         final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
7658         for(int i=0; i < mGpsSignalQualityTimer.length; i++) {
7659             energyUsedMaMs
7660                     += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
7661                     * (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000);
7662         }
7663         return (long) energyUsedMaMs;
7664     }
7665 
getPhoneOnTime(long elapsedRealtimeUs, int which)7666     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
7667         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7668     }
7669 
getPhoneOnCount(int which)7670     @Override public int getPhoneOnCount(int which) {
7671         return mPhoneOnTimer.getCountLocked(which);
7672     }
7673 
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)7674     @Override public long getPhoneSignalStrengthTime(int strengthBin,
7675             long elapsedRealtimeUs, int which) {
7676         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
7677                 elapsedRealtimeUs, which);
7678     }
7679 
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)7680     @Override public long getPhoneSignalScanningTime(
7681             long elapsedRealtimeUs, int which) {
7682         return mPhoneSignalScanningTimer.getTotalTimeLocked(
7683                 elapsedRealtimeUs, which);
7684     }
7685 
getPhoneSignalScanningTimer()7686     @Override public Timer getPhoneSignalScanningTimer() {
7687         return mPhoneSignalScanningTimer;
7688     }
7689 
getPhoneSignalStrengthCount(int strengthBin, int which)7690     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
7691         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
7692     }
7693 
getPhoneSignalStrengthTimer(int strengthBin)7694     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
7695         return mPhoneSignalStrengthsTimer[strengthBin];
7696     }
7697 
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)7698     @Override public long getPhoneDataConnectionTime(int dataType,
7699             long elapsedRealtimeUs, int which) {
7700         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
7701                 elapsedRealtimeUs, which);
7702     }
7703 
getPhoneDataConnectionCount(int dataType, int which)7704     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
7705         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
7706     }
7707 
getPhoneDataConnectionTimer(int dataType)7708     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
7709         return mPhoneDataConnectionsTimer[dataType];
7710     }
7711 
getNrNsaTime(long elapsedRealtimeUs)7712     @Override public long getNrNsaTime(long elapsedRealtimeUs) {
7713         return mNrNsaTimer.getTotalTimeLocked(elapsedRealtimeUs, STATS_SINCE_CHARGED);
7714     }
7715 
getActiveRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)7716     @Override public long getActiveRadioDurationMs(@RadioAccessTechnology int rat,
7717             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
7718             long elapsedRealtimeMs) {
7719         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7720         if (stats == null) return 0L;
7721 
7722         final int freqCount = stats.perStateTimers.length;
7723         if (frequencyRange < 0 || frequencyRange >= freqCount) return 0L;
7724 
7725         final StopwatchTimer[] strengthTimers = stats.perStateTimers[frequencyRange];
7726         final int strengthCount = strengthTimers.length;
7727         if (signalStrength < 0 || signalStrength >= strengthCount) return 0L;
7728 
7729         return stats.perStateTimers[frequencyRange][signalStrength].getTotalTimeLocked(
7730                 elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
7731     }
7732 
7733     @Override
getActiveTxRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)7734     public long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
7735             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
7736             long elapsedRealtimeMs) {
7737         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7738         if (stats == null) return DURATION_UNAVAILABLE;
7739 
7740         final LongSamplingCounter counter = stats.getTxDurationCounter(frequencyRange,
7741                 signalStrength, false);
7742         if (counter == null) return DURATION_UNAVAILABLE;
7743 
7744         return counter.getCountLocked(STATS_SINCE_CHARGED);
7745     }
7746 
7747     @Override
getActiveRxRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs)7748     public long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
7749             @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs) {
7750         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7751         if (stats == null) return DURATION_UNAVAILABLE;
7752 
7753         final LongSamplingCounter counter = stats.getRxDurationCounter(frequencyRange, false);
7754         if (counter == null) return DURATION_UNAVAILABLE;
7755 
7756         return counter.getCountLocked(STATS_SINCE_CHARGED);
7757     }
7758 
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)7759     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
7760         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7761     }
7762 
getMobileRadioActiveCount(int which)7763     @Override public int getMobileRadioActiveCount(int which) {
7764         return mMobileRadioActiveTimer.getCountLocked(which);
7765     }
7766 
getMobileRadioActiveAdjustedTime(int which)7767     @Override public long getMobileRadioActiveAdjustedTime(int which) {
7768         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
7769     }
7770 
getMobileRadioActiveUnknownTime(int which)7771     @Override public long getMobileRadioActiveUnknownTime(int which) {
7772         return mMobileRadioActiveUnknownTime.getCountLocked(which);
7773     }
7774 
getMobileRadioActiveUnknownCount(int which)7775     @Override public int getMobileRadioActiveUnknownCount(int which) {
7776         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
7777     }
7778 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)7779     @Override public long getWifiMulticastWakelockTime(
7780             long elapsedRealtimeUs, int which) {
7781         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
7782                 elapsedRealtimeUs, which);
7783     }
7784 
getWifiMulticastWakelockCount(int which)7785     @Override public int getWifiMulticastWakelockCount(int which) {
7786         return mWifiMulticastWakelockTimer.getCountLocked(which);
7787     }
7788 
getWifiOnTime(long elapsedRealtimeUs, int which)7789     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
7790         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7791     }
7792 
getWifiActiveTime(long elapsedRealtimeUs, int which)7793     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
7794         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7795     }
7796 
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)7797     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
7798         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7799     }
7800 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)7801     @Override public long getWifiStateTime(int wifiState,
7802             long elapsedRealtimeUs, int which) {
7803         return mWifiStateTimer[wifiState].getTotalTimeLocked(
7804                 elapsedRealtimeUs, which);
7805     }
7806 
getWifiStateCount(int wifiState, int which)7807     @Override public int getWifiStateCount(int wifiState, int which) {
7808         return mWifiStateTimer[wifiState].getCountLocked(which);
7809     }
7810 
getWifiStateTimer(int wifiState)7811     @Override public Timer getWifiStateTimer(int wifiState) {
7812         return mWifiStateTimer[wifiState];
7813     }
7814 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)7815     @Override public long getWifiSupplStateTime(int state,
7816             long elapsedRealtimeUs, int which) {
7817         return mWifiSupplStateTimer[state].getTotalTimeLocked(
7818                 elapsedRealtimeUs, which);
7819     }
7820 
getWifiSupplStateCount(int state, int which)7821     @Override public int getWifiSupplStateCount(int state, int which) {
7822         return mWifiSupplStateTimer[state].getCountLocked(which);
7823     }
7824 
getWifiSupplStateTimer(int state)7825     @Override public Timer getWifiSupplStateTimer(int state) {
7826         return mWifiSupplStateTimer[state];
7827     }
7828 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)7829     @Override public long getWifiSignalStrengthTime(int strengthBin,
7830             long elapsedRealtimeUs, int which) {
7831         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
7832                 elapsedRealtimeUs, which);
7833     }
7834 
getWifiSignalStrengthCount(int strengthBin, int which)7835     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
7836         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
7837     }
7838 
getWifiSignalStrengthTimer(int strengthBin)7839     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
7840         return mWifiSignalStrengthsTimer[strengthBin];
7841     }
7842 
7843     @Override
getBluetoothControllerActivity()7844     public ControllerActivityCounter getBluetoothControllerActivity() {
7845         return mBluetoothActivity;
7846     }
7847 
7848     @Override
getWifiControllerActivity()7849     public ControllerActivityCounter getWifiControllerActivity() {
7850         return mWifiActivity;
7851     }
7852 
7853     @Override
getModemControllerActivity()7854     public ControllerActivityCounter getModemControllerActivity() {
7855         return mModemActivity;
7856     }
7857 
7858     @Override
hasBluetoothActivityReporting()7859     public boolean hasBluetoothActivityReporting() {
7860         return mHasBluetoothReporting;
7861     }
7862 
7863     @Override
hasWifiActivityReporting()7864     public boolean hasWifiActivityReporting() {
7865         return mHasWifiReporting;
7866     }
7867 
7868     @Override
hasModemActivityReporting()7869     public boolean hasModemActivityReporting() {
7870         return mHasModemReporting;
7871     }
7872 
7873     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)7874     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
7875         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7876     }
7877 
7878     @Override
getFlashlightOnCount(int which)7879     public long getFlashlightOnCount(int which) {
7880         return mFlashlightOnTimer.getCountLocked(which);
7881     }
7882 
7883     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)7884     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
7885         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7886     }
7887 
7888     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)7889     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
7890         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7891     }
7892 
7893     @Override
getNetworkActivityBytes(int type, int which)7894     public long getNetworkActivityBytes(int type, int which) {
7895         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
7896             return mNetworkByteActivityCounters[type].getCountLocked(which);
7897         } else {
7898             return 0;
7899         }
7900     }
7901 
7902     @Override
getNetworkActivityPackets(int type, int which)7903     public long getNetworkActivityPackets(int type, int which) {
7904         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
7905             return mNetworkPacketActivityCounters[type].getCountLocked(which);
7906         } else {
7907             return 0;
7908         }
7909     }
7910 
7911     @GuardedBy("this")
7912     @Override
getBluetoothEnergyConsumptionUC()7913     public long getBluetoothEnergyConsumptionUC() {
7914         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH);
7915     }
7916 
7917     @GuardedBy("this")
7918     @Override
getCpuEnergyConsumptionUC()7919     public long getCpuEnergyConsumptionUC() {
7920         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU);
7921     }
7922 
7923     @GuardedBy("this")
7924     @Override
getGnssEnergyConsumptionUC()7925     public long getGnssEnergyConsumptionUC() {
7926         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_GNSS);
7927     }
7928 
7929     @GuardedBy("this")
7930     @Override
getMobileRadioEnergyConsumptionUC()7931     public long getMobileRadioEnergyConsumptionUC() {
7932         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
7933     }
7934 
7935     @GuardedBy("this")
7936     @Override
getPhoneEnergyConsumptionUC()7937     public long getPhoneEnergyConsumptionUC() {
7938         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_PHONE);
7939     }
7940 
7941     @GuardedBy("this")
7942     @Override
getScreenOnEnergyConsumptionUC()7943     public long getScreenOnEnergyConsumptionUC() {
7944         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON);
7945     }
7946 
7947     @GuardedBy("this")
7948     @Override
getScreenDozeEnergyConsumptionUC()7949     public long getScreenDozeEnergyConsumptionUC() {
7950         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_DOZE);
7951     }
7952 
7953     @GuardedBy("this")
7954     @Override
getWifiEnergyConsumptionUC()7955     public long getWifiEnergyConsumptionUC() {
7956         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI);
7957     }
7958 
7959     @GuardedBy("this")
7960     @Override
getCameraEnergyConsumptionUC()7961     public long getCameraEnergyConsumptionUC() {
7962         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
7963     }
7964 
7965     /**
7966      * Returns the consumption (in microcoulombs) that the given standard power bucket consumed.
7967      * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable
7968      *
7969      * @param bucket standard power bucket of interest
7970      * @return charge (in microcoulombs) used for this power bucket
7971      */
7972     @GuardedBy("this")
getPowerBucketConsumptionUC(@tandardPowerBucket int bucket)7973     private long getPowerBucketConsumptionUC(@StandardPowerBucket int bucket) {
7974         if (mGlobalEnergyConsumerStats == null) {
7975             return POWER_DATA_UNAVAILABLE;
7976         }
7977         return mGlobalEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket);
7978     }
7979 
7980     @GuardedBy("this")
7981     @Override
getCustomEnergyConsumerBatteryConsumptionUC()7982     public @Nullable long[] getCustomEnergyConsumerBatteryConsumptionUC() {
7983         if (mGlobalEnergyConsumerStats == null) {
7984             return null;
7985         }
7986         return mGlobalEnergyConsumerStats.getAccumulatedCustomBucketCharges();
7987     }
7988 
7989     /**
7990      * Returns the names of custom power components.
7991      */
7992     @Override
getCustomEnergyConsumerNames()7993     public @NonNull String[] getCustomEnergyConsumerNames() {
7994         synchronized (this) {
7995             if (mEnergyConsumerStatsConfig == null) {
7996                 return new String[0];
7997             }
7998             final String[] names = mEnergyConsumerStatsConfig.getCustomBucketNames();
7999             for (int i = 0; i < names.length; i++) {
8000                 if (TextUtils.isEmpty(names[i])) {
8001                     names[i] = "CUSTOM_" + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i;
8002                 }
8003             }
8004             return names;
8005         }
8006     }
8007 
8008     @Override
getStartClockTime()8009     public long getStartClockTime() {
8010         synchronized (this) {
8011             final long currentTimeMs = mClock.currentTimeMillis();
8012             if ((currentTimeMs > MILLISECONDS_IN_YEAR
8013                     && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
8014                 || (mStartClockTimeMs > currentTimeMs)) {
8015                 // If the start clock time has changed by more than a year, then presumably
8016                 // the previous time was completely bogus.  So we are going to figure out a
8017                 // new time based on how much time has elapsed since we started counting.
8018                 mHistory.recordCurrentTimeChange(mClock.elapsedRealtime(), mClock.uptimeMillis(),
8019                         currentTimeMs);
8020                 adjustStartClockTime(currentTimeMs);
8021             }
8022             return mStartClockTimeMs;
8023         }
8024     }
8025 
8026     /**
8027      * Returns the monotonic time when the BatteryStats session started.
8028      */
getMonotonicStartTime()8029     public long getMonotonicStartTime() {
8030         return mMonotonicStartTime;
8031     }
8032 
8033     /**
8034      * Returns the monotonic time when the BatteryStats session ended, or
8035      * {@link MonotonicClock#UNDEFINED} if the session is still ongoing.
8036      */
getMonotonicEndTime()8037     public long getMonotonicEndTime() {
8038         return mMonotonicEndTime;
8039     }
8040 
getStartPlatformVersion()8041     @Override public String getStartPlatformVersion() {
8042         return mStartPlatformVersion;
8043     }
8044 
getEndPlatformVersion()8045     @Override public String getEndPlatformVersion() {
8046         return mEndPlatformVersion;
8047     }
8048 
getParcelVersion()8049     @Override public int getParcelVersion() {
8050         return VERSION;
8051     }
8052 
getIsOnBattery()8053     @Override public boolean getIsOnBattery() {
8054         return mOnBattery;
8055     }
8056 
getStatsStartRealtime()8057     @Override public long getStatsStartRealtime() {
8058         return mRealtimeStartUs;
8059     }
8060 
getUidStats()8061     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
8062         return mUidStats;
8063     }
8064 
resetIfNotNull(T t, boolean detachIfReset, long elapsedRealtimeUs)8065     private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset,
8066             long elapsedRealtimeUs) {
8067         if (t != null) {
8068             return t.reset(detachIfReset, elapsedRealtimeUs);
8069         }
8070         return true;
8071     }
8072 
resetIfNotNull(T[] t, boolean detachIfReset, long elapsedRealtimeUs)8073     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset,
8074             long elapsedRealtimeUs) {
8075         if (t != null) {
8076             boolean ret = true;
8077             for (int i = 0; i < t.length; i++) {
8078                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
8079             }
8080             return ret;
8081         }
8082         return true;
8083     }
8084 
resetIfNotNull(T[][] t, boolean detachIfReset, long elapsedRealtimeUs)8085     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset,
8086             long elapsedRealtimeUs) {
8087         if (t != null) {
8088             boolean ret = true;
8089             for (int i = 0; i < t.length; i++) {
8090                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
8091             }
8092             return ret;
8093         }
8094         return true;
8095     }
8096 
resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset, long elapsedRealtimeUs)8097     private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
8098             boolean detachIfReset, long elapsedRealtimeUs) {
8099         if (counter != null) {
8100             counter.reset(detachIfReset, elapsedRealtimeUs);
8101         }
8102         return true;
8103     }
8104 
detachIfNotNull(T t)8105     private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
8106         if (t != null) {
8107             t.detach();
8108         }
8109     }
8110 
detachIfNotNull(T[] t)8111     private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
8112         if (t != null) {
8113             for (int i = 0; i < t.length; i++) {
8114                 detachIfNotNull(t[i]);
8115             }
8116         }
8117     }
8118 
detachIfNotNull(T[][] t)8119     private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
8120         if (t != null) {
8121             for (int i = 0; i < t.length; i++) {
8122                 detachIfNotNull(t[i]);
8123             }
8124         }
8125     }
8126 
detachIfNotNull(ControllerActivityCounterImpl counter)8127     private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
8128         if (counter != null) {
8129             counter.detach();
8130         }
8131     }
8132 
8133     /**
8134      * Accumulates stats for a specific binder transaction.
8135      */
8136     @VisibleForTesting
8137     protected static class BinderCallStats {
8138         public Class<? extends Binder> binderClass;
8139         public int transactionCode;
8140         public String methodName;
8141 
8142         public long callCount;
8143         public long recordedCallCount;
8144         public long recordedCpuTimeMicros;
8145 
8146 
8147         @Override
hashCode()8148         public int hashCode() {
8149             return binderClass.hashCode() * 31 + transactionCode;
8150         }
8151 
8152         @Override
equals(Object obj)8153         public boolean equals(Object obj) {
8154             if (!(obj instanceof BinderCallStats)) {
8155                 return false;
8156             }
8157             BinderCallStats bcsk = (BinderCallStats) obj;
8158             return binderClass.equals(bcsk.binderClass) && transactionCode == bcsk.transactionCode;
8159         }
8160 
getClassName()8161         public String getClassName() {
8162             return binderClass.getName();
8163         }
8164 
getMethodName()8165         public String getMethodName() {
8166             return methodName;
8167         }
8168 
8169         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
ensureMethodName(BinderTransactionNameResolver resolver)8170         public void ensureMethodName(BinderTransactionNameResolver resolver) {
8171             if (methodName == null) {
8172                 methodName = resolver.getMethodName(binderClass, transactionCode);
8173             }
8174         }
8175 
8176         @Override
toString()8177         public String toString() {
8178             return "BinderCallStats{"
8179                     + binderClass
8180                     + " transaction=" + transactionCode
8181                     + " callCount=" + callCount
8182                     + " recordedCallCount=" + recordedCallCount
8183                     + " recorderCpuTimeMicros=" + recordedCpuTimeMicros
8184                     + "}";
8185         }
8186     }
8187 
8188     /**
8189      * The statistics associated with a particular uid.
8190      */
8191     public static class Uid extends BatteryStats.Uid {
8192         /**
8193          * BatteryStatsImpl that we are associated with.
8194          */
8195         protected BatteryStatsImpl mBsi;
8196 
8197         final int mUid;
8198 
8199         /** TimeBase for when uid is in background and device is on battery. */
8200         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
8201         public final TimeBase mOnBatteryBackgroundTimeBase;
8202         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
8203         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
8204 
8205         boolean mWifiRunning;
8206         StopwatchTimer mWifiRunningTimer;
8207 
8208         boolean mFullWifiLockOut;
8209         StopwatchTimer mFullWifiLockTimer;
8210 
8211         boolean mWifiScanStarted;
8212         DualTimer mWifiScanTimer;
8213 
8214         static final int NO_BATCHED_SCAN_STARTED = -1;
8215         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8216         StopwatchTimer[] mWifiBatchedScanTimer;
8217 
8218         int mWifiMulticastWakelockCount;
8219         StopwatchTimer mWifiMulticastTimer;
8220 
8221         StopwatchTimer mAudioTurnedOnTimer;
8222         StopwatchTimer mVideoTurnedOnTimer;
8223         StopwatchTimer mFlashlightTurnedOnTimer;
8224         StopwatchTimer mCameraTurnedOnTimer;
8225         StopwatchTimer mForegroundActivityTimer;
8226         StopwatchTimer mForegroundServiceTimer;
8227         /** Total time spent by the uid holding any partial wakelocks. */
8228         DualTimer mAggregatedPartialWakelockTimer;
8229         DualTimer mBluetoothScanTimer;
8230         DualTimer mBluetoothUnoptimizedScanTimer;
8231         Counter mBluetoothScanResultCounter;
8232         Counter mBluetoothScanResultBgCounter;
8233 
8234         int mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
8235         StopwatchTimer[] mProcessStateTimer;
8236 
8237         boolean mInForegroundService = false;
8238 
8239         BatchTimer mVibratorOnTimer;
8240 
8241         Counter[] mUserActivityCounters;
8242 
8243         LongSamplingCounter[] mNetworkByteActivityCounters;
8244         LongSamplingCounter[] mNetworkPacketActivityCounters;
8245         TimeMultiStateCounter mMobileRadioActiveTime;
8246         LongSamplingCounter mMobileRadioActiveCount;
8247 
8248         /**
8249          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
8250          */
8251         private LongSamplingCounter mMobileRadioApWakeupCount;
8252 
8253         /**
8254          * How many times this UID woke up the Application Processor due to a Wifi packet.
8255          */
8256         private LongSamplingCounter mWifiRadioApWakeupCount;
8257 
8258         /**
8259          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
8260          * Can be null if the UID has had no such activity.
8261          */
8262         private ControllerActivityCounterImpl mWifiControllerActivity;
8263 
8264         /**
8265          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
8266          * Can be null if the UID has had no such activity.
8267          */
8268         private ControllerActivityCounterImpl mBluetoothControllerActivity;
8269 
8270         /**
8271          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
8272          * Can be null if the UID has had no such activity.
8273          */
8274         private ControllerActivityCounterImpl mModemControllerActivity;
8275 
8276         /**
8277          * The CPU times we had at the last history details update.
8278          */
8279         long mLastStepUserTimeMs;
8280         long mLastStepSystemTimeMs;
8281         long mCurStepUserTimeMs;
8282         long mCurStepSystemTimeMs;
8283 
8284         LongSamplingCounter mUserCpuTime;
8285         LongSamplingCounter mSystemCpuTime;
8286         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
8287         TimeMultiStateCounter mCpuActiveTimeMs;
8288 
8289         LongSamplingCounterArray mCpuFreqTimeMs;
8290         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
8291         LongSamplingCounterArray mCpuClusterTimesMs;
8292 
8293         TimeInFreqMultiStateCounter mProcStateTimeMs;
8294         TimeInFreqMultiStateCounter mProcStateScreenOffTimeMs;
8295 
8296         SparseArray<ChildUid> mChildUids;
8297 
8298         /**
8299          * The statistics we have collected for this uid's wake locks.
8300          */
8301         final OverflowArrayMap<Wakelock> mWakelockStats;
8302 
8303         /**
8304          * The statistics we have collected for this uid's syncs.
8305          */
8306         final OverflowArrayMap<DualTimer> mSyncStats;
8307 
8308         /**
8309          * The statistics we have collected for this uid's jobs.
8310          */
8311         final OverflowArrayMap<DualTimer> mJobStats;
8312 
8313         /**
8314          * Count of the jobs that have completed and the reasons why they completed.
8315          */
8316         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
8317 
8318         /**
8319          * Count of app launch events that had associated deferred job counts or info about
8320          * last time a job was run.
8321          */
8322         Counter mJobsDeferredEventCount;
8323 
8324         /**
8325          * Count of deferred jobs that were pending when the app was launched or brought to
8326          * the foreground through a user interaction.
8327          */
8328         Counter mJobsDeferredCount;
8329 
8330         /**
8331          * Sum of time since the last time a job was run for this app before it was launched.
8332          */
8333         LongSamplingCounter mJobsFreshnessTimeMs;
8334 
8335         /**
8336          * Array of counts of instances where the time since the last job was run for the app
8337          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
8338          */
8339         final Counter[] mJobsFreshnessBuckets;
8340 
8341         /**
8342          * The statistics we have collected for this uid's sensor activations.
8343          */
8344         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
8345 
8346         /**
8347          * The statistics we have collected for this uid's processes.
8348          */
8349         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
8350 
8351         /**
8352          * The statistics we have collected for this uid's processes.
8353          */
8354         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
8355 
8356         /**
8357          * The transient wake stats we have collected for this uid's pids.
8358          */
8359         final SparseArray<Pid> mPids = new SparseArray<>();
8360 
8361         /**
8362          * Grand total of system server binder calls made by this uid.
8363          */
8364         private long mBinderCallCount;
8365 
8366         /**
8367          * Detailed information about system server binder calls made by this uid.
8368          */
8369         private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>();
8370 
8371         /**
8372          * EnergyConsumer consumption by this uid while on battery.
8373          * Its '<b>custom</b> power buckets' correspond to the
8374          * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
8375          * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
8376          *
8377          * Will be null if energy consumer data is completely unavailable (in which case
8378          * {@link #mGlobalEnergyConsumerStats} will also be null) or if the power usage by this uid
8379          * is 0 for every bucket.
8380          */
8381         private EnergyConsumerStats mUidEnergyConsumerStats;
8382 
8383         /**
8384          * Estimated total time spent by the system server handling requests from this uid.
8385          */
8386         private long mSystemServiceTimeUs;
8387 
8388         /**
8389          * Estimated proportion of system server binder call CPU cost for this uid.
8390          */
8391         private double mProportionalSystemServiceUsage;
8392 
Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs)8393         public Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs) {
8394             mBsi = bsi;
8395             mUid = uid;
8396 
8397             /* Observer list of TimeBase object in Uid is short */
8398             mOnBatteryBackgroundTimeBase = new TimeBase(false);
8399             mOnBatteryBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8400             /* Observer list of TimeBase object in Uid is short */
8401             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
8402             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8403 
8404             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8405             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8406             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
8407 
8408             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
8409                 @Override public Wakelock instantiateObject() {
8410                     return new Wakelock(mBsi, Uid.this);
8411                 }
8412             };
8413             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
8414                 @Override public DualTimer instantiateObject() {
8415                     return new DualTimer(mBsi.mClock, Uid.this, SYNC, null,
8416                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8417                 }
8418             };
8419             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
8420                 @Override public DualTimer instantiateObject() {
8421                     return new DualTimer(mBsi.mClock, Uid.this, JOB, null,
8422                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8423                 }
8424             };
8425 
8426             mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, this, WIFI_RUNNING,
8427                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
8428             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, this, FULL_WIFI_LOCK,
8429                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
8430             mWifiScanTimer = new DualTimer(mBsi.mClock, this, WIFI_SCAN,
8431                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8432             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
8433             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, this, WIFI_MULTICAST_ENABLED,
8434                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
8435             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
8436             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
8437             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
8438             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8439             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
8440         }
8441 
8442         @GuardedBy("mBsi")
8443         @VisibleForTesting
setProcessStateForTest(int procState, long elapsedTimeMs)8444         public void setProcessStateForTest(int procState, long elapsedTimeMs) {
8445             mProcessState = procState;
8446             getProcStateTimeCounter(elapsedTimeMs).setState(procState, elapsedTimeMs);
8447             getProcStateScreenOffTimeCounter(elapsedTimeMs).setState(procState, elapsedTimeMs);
8448             final int batteryConsumerProcessState =
8449                     mapUidProcessStateToBatteryConsumerProcessState(procState);
8450             getCpuActiveTimeCounter().setState(batteryConsumerProcessState, elapsedTimeMs);
8451             getMobileRadioActiveTimeCounter().setState(batteryConsumerProcessState, elapsedTimeMs);
8452             final ControllerActivityCounterImpl wifiControllerActivity =
8453                     getWifiControllerActivity();
8454             if (wifiControllerActivity != null) {
8455                 wifiControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs);
8456             }
8457             final ControllerActivityCounterImpl bluetoothControllerActivity =
8458                     getBluetoothControllerActivity();
8459             if (bluetoothControllerActivity != null) {
8460                 bluetoothControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs);
8461             }
8462             final EnergyConsumerStats energyStats =
8463                     getOrCreateEnergyConsumerStatsIfSupportedLocked();
8464             if (energyStats != null) {
8465                 energyStats.setState(batteryConsumerProcessState, elapsedTimeMs);
8466             }
8467         }
8468 
8469         @Override
getCpuFreqTimes(int which)8470         public long[] getCpuFreqTimes(int which) {
8471             return nullIfAllZeros(mCpuFreqTimeMs, which);
8472         }
8473 
8474         @Override
getScreenOffCpuFreqTimes(int which)8475         public long[] getScreenOffCpuFreqTimes(int which) {
8476             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
8477         }
8478 
getCpuActiveTimeCounter()8479         private TimeMultiStateCounter getCpuActiveTimeCounter() {
8480             if (mCpuActiveTimeMs == null) {
8481                 final long timestampMs = mBsi.mClock.elapsedRealtime();
8482                 mCpuActiveTimeMs = new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase,
8483                         BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
8484                 mCpuActiveTimeMs.setState(
8485                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
8486                         timestampMs);
8487             }
8488             return mCpuActiveTimeMs;
8489         }
8490 
8491         @Override
getCpuActiveTime()8492         public long getCpuActiveTime() {
8493             if (mCpuActiveTimeMs == null) {
8494                 return 0;
8495             }
8496 
8497             long activeTime = 0;
8498             for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
8499                 activeTime += mCpuActiveTimeMs.getCountForProcessState(procState);
8500             }
8501             return activeTime;
8502         }
8503 
8504         @Override
getCpuActiveTime(int procState)8505         public long getCpuActiveTime(int procState) {
8506             if (mCpuActiveTimeMs == null
8507                     || procState < 0 || procState >= BatteryConsumer.PROCESS_STATE_COUNT) {
8508                 return 0;
8509             }
8510 
8511             return mCpuActiveTimeMs.getCountForProcessState(procState);
8512         }
8513 
8514         @Override
getCpuClusterTimes()8515         public long[] getCpuClusterTimes() {
8516             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
8517         }
8518 
8519         @GuardedBy("mBsi")
8520         @Override
getCpuFreqTimes(long[] timesInFreqMs, int procState)8521         public boolean getCpuFreqTimes(long[] timesInFreqMs, int procState) {
8522             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
8523                 return false;
8524             }
8525             if (mProcStateTimeMs == null) {
8526                 return false;
8527             }
8528             if (!mBsi.mPerProcStateCpuTimesAvailable) {
8529                 mProcStateTimeMs = null;
8530                 return false;
8531             }
8532             return mProcStateTimeMs.getCountsLocked(timesInFreqMs, procState);
8533         }
8534 
8535         @GuardedBy("mBsi")
8536         @Override
getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState)8537         public boolean getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState) {
8538             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
8539                 return false;
8540             }
8541             if (mProcStateScreenOffTimeMs == null) {
8542                 return false;
8543             }
8544             if (!mBsi.mPerProcStateCpuTimesAvailable) {
8545                 mProcStateScreenOffTimeMs = null;
8546                 return false;
8547             }
8548             return mProcStateScreenOffTimeMs.getCountsLocked(timesInFreqMs, procState);
8549         }
8550 
getBinderCallCount()8551         public long getBinderCallCount() {
8552             return mBinderCallCount;
8553         }
8554 
8555         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
getBinderCallStats()8556         public ArraySet<BinderCallStats> getBinderCallStats() {
8557             return mBinderCallStats;
8558         }
8559 
8560         @Override
getProportionalSystemServiceUsage()8561         public  double getProportionalSystemServiceUsage() {
8562             return mProportionalSystemServiceUsage;
8563         }
8564 
8565         /**
8566          * Adds isolated UID to the list of children.
8567          */
addIsolatedUid(int isolatedUid)8568         public void addIsolatedUid(int isolatedUid) {
8569             if (mChildUids == null) {
8570                 mChildUids = new SparseArray<>();
8571             } else if (mChildUids.indexOfKey(isolatedUid) >= 0) {
8572                 return;
8573             }
8574             mChildUids.put(isolatedUid, new ChildUid());
8575         }
8576 
8577         /**
8578          * Removes isolated UID from the list of children.
8579          */
removeIsolatedUid(int isolatedUid)8580         public void removeIsolatedUid(int isolatedUid) {
8581             final int idx = mChildUids == null ? -1 : mChildUids.indexOfKey(isolatedUid);
8582             if (idx < 0) {
8583                 return;
8584             }
8585             mChildUids.remove(idx);
8586         }
8587 
8588         @GuardedBy("mBsi")
getChildUid(int childUid)8589         ChildUid getChildUid(int childUid) {
8590             return mChildUids == null ? null : mChildUids.get(childUid);
8591         }
8592 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)8593         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
8594             if (cpuTimesMs == null) {
8595                 return null;
8596             }
8597             final long[] counts = cpuTimesMs.getCountsLocked(which);
8598             if (counts == null) {
8599                 return null;
8600             }
8601             // Return counts only if at least one of the elements is non-zero.
8602             for (int i = counts.length - 1; i >= 0; --i) {
8603                 if (counts[i] != 0) {
8604                     return counts;
8605                 }
8606             }
8607             return null;
8608         }
8609 
8610         @GuardedBy("mBsi")
ensureMultiStateCounters(long timestampMs)8611         private void ensureMultiStateCounters(long timestampMs) {
8612             if (mBsi.mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
8613                 throw new IllegalStateException("Multi-state counters used in streamlined mode");
8614             }
8615 
8616             if (mProcStateTimeMs == null) {
8617                 mProcStateTimeMs =
8618                         new TimeInFreqMultiStateCounter(mBsi.mOnBatteryTimeBase,
8619                                 PROC_STATE_TIME_COUNTER_STATE_COUNT,
8620                                 mBsi.mCpuScalingPolicies.getScalingStepCount(),
8621                                 timestampMs);
8622             }
8623             if (mProcStateScreenOffTimeMs == null) {
8624                 mProcStateScreenOffTimeMs =
8625                         new TimeInFreqMultiStateCounter(mBsi.mOnBatteryScreenOffTimeBase,
8626                                 PROC_STATE_TIME_COUNTER_STATE_COUNT,
8627                                 mBsi.mCpuScalingPolicies.getScalingStepCount(),
8628                                 timestampMs);
8629             }
8630         }
8631 
8632         @GuardedBy("mBsi")
getProcStateTimeCounter(long timestampMs)8633         private TimeInFreqMultiStateCounter getProcStateTimeCounter(long timestampMs) {
8634             ensureMultiStateCounters(timestampMs);
8635             return mProcStateTimeMs;
8636         }
8637 
8638         @GuardedBy("mBsi")
getProcStateScreenOffTimeCounter(long timestampMs)8639         private TimeInFreqMultiStateCounter getProcStateScreenOffTimeCounter(long timestampMs) {
8640             ensureMultiStateCounters(timestampMs);
8641             return mProcStateScreenOffTimeMs;
8642         }
8643 
8644         @Override
getAggregatedPartialWakelockTimer()8645         public Timer getAggregatedPartialWakelockTimer() {
8646             return mAggregatedPartialWakelockTimer;
8647         }
8648 
8649         @Override
getWakelockStats()8650         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
8651             return mWakelockStats.getMap();
8652         }
8653 
8654         @Override
getMulticastWakelockStats()8655         public Timer getMulticastWakelockStats() {
8656             return mWifiMulticastTimer;
8657         }
8658 
8659         @Override
getSyncStats()8660         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
8661             return mSyncStats.getMap();
8662         }
8663 
8664         @Override
getJobStats()8665         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
8666             return mJobStats.getMap();
8667         }
8668 
8669         @Override
getJobCompletionStats()8670         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
8671             return mJobCompletions;
8672         }
8673 
8674         @Override
getSensorStats()8675         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
8676             return mSensorStats;
8677         }
8678 
8679         @Override
getProcessStats()8680         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
8681             return mProcessStats;
8682         }
8683 
8684         @Override
getPackageStats()8685         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
8686             return mPackageStats;
8687         }
8688 
8689         @Override
getUid()8690         public int getUid() {
8691             return mUid;
8692         }
8693 
8694         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)8695         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
8696             if (!mWifiRunning) {
8697                 mWifiRunning = true;
8698                 if (mWifiRunningTimer == null) {
8699                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, Uid.this, WIFI_RUNNING,
8700                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
8701                 }
8702                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
8703             }
8704         }
8705 
8706         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)8707         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
8708             if (mWifiRunning) {
8709                 mWifiRunning = false;
8710                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
8711             }
8712         }
8713 
8714         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)8715         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
8716             if (!mFullWifiLockOut) {
8717                 mFullWifiLockOut = true;
8718                 if (mFullWifiLockTimer == null) {
8719                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, Uid.this, FULL_WIFI_LOCK,
8720                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
8721                 }
8722                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
8723             }
8724         }
8725 
8726         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)8727         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
8728             if (mFullWifiLockOut) {
8729                 mFullWifiLockOut = false;
8730                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
8731             }
8732         }
8733 
8734         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)8735         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
8736             if (!mWifiScanStarted) {
8737                 mWifiScanStarted = true;
8738                 if (mWifiScanTimer == null) {
8739                     mWifiScanTimer = new DualTimer(mBsi.mClock, Uid.this, WIFI_SCAN,
8740                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
8741                             mOnBatteryBackgroundTimeBase);
8742                 }
8743                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
8744             }
8745         }
8746 
8747         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)8748         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
8749             if (mWifiScanStarted) {
8750                 mWifiScanStarted = false;
8751                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
8752             }
8753         }
8754 
8755         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)8756         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
8757             int bin = 0;
8758             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
8759                 csph = csph >> 3;
8760                 bin++;
8761             }
8762 
8763             if (mWifiBatchedScanBinStarted == bin) return;
8764 
8765             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
8766                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
8767                         stopRunningLocked(elapsedRealtimeMs);
8768             }
8769             mWifiBatchedScanBinStarted = bin;
8770             if (mWifiBatchedScanTimer[bin] == null) {
8771                 makeWifiBatchedScanBin(bin, null);
8772             }
8773             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
8774         }
8775 
8776         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)8777         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
8778             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
8779                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
8780                         stopRunningLocked(elapsedRealtimeMs);
8781                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8782             }
8783         }
8784 
8785         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)8786         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
8787             if (mWifiMulticastWakelockCount == 0) {
8788                 if (mWifiMulticastTimer == null) {
8789                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
8790                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
8791                 }
8792                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
8793             }
8794             mWifiMulticastWakelockCount++;
8795         }
8796 
8797         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)8798         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
8799             if (mWifiMulticastWakelockCount == 0) {
8800                 return;
8801             }
8802 
8803             mWifiMulticastWakelockCount--;
8804             if (mWifiMulticastWakelockCount == 0) {
8805                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
8806             }
8807         }
8808 
8809         @Override
getWifiControllerActivity()8810         public ControllerActivityCounterImpl getWifiControllerActivity() {
8811             return mWifiControllerActivity;
8812         }
8813 
8814         @Override
getBluetoothControllerActivity()8815         public ControllerActivityCounterImpl getBluetoothControllerActivity() {
8816             return mBluetoothControllerActivity;
8817         }
8818 
8819         @Override
getModemControllerActivity()8820         public ControllerActivityCounter getModemControllerActivity() {
8821             return mModemControllerActivity;
8822         }
8823 
getOrCreateWifiControllerActivityLocked()8824         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
8825             if (mWifiControllerActivity == null) {
8826                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8827                         mBsi.mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
8828             }
8829             return mWifiControllerActivity;
8830         }
8831 
getOrCreateBluetoothControllerActivityLocked()8832         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
8833             if (mBluetoothControllerActivity == null) {
8834                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8835                         mBsi.mOnBatteryTimeBase, NUM_BT_TX_LEVELS);
8836             }
8837             return mBluetoothControllerActivity;
8838         }
8839 
getOrCreateModemControllerActivityLocked()8840         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
8841             if (mModemControllerActivity == null) {
8842                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8843                         mBsi.mOnBatteryTimeBase, mBsi.MODEM_TX_POWER_LEVEL_COUNT);
8844             }
8845             return mModemControllerActivity;
8846         }
8847 
8848         @GuardedBy("mBsi")
getOrCreateEnergyConsumerStatsLocked()8849         private EnergyConsumerStats getOrCreateEnergyConsumerStatsLocked() {
8850             if (mUidEnergyConsumerStats == null) {
8851                 mUidEnergyConsumerStats = new EnergyConsumerStats(mBsi.mEnergyConsumerStatsConfig);
8852             }
8853             return mUidEnergyConsumerStats;
8854         }
8855 
8856         @GuardedBy("mBsi")
getOrCreateEnergyConsumerStatsIfSupportedLocked()8857         private EnergyConsumerStats getOrCreateEnergyConsumerStatsIfSupportedLocked() {
8858             if (mUidEnergyConsumerStats == null && mBsi.mEnergyConsumerStatsConfig != null) {
8859                 mUidEnergyConsumerStats = new EnergyConsumerStats(mBsi.mEnergyConsumerStatsConfig);
8860             }
8861             return mUidEnergyConsumerStats;
8862         }
8863 
8864         /** Adds the given charge to the given standard power bucket for this uid. */
8865         @GuardedBy("mBsi")
addChargeToStandardBucketLocked(long chargeDeltaUC, @StandardPowerBucket int powerBucket, long timestampMs)8866         private void addChargeToStandardBucketLocked(long chargeDeltaUC,
8867                 @StandardPowerBucket int powerBucket, long timestampMs) {
8868             final EnergyConsumerStats energyConsumerStats =
8869                     getOrCreateEnergyConsumerStatsLocked();
8870             energyConsumerStats.updateStandardBucket(powerBucket, chargeDeltaUC, timestampMs);
8871         }
8872 
8873         /** Adds the given charge to the given custom power bucket for this uid. */
8874         @GuardedBy("mBsi")
addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket)8875         private void addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket) {
8876             getOrCreateEnergyConsumerStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC,
8877                     mBsi.mClock.elapsedRealtime());
8878         }
8879 
8880         /**
8881          * Returns the battery consumption (in microcoulomb) of this uid for a standard power bucket
8882          * of interest.
8883          * @param bucket standard power bucket of interest
8884          * @return consumption (in microcolombs) used by this uid for this power bucket
8885          */
8886         @GuardedBy("mBsi")
getEnergyConsumptionUC(@tandardPowerBucket int bucket)8887         public long getEnergyConsumptionUC(@StandardPowerBucket int bucket) {
8888             if (mBsi.mGlobalEnergyConsumerStats == null
8889                     || !mBsi.mGlobalEnergyConsumerStats.isStandardBucketSupported(bucket)) {
8890                 return POWER_DATA_UNAVAILABLE;
8891             }
8892             if (mUidEnergyConsumerStats == null) {
8893                 return 0L; // It is supported, but was never filled, so it must be 0
8894             }
8895             return mUidEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket);
8896         }
8897 
8898         /**
8899          * Returns the battery consumption (in microcoulombs) of this uid for a standard power
8900          * bucket and a process state, such as Uid.PROCESS_STATE_TOP.
8901          */
8902         @GuardedBy("mBsi")
getEnergyConsumptionUC(@tandardPowerBucket int bucket, int processState)8903         public long getEnergyConsumptionUC(@StandardPowerBucket int bucket,
8904                 int processState) {
8905             if (mBsi.mGlobalEnergyConsumerStats == null
8906                     || !mBsi.mGlobalEnergyConsumerStats.isStandardBucketSupported(bucket)) {
8907                 return POWER_DATA_UNAVAILABLE;
8908             }
8909             if (mUidEnergyConsumerStats == null) {
8910                 return 0L; // It is supported, but was never filled, so it must be 0
8911             }
8912             return mUidEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket, processState);
8913         }
8914 
8915         @GuardedBy("mBsi")
8916         @Override
getCustomEnergyConsumerBatteryConsumptionUC()8917         public long[] getCustomEnergyConsumerBatteryConsumptionUC() {
8918             if (mBsi.mGlobalEnergyConsumerStats == null) {
8919                 return null;
8920             }
8921             if (mUidEnergyConsumerStats == null) {
8922                 // Custom buckets may exist. But all values for this uid are 0 so we report all 0s.
8923                 return new long[mBsi.mGlobalEnergyConsumerStats.getNumberCustomPowerBuckets()];
8924             }
8925             return mUidEnergyConsumerStats.getAccumulatedCustomBucketCharges();
8926         }
8927 
8928         @GuardedBy("mBsi")
8929         @Override
getBluetoothEnergyConsumptionUC()8930         public long getBluetoothEnergyConsumptionUC() {
8931             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH);
8932         }
8933 
8934         @GuardedBy("mBsi")
8935         @Override
getBluetoothEnergyConsumptionUC( @atteryConsumer.ProcessState int processState)8936         public long getBluetoothEnergyConsumptionUC(
8937                 @BatteryConsumer.ProcessState int processState) {
8938             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
8939                     processState);
8940         }
8941 
8942         @GuardedBy("mBsi")
8943         @Override
getCpuEnergyConsumptionUC()8944         public long getCpuEnergyConsumptionUC() {
8945             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU);
8946         }
8947 
8948         @GuardedBy("mBsi")
8949         @Override
getCpuEnergyConsumptionUC( @atteryConsumer.ProcessState int processState)8950         public long getCpuEnergyConsumptionUC(
8951                 @BatteryConsumer.ProcessState int processState) {
8952             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU,
8953                     processState);
8954         }
8955 
8956         @GuardedBy("mBsi")
8957         @Override
getGnssEnergyConsumptionUC()8958         public long getGnssEnergyConsumptionUC() {
8959             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_GNSS);
8960         }
8961 
8962         @GuardedBy("mBsi")
8963         @Override
getMobileRadioEnergyConsumptionUC()8964         public long getMobileRadioEnergyConsumptionUC() {
8965             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
8966         }
8967 
8968         @GuardedBy("mBsi")
8969         @Override
getMobileRadioEnergyConsumptionUC(int processState)8970         public long getMobileRadioEnergyConsumptionUC(int processState) {
8971             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
8972                     processState);
8973         }
8974 
8975         @GuardedBy("mBsi")
8976         @Override
getScreenOnEnergyConsumptionUC()8977         public long getScreenOnEnergyConsumptionUC() {
8978             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON);
8979         }
8980 
8981         @GuardedBy("mBsi")
8982         @Override
getWifiEnergyConsumptionUC()8983         public long getWifiEnergyConsumptionUC() {
8984             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI);
8985         }
8986 
8987         @GuardedBy("mBsi")
8988         @Override
getWifiEnergyConsumptionUC(int processState)8989         public long getWifiEnergyConsumptionUC(int processState) {
8990             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI,
8991                     processState);
8992         }
8993 
8994         @GuardedBy("mBsi")
8995         @Override
getCameraEnergyConsumptionUC()8996         public long getCameraEnergyConsumptionUC() {
8997             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
8998         }
8999 
9000         /**
9001          * Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
9002          * since last marked. Also sets the mark time for both these timers.
9003          *
9004          * @see CpuPowerCalculator
9005          *
9006          * @param doCalc if true, then calculate the minimum; else don't bother and return 0. Either
9007          *               way, the mark is set.
9008          */
markProcessForegroundTimeUs(long elapsedRealtimeMs, boolean doCalc)9009         private long markProcessForegroundTimeUs(long elapsedRealtimeMs,
9010                 boolean doCalc) {
9011             long fgTimeUs = 0;
9012             final StopwatchTimer fgTimer = mForegroundActivityTimer;
9013             if (fgTimer != null) {
9014                 if (doCalc) fgTimeUs = fgTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
9015                 fgTimer.setMark(elapsedRealtimeMs);
9016             }
9017 
9018             long topTimeUs = 0;
9019             final StopwatchTimer topTimer = mProcessStateTimer[PROCESS_STATE_TOP];
9020             if (topTimer != null) {
9021                 if (doCalc) topTimeUs = topTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
9022                 topTimer.setMark(elapsedRealtimeMs);
9023             }
9024 
9025             // Return the min of the two
9026             return (topTimeUs < fgTimeUs) ? topTimeUs : fgTimeUs;
9027         }
9028 
9029 
9030         /**
9031          * Gets the uid's time spent using the GNSS since last marked. Also sets the mark time for
9032          * the GNSS timer.
9033          */
markGnssTimeUs(long elapsedRealtimeMs)9034         private long markGnssTimeUs(long elapsedRealtimeMs) {
9035             final Sensor sensor = mSensorStats.get(Sensor.GPS);
9036             if (sensor == null) {
9037                 return 0;
9038             }
9039 
9040             final StopwatchTimer timer = sensor.mTimer;
9041             if (timer == null) {
9042                 return 0;
9043             }
9044 
9045             final long gnssTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
9046             timer.setMark(elapsedRealtimeMs);
9047             return gnssTimeUs;
9048         }
9049 
9050         /**
9051          * Gets the uid's time spent using the camera since last marked. Also sets the mark time for
9052          * the camera timer.
9053          */
markCameraTimeUs(long elapsedRealtimeMs)9054         private long markCameraTimeUs(long elapsedRealtimeMs) {
9055             final StopwatchTimer timer = mCameraTurnedOnTimer;
9056             if (timer == null) {
9057                 return 0;
9058             }
9059             final long cameraTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
9060             timer.setMark(elapsedRealtimeMs);
9061             return cameraTimeUs;
9062         }
9063 
createAudioTurnedOnTimerLocked()9064         public StopwatchTimer createAudioTurnedOnTimerLocked() {
9065             if (mAudioTurnedOnTimer == null) {
9066                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, AUDIO_TURNED_ON,
9067                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9068             }
9069             return mAudioTurnedOnTimer;
9070         }
9071 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)9072         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
9073             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9074         }
9075 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)9076         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
9077             if (mAudioTurnedOnTimer != null) {
9078                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9079             }
9080         }
9081 
noteResetAudioLocked(long elapsedRealtimeMs)9082         public void noteResetAudioLocked(long elapsedRealtimeMs) {
9083             if (mAudioTurnedOnTimer != null) {
9084                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9085             }
9086         }
9087 
createVideoTurnedOnTimerLocked()9088         public StopwatchTimer createVideoTurnedOnTimerLocked() {
9089             if (mVideoTurnedOnTimer == null) {
9090                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, VIDEO_TURNED_ON,
9091                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9092             }
9093             return mVideoTurnedOnTimer;
9094         }
9095 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)9096         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
9097             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9098         }
9099 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)9100         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
9101             if (mVideoTurnedOnTimer != null) {
9102                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9103             }
9104         }
9105 
noteResetVideoLocked(long elapsedRealtimeMs)9106         public void noteResetVideoLocked(long elapsedRealtimeMs) {
9107             if (mVideoTurnedOnTimer != null) {
9108                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9109             }
9110         }
9111 
createFlashlightTurnedOnTimerLocked()9112         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
9113             if (mFlashlightTurnedOnTimer == null) {
9114                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9115                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9116             }
9117             return mFlashlightTurnedOnTimer;
9118         }
9119 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)9120         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
9121             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9122         }
9123 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)9124         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
9125             if (mFlashlightTurnedOnTimer != null) {
9126                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9127             }
9128         }
9129 
noteResetFlashlightLocked(long elapsedRealtimeMs)9130         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
9131             if (mFlashlightTurnedOnTimer != null) {
9132                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9133             }
9134         }
9135 
createCameraTurnedOnTimerLocked()9136         public StopwatchTimer createCameraTurnedOnTimerLocked() {
9137             if (mCameraTurnedOnTimer == null) {
9138                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, CAMERA_TURNED_ON,
9139                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9140             }
9141             return mCameraTurnedOnTimer;
9142         }
9143 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)9144         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
9145             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9146         }
9147 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)9148         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
9149             if (mCameraTurnedOnTimer != null) {
9150                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9151             }
9152         }
9153 
noteResetCameraLocked(long elapsedRealtimeMs)9154         public void noteResetCameraLocked(long elapsedRealtimeMs) {
9155             if (mCameraTurnedOnTimer != null) {
9156                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9157             }
9158         }
9159 
createForegroundActivityTimerLocked()9160         public StopwatchTimer createForegroundActivityTimerLocked() {
9161             if (mForegroundActivityTimer == null) {
9162                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9163                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
9164             }
9165             return mForegroundActivityTimer;
9166         }
9167 
createForegroundServiceTimerLocked()9168         public StopwatchTimer createForegroundServiceTimerLocked() {
9169             if (mForegroundServiceTimer == null) {
9170                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9171                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
9172             }
9173             return mForegroundServiceTimer;
9174         }
9175 
createAggregatedPartialWakelockTimerLocked()9176         public DualTimer createAggregatedPartialWakelockTimerLocked() {
9177             if (mAggregatedPartialWakelockTimer == null) {
9178                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClock, this,
9179                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
9180                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
9181             }
9182             return mAggregatedPartialWakelockTimer;
9183         }
9184 
createBluetoothScanTimerLocked()9185         public DualTimer createBluetoothScanTimerLocked() {
9186             if (mBluetoothScanTimer == null) {
9187                 mBluetoothScanTimer = new DualTimer(mBsi.mClock, Uid.this, BLUETOOTH_SCAN_ON,
9188                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
9189                         mOnBatteryBackgroundTimeBase);
9190             }
9191             return mBluetoothScanTimer;
9192         }
9193 
createBluetoothUnoptimizedScanTimerLocked()9194         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
9195             if (mBluetoothUnoptimizedScanTimer == null) {
9196                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClock, Uid.this,
9197                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
9198                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
9199             }
9200             return mBluetoothUnoptimizedScanTimer;
9201         }
9202 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)9203         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
9204                 boolean isUnoptimized) {
9205             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
9206             if (isUnoptimized) {
9207                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
9208             }
9209         }
9210 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)9211         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
9212             if (mBluetoothScanTimer != null) {
9213                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
9214             }
9215             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
9216                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
9217             }
9218         }
9219 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)9220         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
9221             if (mBluetoothScanTimer != null) {
9222                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
9223             }
9224             if (mBluetoothUnoptimizedScanTimer != null) {
9225                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
9226             }
9227         }
9228 
createBluetoothScanResultCounterLocked()9229         public Counter createBluetoothScanResultCounterLocked() {
9230             if (mBluetoothScanResultCounter == null) {
9231                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
9232             }
9233             return mBluetoothScanResultCounter;
9234         }
9235 
createBluetoothScanResultBgCounterLocked()9236         public Counter createBluetoothScanResultBgCounterLocked() {
9237             if (mBluetoothScanResultBgCounter == null) {
9238                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
9239             }
9240             return mBluetoothScanResultBgCounter;
9241         }
9242 
noteBluetoothScanResultsLocked(int numNewResults)9243         public void noteBluetoothScanResultsLocked(int numNewResults) {
9244             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
9245             // Uses background timebase, so the count will only be incremented if uid in background.
9246             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
9247         }
9248 
9249         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)9250         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
9251             // We always start, since we want multiple foreground PIDs to nest
9252             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
9253         }
9254 
9255         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)9256         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
9257             if (mForegroundActivityTimer != null) {
9258                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
9259             }
9260         }
9261 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)9262         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
9263             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
9264         }
9265 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)9266         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
9267             if (mForegroundServiceTimer != null) {
9268                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
9269             }
9270         }
9271 
createVibratorOnTimerLocked()9272         public BatchTimer createVibratorOnTimerLocked() {
9273             if (mVibratorOnTimer == null) {
9274                 mVibratorOnTimer = new BatchTimer(mBsi.mClock, Uid.this, VIBRATOR_ON,
9275                         mBsi.mOnBatteryTimeBase);
9276             }
9277             return mVibratorOnTimer;
9278         }
9279 
noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs)9280         public void noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs) {
9281             createVibratorOnTimerLocked().addDuration(durationMillis, elapsedRealtimeMs);
9282         }
9283 
noteVibratorOffLocked(long elapsedRealtimeMs)9284         public void noteVibratorOffLocked(long elapsedRealtimeMs) {
9285             if (mVibratorOnTimer != null) {
9286                 mVibratorOnTimer.abortLastDuration(elapsedRealtimeMs);
9287             }
9288         }
9289 
9290         @Override
getWifiRunningTime(long elapsedRealtimeUs, int which)9291         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
9292             if (mWifiRunningTimer == null) {
9293                 return 0;
9294             }
9295             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9296         }
9297 
9298         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)9299         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
9300             if (mFullWifiLockTimer == null) {
9301                 return 0;
9302             }
9303             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9304         }
9305 
9306         @Override
getWifiScanTime(long elapsedRealtimeUs, int which)9307         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
9308             if (mWifiScanTimer == null) {
9309                 return 0;
9310             }
9311             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9312         }
9313 
9314         @Override
getWifiScanCount(int which)9315         public int getWifiScanCount(int which) {
9316             if (mWifiScanTimer == null) {
9317                 return 0;
9318             }
9319             return mWifiScanTimer.getCountLocked(which);
9320         }
9321 
9322         @Override
getWifiScanTimer()9323         public Timer getWifiScanTimer() {
9324             return mWifiScanTimer;
9325         }
9326 
9327         @Override
getWifiScanBackgroundCount(int which)9328         public int getWifiScanBackgroundCount(int which) {
9329             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
9330                 return 0;
9331             }
9332             return mWifiScanTimer.getSubTimer().getCountLocked(which);
9333         }
9334 
9335         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)9336         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
9337             if (mWifiScanTimer == null) {
9338                 return 0;
9339             }
9340             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
9341             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
9342         }
9343 
9344         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)9345         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
9346             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
9347                 return 0;
9348             }
9349             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
9350             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
9351         }
9352 
9353         @Override
getWifiScanBackgroundTimer()9354         public Timer getWifiScanBackgroundTimer() {
9355             if (mWifiScanTimer == null) {
9356                 return null;
9357             }
9358             return mWifiScanTimer.getSubTimer();
9359         }
9360 
9361         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)9362         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
9363             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
9364             if (mWifiBatchedScanTimer[csphBin] == null) {
9365                 return 0;
9366             }
9367             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
9368         }
9369 
9370         @Override
getWifiBatchedScanCount(int csphBin, int which)9371         public int getWifiBatchedScanCount(int csphBin, int which) {
9372             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
9373             if (mWifiBatchedScanTimer[csphBin] == null) {
9374                 return 0;
9375             }
9376             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
9377         }
9378 
9379         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)9380         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
9381             if (mWifiMulticastTimer == null) {
9382                 return 0;
9383             }
9384             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9385         }
9386 
9387         @Override
getAudioTurnedOnTimer()9388         public Timer getAudioTurnedOnTimer() {
9389             return mAudioTurnedOnTimer;
9390         }
9391 
9392         @Override
getVideoTurnedOnTimer()9393         public Timer getVideoTurnedOnTimer() {
9394             return mVideoTurnedOnTimer;
9395         }
9396 
9397         @Override
getFlashlightTurnedOnTimer()9398         public Timer getFlashlightTurnedOnTimer() {
9399             return mFlashlightTurnedOnTimer;
9400         }
9401 
9402         @Override
getCameraTurnedOnTimer()9403         public Timer getCameraTurnedOnTimer() {
9404             return mCameraTurnedOnTimer;
9405         }
9406 
9407         @Override
getForegroundActivityTimer()9408         public Timer getForegroundActivityTimer() {
9409             return mForegroundActivityTimer;
9410         }
9411 
9412         @Override
getForegroundServiceTimer()9413         public Timer getForegroundServiceTimer() {
9414             return mForegroundServiceTimer;
9415         }
9416 
9417         @Override
getBluetoothScanTimer()9418         public Timer getBluetoothScanTimer() {
9419             return mBluetoothScanTimer;
9420         }
9421 
9422         @Override
getBluetoothScanBackgroundTimer()9423         public Timer getBluetoothScanBackgroundTimer() {
9424             if (mBluetoothScanTimer == null) {
9425                 return null;
9426             }
9427             return mBluetoothScanTimer.getSubTimer();
9428         }
9429 
9430         @Override
getBluetoothUnoptimizedScanTimer()9431         public Timer getBluetoothUnoptimizedScanTimer() {
9432             return mBluetoothUnoptimizedScanTimer;
9433         }
9434 
9435         @Override
getBluetoothUnoptimizedScanBackgroundTimer()9436         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
9437             if (mBluetoothUnoptimizedScanTimer == null) {
9438                 return null;
9439             }
9440             return mBluetoothUnoptimizedScanTimer.getSubTimer();
9441         }
9442 
9443         @Override
getBluetoothScanResultCounter()9444         public Counter getBluetoothScanResultCounter() {
9445             return mBluetoothScanResultCounter;
9446         }
9447 
9448         @Override
getBluetoothScanResultBgCounter()9449         public Counter getBluetoothScanResultBgCounter() {
9450             return mBluetoothScanResultBgCounter;
9451         }
9452 
makeProcessState(int i, Parcel in)9453         void makeProcessState(int i, Parcel in) {
9454             if (i < 0 || i >= NUM_PROCESS_STATE) return;
9455 
9456             detachIfNotNull(mProcessStateTimer[i]);
9457             if (in == null) {
9458                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClock, this, PROCESS_STATE, null,
9459                         mBsi.mOnBatteryTimeBase);
9460             } else {
9461                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClock, this, PROCESS_STATE, null,
9462                         mBsi.mOnBatteryTimeBase, in);
9463             }
9464         }
9465 
9466         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)9467         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
9468             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
9469             if (mProcessStateTimer[state] == null) {
9470                 return 0;
9471             }
9472             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
9473         }
9474 
9475         @Override
getProcessStateTimer(int state)9476         public Timer getProcessStateTimer(int state) {
9477             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
9478             return mProcessStateTimer[state];
9479         }
9480 
9481         @Override
getVibratorOnTimer()9482         public Timer getVibratorOnTimer() {
9483             return mVibratorOnTimer;
9484         }
9485 
9486         @Override
noteUserActivityLocked(@owerManager.UserActivityEvent int event)9487         public void noteUserActivityLocked(@PowerManager.UserActivityEvent int event) {
9488             if (mUserActivityCounters == null) {
9489                 initUserActivityLocked();
9490             }
9491             if (event >= 0 && event < NUM_USER_ACTIVITY_TYPES) {
9492                 mUserActivityCounters[event].stepAtomic();
9493             } else {
9494                 Slog.w(TAG, "Unknown user activity type " + event + " was specified.",
9495                         new Throwable());
9496             }
9497         }
9498 
9499         @Override
hasUserActivity()9500         public boolean hasUserActivity() {
9501             return mUserActivityCounters != null;
9502         }
9503 
9504         @Override
getUserActivityCount(int type, int which)9505         public int getUserActivityCount(int type, int which) {
9506             if (mUserActivityCounters == null) {
9507                 return 0;
9508             }
9509             return mUserActivityCounters[type].getCountLocked(which);
9510         }
9511 
makeWifiBatchedScanBin(int i, Parcel in)9512         void makeWifiBatchedScanBin(int i, Parcel in) {
9513             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
9514 
9515             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
9516             if (collected == null) {
9517                 collected = new ArrayList<StopwatchTimer>();
9518                 mBsi.mWifiBatchedScanTimers.put(i, collected);
9519             }
9520             detachIfNotNull(mWifiBatchedScanTimer[i]);
9521             if (in == null) {
9522                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClock, this, WIFI_BATCHED_SCAN,
9523                         collected, mBsi.mOnBatteryTimeBase);
9524             } else {
9525                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClock, this, WIFI_BATCHED_SCAN,
9526                         collected, mBsi.mOnBatteryTimeBase, in);
9527             }
9528         }
9529 
9530 
initUserActivityLocked()9531         void initUserActivityLocked() {
9532             detachIfNotNull(mUserActivityCounters);
9533             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
9534             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
9535                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
9536             }
9537         }
9538 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)9539         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
9540             ensureNetworkActivityLocked();
9541             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
9542                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
9543                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
9544             } else {
9545                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
9546                         new Throwable());
9547             }
9548         }
9549 
noteMobileRadioActiveTimeLocked(long batteryUptimeDeltaUs, long elapsedTimeMs)9550         void noteMobileRadioActiveTimeLocked(long batteryUptimeDeltaUs, long elapsedTimeMs) {
9551             ensureNetworkActivityLocked();
9552             getMobileRadioActiveTimeCounter().increment(batteryUptimeDeltaUs, elapsedTimeMs);
9553             mMobileRadioActiveCount.addCountLocked(1);
9554         }
9555 
getMobileRadioActiveTimeCounter()9556         private TimeMultiStateCounter getMobileRadioActiveTimeCounter() {
9557             if (mMobileRadioActiveTime == null) {
9558                 final long timestampMs = mBsi.mClock.elapsedRealtime();
9559                 mMobileRadioActiveTime = new TimeMultiStateCounter(
9560                         mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
9561                 mMobileRadioActiveTime.setState(
9562                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
9563                         timestampMs);
9564                 mMobileRadioActiveTime.update(0, timestampMs);
9565             }
9566             return mMobileRadioActiveTime;
9567         }
9568 
9569         @Override
hasNetworkActivity()9570         public boolean hasNetworkActivity() {
9571             return mNetworkByteActivityCounters != null;
9572         }
9573 
9574         @Override
getNetworkActivityBytes(int type, int which)9575         public long getNetworkActivityBytes(int type, int which) {
9576             if (mNetworkByteActivityCounters != null && type >= 0
9577                     && type < mNetworkByteActivityCounters.length) {
9578                 return mNetworkByteActivityCounters[type].getCountLocked(which);
9579             } else {
9580                 return 0;
9581             }
9582         }
9583 
9584         @Override
getNetworkActivityPackets(int type, int which)9585         public long getNetworkActivityPackets(int type, int which) {
9586             if (mNetworkPacketActivityCounters != null && type >= 0
9587                     && type < mNetworkPacketActivityCounters.length) {
9588                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
9589             } else {
9590                 return 0;
9591             }
9592         }
9593 
9594         @Override
getMobileRadioActiveTime(int which)9595         public long getMobileRadioActiveTime(int which) {
9596             return getMobileRadioActiveTimeInProcessState(BatteryConsumer.PROCESS_STATE_ANY);
9597         }
9598 
9599         @Override
getMobileRadioActiveTimeInProcessState( @atteryConsumer.ProcessState int processState)9600         public long getMobileRadioActiveTimeInProcessState(
9601                 @BatteryConsumer.ProcessState int processState) {
9602             if (mMobileRadioActiveTime == null) {
9603                 return 0;
9604             }
9605             if (processState == BatteryConsumer.PROCESS_STATE_ANY) {
9606                 return mMobileRadioActiveTime.getTotalCountLocked();
9607             } else {
9608                 return mMobileRadioActiveTime.getCountForProcessState(processState);
9609             }
9610         }
9611 
9612         @Override
getMobileRadioActiveCount(int which)9613         public int getMobileRadioActiveCount(int which) {
9614             return mMobileRadioActiveCount != null
9615                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
9616         }
9617 
9618         @Override
getUserCpuTimeUs(int which)9619         public long getUserCpuTimeUs(int which) {
9620             return mUserCpuTime.getCountLocked(which);
9621         }
9622 
9623         @Override
getSystemCpuTimeUs(int which)9624         public long getSystemCpuTimeUs(int which) {
9625             return mSystemCpuTime.getCountLocked(which);
9626         }
9627 
9628         @Override
9629         @Deprecated
getTimeAtCpuSpeed(int cluster, int step, int which)9630         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
9631             if (mCpuClusterSpeedTimesUs != null) {
9632                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
9633                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
9634                     if (cpuSpeedTimesUs != null) {
9635                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
9636                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
9637                             if (c != null) {
9638                                 return c.getCountLocked(which);
9639                             }
9640                         }
9641                     }
9642                 }
9643             }
9644             return 0;
9645         }
9646 
noteMobileRadioApWakeupLocked()9647         public void noteMobileRadioApWakeupLocked() {
9648             if (mMobileRadioApWakeupCount == null) {
9649                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9650             }
9651             mMobileRadioApWakeupCount.addCountLocked(1);
9652         }
9653 
9654         @Override
getMobileRadioApWakeupCount(int which)9655         public long getMobileRadioApWakeupCount(int which) {
9656             if (mMobileRadioApWakeupCount != null) {
9657                 return mMobileRadioApWakeupCount.getCountLocked(which);
9658             }
9659             return 0;
9660         }
9661 
noteWifiRadioApWakeupLocked()9662         public void noteWifiRadioApWakeupLocked() {
9663             if (mWifiRadioApWakeupCount == null) {
9664                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9665             }
9666             mWifiRadioApWakeupCount.addCountLocked(1);
9667         }
9668 
9669         @Override
getWifiRadioApWakeupCount(int which)9670         public long getWifiRadioApWakeupCount(int which) {
9671             if (mWifiRadioApWakeupCount != null) {
9672                 return mWifiRadioApWakeupCount.getCountLocked(which);
9673             }
9674             return 0;
9675         }
9676 
9677         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)9678         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
9679             sb.setLength(0);
9680             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
9681             if (deferredEventCount == 0) {
9682                 return;
9683             }
9684             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
9685             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
9686             sb.append(deferredEventCount); sb.append(',');
9687             sb.append(deferredCount); sb.append(',');
9688             sb.append(totalLatency);
9689             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9690                 if (mJobsFreshnessBuckets[i] == null) {
9691                     sb.append(",0");
9692                 } else {
9693                     sb.append(",");
9694                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
9695                 }
9696             }
9697         }
9698 
9699         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)9700         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
9701             sb.setLength(0);
9702             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
9703             if (deferredEventCount == 0) {
9704                 return;
9705             }
9706             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
9707             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
9708             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
9709             sb.append("count="); sb.append(deferredCount); sb.append(", ");
9710             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
9711             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9712                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
9713                 if (mJobsFreshnessBuckets[i] == null) {
9714                     sb.append("0");
9715                 } else {
9716                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
9717                 }
9718                 sb.append(" ");
9719             }
9720         }
9721 
ensureNetworkActivityLocked()9722         void ensureNetworkActivityLocked() {
9723             if (mNetworkByteActivityCounters != null) {
9724                 return;
9725             }
9726 
9727             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9728             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9729             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9730                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9731                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9732             }
9733             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9734         }
9735 
9736         /**
9737          * Clear all stats for this uid.  Returns true if the uid is completely
9738          * inactive so can be dropped.
9739          */
9740         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptimeUs, long realtimeUs, int resetReason)9741         public boolean reset(long uptimeUs, long realtimeUs, int resetReason) {
9742             boolean active = false;
9743 
9744             mOnBatteryBackgroundTimeBase.init(uptimeUs, realtimeUs);
9745             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeUs, realtimeUs);
9746 
9747             if (mWifiRunningTimer != null) {
9748                 active |= !mWifiRunningTimer.reset(false, realtimeUs);
9749                 active |= mWifiRunning;
9750             }
9751             if (mFullWifiLockTimer != null) {
9752                 active |= !mFullWifiLockTimer.reset(false, realtimeUs);
9753                 active |= mFullWifiLockOut;
9754             }
9755             if (mWifiScanTimer != null) {
9756                 active |= !mWifiScanTimer.reset(false, realtimeUs);
9757                 active |= mWifiScanStarted;
9758             }
9759             if (mWifiBatchedScanTimer != null) {
9760                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9761                     if (mWifiBatchedScanTimer[i] != null) {
9762                         active |= !mWifiBatchedScanTimer[i].reset(false, realtimeUs);
9763                     }
9764                 }
9765                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
9766             }
9767             if (mWifiMulticastTimer != null) {
9768                 active |= !mWifiMulticastTimer.reset(false, realtimeUs);
9769                 active |= (mWifiMulticastWakelockCount > 0);
9770             }
9771 
9772             active |= !resetIfNotNull(mAudioTurnedOnTimer, false, realtimeUs);
9773             active |= !resetIfNotNull(mVideoTurnedOnTimer, false, realtimeUs);
9774             active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false, realtimeUs);
9775             active |= !resetIfNotNull(mCameraTurnedOnTimer, false, realtimeUs);
9776             active |= !resetIfNotNull(mForegroundActivityTimer, false, realtimeUs);
9777             active |= !resetIfNotNull(mForegroundServiceTimer, false, realtimeUs);
9778             active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false, realtimeUs);
9779             active |= !resetIfNotNull(mBluetoothScanTimer, false, realtimeUs);
9780             active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false, realtimeUs);
9781 
9782             resetIfNotNull(mBluetoothScanResultCounter, false, realtimeUs);
9783             resetIfNotNull(mBluetoothScanResultBgCounter, false, realtimeUs);
9784 
9785             if (mProcessStateTimer != null) {
9786                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
9787                     active |= !resetIfNotNull(mProcessStateTimer[i], false, realtimeUs);
9788                 }
9789                 active |= (mProcessState != Uid.PROCESS_STATE_NONEXISTENT);
9790             }
9791             if (mVibratorOnTimer != null) {
9792                 if (mVibratorOnTimer.reset(false, realtimeUs)) {
9793                     mVibratorOnTimer.detach();
9794                     mVibratorOnTimer = null;
9795                 } else {
9796                     active = true;
9797                 }
9798             }
9799 
9800             resetIfNotNull(mUserActivityCounters, false, realtimeUs);
9801 
9802             resetIfNotNull(mNetworkByteActivityCounters, false, realtimeUs);
9803             resetIfNotNull(mNetworkPacketActivityCounters, false, realtimeUs);
9804             resetIfNotNull(mMobileRadioActiveTime, false, realtimeUs);
9805             resetIfNotNull(mMobileRadioActiveCount, false, realtimeUs);
9806 
9807             resetIfNotNull(mWifiControllerActivity, false, realtimeUs);
9808             resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs);
9809             resetIfNotNull(mModemControllerActivity, false, realtimeUs);
9810 
9811             if (resetReason == RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE) {
9812                 mUidEnergyConsumerStats = null;
9813             } else {
9814                 EnergyConsumerStats.resetIfNotNull(mUidEnergyConsumerStats);
9815             }
9816 
9817             resetIfNotNull(mUserCpuTime, false, realtimeUs);
9818             resetIfNotNull(mSystemCpuTime, false, realtimeUs);
9819 
9820             resetIfNotNull(mCpuClusterSpeedTimesUs, false, realtimeUs);
9821 
9822             resetIfNotNull(mCpuFreqTimeMs, false, realtimeUs /* unused */);
9823             resetIfNotNull(mScreenOffCpuFreqTimeMs, false, realtimeUs /* unused */);
9824 
9825 
9826             resetIfNotNull(mCpuActiveTimeMs, false, realtimeUs /* unused */);
9827             resetIfNotNull(mCpuClusterTimesMs, false, realtimeUs /* unused */);
9828 
9829             resetIfNotNull(mProcStateTimeMs, false, realtimeUs /* unused */);
9830 
9831             resetIfNotNull(mProcStateScreenOffTimeMs, false, realtimeUs /* unused */);
9832 
9833             resetIfNotNull(mMobileRadioApWakeupCount, false, realtimeUs);
9834 
9835             resetIfNotNull(mWifiRadioApWakeupCount, false, realtimeUs);
9836 
9837 
9838             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9839             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
9840                 Wakelock wl = wakeStats.valueAt(iw);
9841                 if (wl.reset(realtimeUs)) {
9842                     wakeStats.removeAt(iw);
9843                 } else {
9844                     active = true;
9845                 }
9846             }
9847             final long realtimeMs = realtimeUs / 1000;
9848             mWakelockStats.cleanup(realtimeMs);
9849             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9850             for (int is=syncStats.size()-1; is>=0; is--) {
9851                 DualTimer timer = syncStats.valueAt(is);
9852                 if (timer.reset(false, realtimeUs)) {
9853                     syncStats.removeAt(is);
9854                     timer.detach();
9855                 } else {
9856                     active = true;
9857                 }
9858             }
9859             mSyncStats.cleanup(realtimeMs);
9860             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9861             for (int ij=jobStats.size()-1; ij>=0; ij--) {
9862                 DualTimer timer = jobStats.valueAt(ij);
9863                 if (timer.reset(false, realtimeUs)) {
9864                     jobStats.removeAt(ij);
9865                     timer.detach();
9866                 } else {
9867                     active = true;
9868                 }
9869             }
9870             mJobStats.cleanup(realtimeMs);
9871             mJobCompletions.clear();
9872 
9873             resetIfNotNull(mJobsDeferredEventCount, false, realtimeUs);
9874             resetIfNotNull(mJobsDeferredCount, false, realtimeUs);
9875             resetIfNotNull(mJobsFreshnessTimeMs, false, realtimeUs /* unused */);
9876             resetIfNotNull(mJobsFreshnessBuckets, false, realtimeUs);
9877 
9878             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
9879                 Sensor s = mSensorStats.valueAt(ise);
9880                 if (s.reset(realtimeUs)) {
9881                     mSensorStats.removeAt(ise);
9882                 } else {
9883                     active = true;
9884                 }
9885             }
9886 
9887             for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
9888                 Proc proc = mProcessStats.valueAt(ip);
9889                 proc.detach();
9890             }
9891             mProcessStats.clear();
9892 
9893             for (int i = mPids.size() - 1; i >= 0; i--) {
9894                 Pid pid = mPids.valueAt(i);
9895                 if (pid.mWakeNesting > 0) {
9896                     active = true;
9897                 } else {
9898                     mPids.removeAt(i);
9899                 }
9900             }
9901 
9902 
9903             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
9904                 Pkg p = mPackageStats.valueAt(i);
9905                 p.detach();
9906             }
9907             mPackageStats.clear();
9908 
9909             mBinderCallCount = 0;
9910             mBinderCallStats.clear();
9911 
9912             mProportionalSystemServiceUsage = 0;
9913 
9914             mLastStepUserTimeMs = mLastStepSystemTimeMs = 0;
9915             mCurStepUserTimeMs = mCurStepSystemTimeMs = 0;
9916 
9917 
9918             return !active;
9919         }
9920 
9921         /**
9922          * This method MUST be called whenever the Uid object is destructed, otherwise it is a
9923          * memory leak in {@link TimeBase#mObservers} list.
9924          * Typically the Uid object is destructed when it is removed from
9925          * {@link BatteryStatsImpl#mUidStats}
9926          */
detachFromTimeBase()9927         void detachFromTimeBase() {
9928             detachIfNotNull(mWifiRunningTimer);
9929             detachIfNotNull(mFullWifiLockTimer);
9930             detachIfNotNull(mWifiScanTimer);
9931             detachIfNotNull(mWifiBatchedScanTimer);
9932             detachIfNotNull(mWifiMulticastTimer);
9933             detachIfNotNull(mAudioTurnedOnTimer);
9934             detachIfNotNull(mVideoTurnedOnTimer);
9935             detachIfNotNull(mFlashlightTurnedOnTimer);
9936 
9937             detachIfNotNull(mCameraTurnedOnTimer);
9938             detachIfNotNull(mForegroundActivityTimer);
9939             detachIfNotNull(mForegroundServiceTimer);
9940 
9941             detachIfNotNull(mAggregatedPartialWakelockTimer);
9942 
9943             detachIfNotNull(mBluetoothScanTimer);
9944             detachIfNotNull(mBluetoothUnoptimizedScanTimer);
9945             detachIfNotNull(mBluetoothScanResultCounter);
9946             detachIfNotNull(mBluetoothScanResultBgCounter);
9947 
9948             detachIfNotNull(mProcessStateTimer);
9949 
9950             detachIfNotNull(mVibratorOnTimer);
9951 
9952             detachIfNotNull(mUserActivityCounters);
9953 
9954             detachIfNotNull(mNetworkByteActivityCounters);
9955             detachIfNotNull(mNetworkPacketActivityCounters);
9956 
9957             detachIfNotNull(mMobileRadioActiveTime);
9958             detachIfNotNull(mMobileRadioActiveCount);
9959             detachIfNotNull(mMobileRadioApWakeupCount);
9960             detachIfNotNull(mWifiRadioApWakeupCount);
9961 
9962             detachIfNotNull(mWifiControllerActivity);
9963             detachIfNotNull(mBluetoothControllerActivity);
9964             detachIfNotNull(mModemControllerActivity);
9965 
9966             mPids.clear();
9967 
9968             detachIfNotNull(mUserCpuTime);
9969             detachIfNotNull(mSystemCpuTime);
9970 
9971             detachIfNotNull(mCpuClusterSpeedTimesUs);
9972 
9973             detachIfNotNull(mCpuActiveTimeMs);
9974             detachIfNotNull(mCpuFreqTimeMs);
9975 
9976             detachIfNotNull(mScreenOffCpuFreqTimeMs);
9977 
9978             detachIfNotNull(mCpuClusterTimesMs);
9979 
9980             detachIfNotNull(mProcStateTimeMs);
9981 
9982             detachIfNotNull(mProcStateScreenOffTimeMs);
9983 
9984             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9985             for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
9986                 Wakelock wl = wakeStats.valueAt(iw);
9987                 wl.detachFromTimeBase();
9988             }
9989             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9990             for (int is = syncStats.size() - 1; is >= 0; is--) {
9991                 DualTimer timer = syncStats.valueAt(is);
9992                 detachIfNotNull(timer);
9993             }
9994             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9995             for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
9996                 DualTimer timer = jobStats.valueAt(ij);
9997                 detachIfNotNull(timer);
9998             }
9999 
10000             detachIfNotNull(mJobsDeferredEventCount);
10001             detachIfNotNull(mJobsDeferredCount);
10002             detachIfNotNull(mJobsFreshnessTimeMs);
10003             detachIfNotNull(mJobsFreshnessBuckets);
10004 
10005 
10006             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
10007                 Sensor s = mSensorStats.valueAt(ise);
10008                 s.detachFromTimeBase();
10009             }
10010 
10011             for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
10012                 Proc proc = mProcessStats.valueAt(ip);
10013                 proc.detach();
10014             }
10015             mProcessStats.clear();
10016 
10017             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
10018                 Pkg p = mPackageStats.valueAt(i);
10019                 p.detach();
10020             }
10021             mPackageStats.clear();
10022         }
10023 
writeJobCompletionsToParcelLocked(Parcel out)10024         void writeJobCompletionsToParcelLocked(Parcel out) {
10025             int NJC = mJobCompletions.size();
10026             out.writeInt(NJC);
10027             for (int ijc=0; ijc<NJC; ijc++) {
10028                 out.writeString(mJobCompletions.keyAt(ijc));
10029                 SparseIntArray types = mJobCompletions.valueAt(ijc);
10030                 int NT = types.size();
10031                 out.writeInt(NT);
10032                 for (int it=0; it<NT; it++) {
10033                     out.writeInt(types.keyAt(it));
10034                     out.writeInt(types.valueAt(it));
10035                 }
10036             }
10037         }
10038 
readJobCompletionsFromParcelLocked(Parcel in)10039         void readJobCompletionsFromParcelLocked(Parcel in) {
10040             int numJobCompletions = in.readInt();
10041             mJobCompletions.clear();
10042             for (int j = 0; j < numJobCompletions; j++) {
10043                 String jobName = in.readString();
10044                 int numTypes = in.readInt();
10045                 if (numTypes > 0) {
10046                     SparseIntArray types = new SparseIntArray();
10047                     for (int k = 0; k < numTypes; k++) {
10048                         int type = in.readInt();
10049                         int count = in.readInt();
10050                         types.put(type, count);
10051                     }
10052                     mJobCompletions.put(jobName, types);
10053                 }
10054             }
10055         }
10056 
noteJobsDeferredLocked(int numDeferred, long sinceLast)10057         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
10058             mJobsDeferredEventCount.addAtomic(1);
10059             mJobsDeferredCount.addAtomic(numDeferred);
10060             if (sinceLast != 0) {
10061                 // Add the total time, which can be divided by the event count to get an average
10062                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
10063                 // Also keep track of how many times there were in these different buckets.
10064                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
10065                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
10066                         if (mJobsFreshnessBuckets[i] == null) {
10067                             mJobsFreshnessBuckets[i] = new Counter(
10068                                     mBsi.mOnBatteryTimeBase);
10069                         }
10070                         mJobsFreshnessBuckets[i].addAtomic(1);
10071                         break;
10072                     }
10073                 }
10074             }
10075         }
10076 
10077         // Reusable object used as a key to lookup values in mBinderCallStats
10078         private static BinderCallStats sTempBinderCallStats = new BinderCallStats();
10079 
10080         /**
10081          * Notes incoming binder call stats associated with this work source UID.
10082          */
noteBinderCallStatsLocked(long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)10083         public void noteBinderCallStatsLocked(long incrementalCallCount,
10084                 Collection<BinderCallsStats.CallStat> callStats) {
10085             if (DEBUG) {
10086                 Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], "
10087                         + " incrementalCallCount: " + incrementalCallCount + " callStats = ["
10088                         + new ArrayList<>(callStats) + "]");
10089             }
10090             mBinderCallCount += incrementalCallCount;
10091             for (BinderCallsStats.CallStat stat : callStats) {
10092                 BinderCallStats bcs;
10093                 sTempBinderCallStats.binderClass = stat.binderClass;
10094                 sTempBinderCallStats.transactionCode = stat.transactionCode;
10095                 int index = mBinderCallStats.indexOf(sTempBinderCallStats);
10096                 if (index >= 0) {
10097                     bcs = mBinderCallStats.valueAt(index);
10098                 } else {
10099                     bcs = new BinderCallStats();
10100                     bcs.binderClass = stat.binderClass;
10101                     bcs.transactionCode = stat.transactionCode;
10102                     mBinderCallStats.add(bcs);
10103                 }
10104 
10105                 bcs.callCount += stat.incrementalCallCount;
10106                 bcs.recordedCallCount = stat.recordedCallCount;
10107                 bcs.recordedCpuTimeMicros = stat.cpuTimeMicros;
10108             }
10109         }
10110 
10111         /**
10112          * The statistics associated with a particular wake lock.
10113          */
10114         public static class Wakelock extends BatteryStats.Uid.Wakelock {
10115             /**
10116              * BatteryStatsImpl that we are associated with.
10117              */
10118             protected BatteryStatsImpl mBsi;
10119 
10120             /**
10121              * BatteryStatsImpl that we are associated with.
10122              */
10123             protected Uid mUid;
10124 
10125             /**
10126              * How long (in ms) this uid has been keeping the device partially awake.
10127              * Tracks both the total time and the time while the app was in the background.
10128              */
10129             DualTimer mTimerPartial;
10130 
10131             /**
10132              * How long (in ms) this uid has been keeping the device fully awake.
10133              */
10134             StopwatchTimer mTimerFull;
10135 
10136             /**
10137              * How long (in ms) this uid has had a window keeping the device awake.
10138              */
10139             StopwatchTimer mTimerWindow;
10140 
10141             /**
10142              * How long (in ms) this uid has had a draw wake lock.
10143              */
10144             StopwatchTimer mTimerDraw;
10145 
Wakelock(BatteryStatsImpl bsi, Uid uid)10146             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
10147                 mBsi = bsi;
10148                 mUid = uid;
10149             }
10150 
10151             /**
10152              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
10153              * proper timer pool from the given BatteryStatsImpl object.
10154              *
10155              * @param in the Parcel to be read from.
10156              * return a new Timer, or null.
10157              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)10158             private StopwatchTimer readStopwatchTimerFromParcel(int type,
10159                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
10160                 if (in.readInt() == 0) {
10161                     return null;
10162                 }
10163 
10164                 return new StopwatchTimer(mBsi.mClock, mUid, type, pool, timeBase, in);
10165             }
10166 
10167             /**
10168              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
10169              * proper timer pool from the given BatteryStatsImpl object.
10170              *
10171              * @param in the Parcel to be read from.
10172              * return a new Timer, or null.
10173              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10174             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
10175                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10176                 if (in.readInt() == 0) {
10177                     return null;
10178                 }
10179 
10180                 return new DualTimer(mBsi.mClock, mUid, type, pool, timeBase, bgTimeBase, in);
10181             }
10182 
reset(long elapsedRealtimeUs)10183             boolean reset(long elapsedRealtimeUs) {
10184                 boolean wlactive = false;
10185 
10186                 wlactive |= !resetIfNotNull(mTimerFull, false, elapsedRealtimeUs);
10187                 wlactive |= !resetIfNotNull(mTimerPartial, false, elapsedRealtimeUs);
10188                 wlactive |= !resetIfNotNull(mTimerWindow, false, elapsedRealtimeUs);
10189                 wlactive |= !resetIfNotNull(mTimerDraw, false, elapsedRealtimeUs);
10190 
10191                 if (!wlactive) {
10192                     detachIfNotNull(mTimerFull);
10193                     mTimerFull = null;
10194 
10195                     detachIfNotNull(mTimerPartial);
10196                     mTimerPartial = null;
10197 
10198                     detachIfNotNull(mTimerWindow);
10199                     mTimerWindow = null;
10200 
10201                     detachIfNotNull(mTimerDraw);
10202                     mTimerDraw = null;
10203                 }
10204                 return !wlactive;
10205             }
10206 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)10207             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
10208                     TimeBase screenOffBgTimeBase, Parcel in) {
10209                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
10210                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
10211                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
10212                         mBsi.mFullTimers, timeBase, in);
10213                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
10214                         mBsi.mWindowTimers, timeBase, in);
10215                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
10216                         mBsi.mDrawTimers, timeBase, in);
10217             }
10218 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)10219             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
10220                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
10221                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
10222                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
10223                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
10224             }
10225 
10226             @Override
getWakeTime(int type)10227             public Timer getWakeTime(int type) {
10228                 switch (type) {
10229                 case WAKE_TYPE_FULL: return mTimerFull;
10230                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
10231                 case WAKE_TYPE_WINDOW: return mTimerWindow;
10232                 case WAKE_TYPE_DRAW: return mTimerDraw;
10233                 default: throw new IllegalArgumentException("type = " + type);
10234                 }
10235             }
10236 
detachFromTimeBase()10237             public void detachFromTimeBase() {
10238                 detachIfNotNull(mTimerPartial);
10239                 detachIfNotNull(mTimerFull);
10240                 detachIfNotNull(mTimerWindow);
10241                 detachIfNotNull(mTimerDraw);
10242             }
10243         }
10244 
10245         public static class Sensor extends BatteryStats.Uid.Sensor {
10246             /**
10247              * BatteryStatsImpl that we are associated with.
10248              */
10249             protected BatteryStatsImpl mBsi;
10250 
10251             /**
10252              * Uid that we are associated with.
10253              */
10254             protected Uid mUid;
10255 
10256             final int mHandle;
10257             DualTimer mTimer;
10258 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)10259             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
10260                 mBsi = bsi;
10261                 mUid = uid;
10262                 mHandle = handle;
10263             }
10264 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10265             private DualTimer readTimersFromParcel(
10266                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10267                 if (in.readInt() == 0) {
10268                     return null;
10269                 }
10270 
10271                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
10272                 if (pool == null) {
10273                     pool = new ArrayList<StopwatchTimer>();
10274                     mBsi.mSensorTimers.put(mHandle, pool);
10275                 }
10276                 return new DualTimer(mBsi.mClock, mUid, 0, pool, timeBase, bgTimeBase, in);
10277             }
10278 
reset(long elapsedRealtimeUs)10279             boolean reset(long elapsedRealtimeUs) {
10280                 if (mTimer.reset(true, elapsedRealtimeUs)) {
10281                     mTimer = null;
10282                     return true;
10283                 }
10284                 return false;
10285             }
10286 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10287             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10288                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
10289             }
10290 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)10291             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
10292                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
10293             }
10294 
10295             @Override
getSensorTime()10296             public Timer getSensorTime() {
10297                 return mTimer;
10298             }
10299 
10300             @Override
getSensorBackgroundTime()10301             public Timer getSensorBackgroundTime() {
10302                 if (mTimer == null) {
10303                     return null;
10304                 }
10305                 return mTimer.getSubTimer();
10306             }
10307 
10308             @Override
getHandle()10309             public int getHandle() {
10310                 return mHandle;
10311             }
10312 
detachFromTimeBase()10313             public void  detachFromTimeBase() {
10314                 detachIfNotNull(mTimer);
10315             }
10316         }
10317 
10318         /**
10319          * The statistics associated with a particular process.
10320          */
10321         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
10322             /**
10323              * BatteryStatsImpl that we are associated with.
10324              */
10325             protected BatteryStatsImpl mBsi;
10326 
10327             /**
10328              * The name of this process.
10329              */
10330             final String mName;
10331 
10332             /**
10333              * Remains true until removed from the stats.
10334              */
10335             boolean mActive = true;
10336 
10337             /**
10338              * Total time (in ms) spent executing in user code.
10339              */
10340             long mUserTimeMs;
10341 
10342             /**
10343              * Total time (in ms) spent executing in kernel code.
10344              */
10345             long mSystemTimeMs;
10346 
10347             /**
10348              * Amount of time (in ms) the process was running in the foreground.
10349              */
10350             long mForegroundTimeMs;
10351 
10352             /**
10353              * Number of times the process has been started.
10354              */
10355             int mStarts;
10356 
10357             /**
10358              * Number of times the process has crashed.
10359              */
10360             int mNumCrashes;
10361 
10362             /**
10363              * Number of times the process has had an ANR.
10364              */
10365             int mNumAnrs;
10366 
10367             ArrayList<ExcessivePower> mExcessivePower;
10368 
Proc(BatteryStatsImpl bsi, String name)10369             public Proc(BatteryStatsImpl bsi, String name) {
10370                 mBsi = bsi;
10371                 mName = name;
10372                 mBsi.mOnBatteryTimeBase.add(this);
10373             }
10374 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10375             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10376                     long baseRealtimeUs) {
10377             }
10378 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10379             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10380                     long baseRealtimeUs) {
10381             }
10382 
10383             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10384             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10385                 if (detachIfReset) {
10386                     this.detach();
10387                 }
10388                 return true;
10389             }
10390 
10391             @Override
detach()10392             public void detach() {
10393                 mActive = false;
10394                 mBsi.mOnBatteryTimeBase.remove(this);
10395             }
10396 
countExcessivePowers()10397             public int countExcessivePowers() {
10398                 return mExcessivePower != null ? mExcessivePower.size() : 0;
10399             }
10400 
getExcessivePower(int i)10401             public ExcessivePower getExcessivePower(int i) {
10402                 if (mExcessivePower != null) {
10403                     return mExcessivePower.get(i);
10404                 }
10405                 return null;
10406             }
10407 
addExcessiveCpu(long overTimeMs, long usedTimeMs)10408             public void addExcessiveCpu(long overTimeMs, long usedTimeMs) {
10409                 if (mExcessivePower == null) {
10410                     mExcessivePower = new ArrayList<ExcessivePower>();
10411                 }
10412                 ExcessivePower ew = new ExcessivePower();
10413                 ew.type = ExcessivePower.TYPE_CPU;
10414                 ew.overTime = overTimeMs;
10415                 ew.usedTime = usedTimeMs;
10416                 mExcessivePower.add(ew);
10417             }
10418 
writeExcessivePowerToParcelLocked(Parcel out)10419             void writeExcessivePowerToParcelLocked(Parcel out) {
10420                 if (mExcessivePower == null) {
10421                     out.writeInt(0);
10422                     return;
10423                 }
10424 
10425                 final int N = mExcessivePower.size();
10426                 out.writeInt(N);
10427                 for (int i=0; i<N; i++) {
10428                     ExcessivePower ew = mExcessivePower.get(i);
10429                     out.writeInt(ew.type);
10430                     out.writeLong(ew.overTime);
10431                     out.writeLong(ew.usedTime);
10432                 }
10433             }
10434 
readExcessivePowerFromParcelLocked(Parcel in)10435             void readExcessivePowerFromParcelLocked(Parcel in) {
10436                 final int N = in.readInt();
10437                 if (N == 0) {
10438                     mExcessivePower = null;
10439                     return;
10440                 }
10441 
10442                 if (N > 10000) {
10443                     throw new ParcelFormatException(
10444                             "File corrupt: too many excessive power entries " + N);
10445                 }
10446 
10447                 mExcessivePower = new ArrayList<>();
10448                 for (int i=0; i<N; i++) {
10449                     ExcessivePower ew = new ExcessivePower();
10450                     ew.type = in.readInt();
10451                     ew.overTime = in.readLong();
10452                     ew.usedTime = in.readLong();
10453                     mExcessivePower.add(ew);
10454                 }
10455             }
10456 
writeToParcelLocked(Parcel out)10457             void writeToParcelLocked(Parcel out) {
10458                 out.writeLong(mUserTimeMs);
10459                 out.writeLong(mSystemTimeMs);
10460                 out.writeLong(mForegroundTimeMs);
10461                 out.writeInt(mStarts);
10462                 out.writeInt(mNumCrashes);
10463                 out.writeInt(mNumAnrs);
10464                 writeExcessivePowerToParcelLocked(out);
10465             }
10466 
readFromParcelLocked(Parcel in)10467             void readFromParcelLocked(Parcel in) {
10468                 mUserTimeMs = in.readLong();
10469                 mSystemTimeMs = in.readLong();
10470                 mForegroundTimeMs = in.readLong();
10471                 mStarts = in.readInt();
10472                 mNumCrashes = in.readInt();
10473                 mNumAnrs = in.readInt();
10474                 readExcessivePowerFromParcelLocked(in);
10475             }
10476 
addCpuTimeLocked(int utimeMs, int stimeMs)10477             public void addCpuTimeLocked(int utimeMs, int stimeMs) {
10478                 addCpuTimeLocked(utimeMs, stimeMs, mBsi.mOnBatteryTimeBase.isRunning());
10479             }
10480 
addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning)10481             public void addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning) {
10482                 if (isRunning) {
10483                     mUserTimeMs += utimeMs;
10484                     mSystemTimeMs += stimeMs;
10485                 }
10486             }
10487 
addForegroundTimeLocked(long ttimeMs)10488             public void addForegroundTimeLocked(long ttimeMs) {
10489                 mForegroundTimeMs += ttimeMs;
10490             }
10491 
incStartsLocked()10492             public void incStartsLocked() {
10493                 mStarts++;
10494             }
10495 
incNumCrashesLocked()10496             public void incNumCrashesLocked() {
10497                 mNumCrashes++;
10498             }
10499 
incNumAnrsLocked()10500             public void incNumAnrsLocked() {
10501                 mNumAnrs++;
10502             }
10503 
10504             @Override
isActive()10505             public boolean isActive() {
10506                 return mActive;
10507             }
10508 
10509             @Override
getUserTime(int which)10510             public long getUserTime(int which) {
10511                 return mUserTimeMs;
10512             }
10513 
10514             @Override
getSystemTime(int which)10515             public long getSystemTime(int which) {
10516                 return mSystemTimeMs;
10517             }
10518 
10519             @Override
getForegroundTime(int which)10520             public long getForegroundTime(int which) {
10521                 return mForegroundTimeMs;
10522             }
10523 
10524             @Override
getStarts(int which)10525             public int getStarts(int which) {
10526                 return mStarts;
10527             }
10528 
10529             @Override
getNumCrashes(int which)10530             public int getNumCrashes(int which) {
10531                 return mNumCrashes;
10532             }
10533 
10534             @Override
getNumAnrs(int which)10535             public int getNumAnrs(int which) {
10536                 return mNumAnrs;
10537             }
10538         }
10539 
10540         /**
10541          * The statistics associated with a particular package.
10542          */
10543         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
10544             /**
10545              * BatteryStatsImpl that we are associated with.
10546              */
10547             protected BatteryStatsImpl mBsi;
10548 
10549             /**
10550              * Number of times wakeup alarms have occurred for this app.
10551              * On screen-off timebase starting in report v25.
10552              */
10553             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
10554 
10555             /**
10556              * The statics we have collected for this package's services.
10557              */
10558             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
10559 
Pkg(BatteryStatsImpl bsi)10560             public Pkg(BatteryStatsImpl bsi) {
10561                 mBsi = bsi;
10562                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
10563             }
10564 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10565             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10566                     long baseRealtimeUs) {
10567             }
10568 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10569             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10570                     long baseRealtimeUs) {
10571             }
10572 
10573             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10574             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10575                 if (detachIfReset) {
10576                     this.detach();
10577                 }
10578                 return true;
10579             }
10580 
10581             @Override
detach()10582             public void detach() {
10583                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
10584                 for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
10585                     detachIfNotNull(mWakeupAlarms.valueAt(j));
10586                 }
10587                 for (int j = mServiceStats.size() - 1; j >= 0; j--) {
10588                     detachIfNotNull(mServiceStats.valueAt(j));
10589                 }
10590             }
10591 
readFromParcelLocked(Parcel in)10592             void readFromParcelLocked(Parcel in) {
10593                 int numWA = in.readInt();
10594                 mWakeupAlarms.clear();
10595                 for (int i=0; i<numWA; i++) {
10596                     String tag = in.readString();
10597                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
10598                 }
10599 
10600                 int numServs = in.readInt();
10601                 mServiceStats.clear();
10602                 for (int m = 0; m < numServs; m++) {
10603                     String serviceName = in.readString();
10604                     Uid.Pkg.Serv serv = new Serv(mBsi);
10605                     mServiceStats.put(serviceName, serv);
10606 
10607                     serv.readFromParcelLocked(in);
10608                 }
10609             }
10610 
writeToParcelLocked(Parcel out)10611             void writeToParcelLocked(Parcel out) {
10612                 int numWA = mWakeupAlarms.size();
10613                 out.writeInt(numWA);
10614                 for (int i=0; i<numWA; i++) {
10615                     out.writeString(mWakeupAlarms.keyAt(i));
10616                     mWakeupAlarms.valueAt(i).writeToParcel(out);
10617                 }
10618 
10619                 final int NS = mServiceStats.size();
10620                 out.writeInt(NS);
10621                 for (int i=0; i<NS; i++) {
10622                     out.writeString(mServiceStats.keyAt(i));
10623                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
10624                     serv.writeToParcelLocked(out);
10625                 }
10626             }
10627 
10628             @Override
getWakeupAlarmStats()10629             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
10630                 return mWakeupAlarms;
10631             }
10632 
noteWakeupAlarmLocked(String tag)10633             public void noteWakeupAlarmLocked(String tag) {
10634                 Counter c = mWakeupAlarms.get(tag);
10635                 if (c == null) {
10636                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
10637                     mWakeupAlarms.put(tag, c);
10638                 }
10639                 c.stepAtomic();
10640             }
10641 
10642             @Override
getServiceStats()10643             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
10644                 return mServiceStats;
10645             }
10646 
10647             /**
10648              * The statistics associated with a particular service.
10649              */
10650             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
10651                 /**
10652                  * BatteryStatsImpl that we are associated with.
10653                  */
10654                 protected BatteryStatsImpl mBsi;
10655 
10656                 /**
10657                  * The android package in which this service resides.
10658                  */
10659                 protected Pkg mPkg;
10660 
10661                 /**
10662                  * Total time (ms in battery uptime) the service has been left started.
10663                  */
10664                 protected long mStartTimeMs;
10665 
10666                 /**
10667                  * If service has been started and not yet stopped, this is
10668                  * when it was started.
10669                  */
10670                 protected long mRunningSinceMs;
10671 
10672                 /**
10673                  * True if we are currently running.
10674                  */
10675                 protected boolean mRunning;
10676 
10677                 /**
10678                  * Total number of times startService() has been called.
10679                  */
10680                 protected int mStarts;
10681 
10682                 /**
10683                  * Total time (ms in battery uptime) the service has been left launched.
10684                  */
10685                 protected long mLaunchedTimeMs;
10686 
10687                 /**
10688                  * If service has been launched and not yet exited, this is
10689                  * when it was launched (ms in battery uptime).
10690                  */
10691                 protected long mLaunchedSinceMs;
10692 
10693                 /**
10694                  * True if we are currently launched.
10695                  */
10696                 protected boolean mLaunched;
10697 
10698                 /**
10699                  * Total number times the service has been launched.
10700                  */
10701                 protected int mLaunches;
10702 
10703                 /**
10704                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
10705                  */
Serv(BatteryStatsImpl bsi)10706                 public Serv(BatteryStatsImpl bsi) {
10707                     mBsi = bsi;
10708                     mBsi.mOnBatteryTimeBase.add(this);
10709                 }
10710 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10711                 public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10712                         long baseRealtimeUs) {
10713                 }
10714 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10715                 public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10716                         long baseRealtimeUs) {
10717                 }
10718 
10719                 @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10720                 public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10721                     if (detachIfReset) {
10722                         this.detach();
10723                     }
10724                     return true;
10725                 }
10726 
10727                 /**
10728                  * Remove this Serv as a listener from the time base.
10729                  Ms*/
10730                 @Override
detach()10731                 public void detach() {
10732                     mBsi.mOnBatteryTimeBase.remove(this);
10733                 }
10734 
readFromParcelLocked(Parcel in)10735                 public void readFromParcelLocked(Parcel in) {
10736                     mStartTimeMs = in.readLong();
10737                     mRunningSinceMs = in.readLong();
10738                     mRunning = in.readInt() != 0;
10739                     mStarts = in.readInt();
10740                     mLaunchedTimeMs = in.readLong();
10741                     mLaunchedSinceMs = in.readLong();
10742                     mLaunched = in.readInt() != 0;
10743                     mLaunches = in.readInt();
10744                 }
10745 
writeToParcelLocked(Parcel out)10746                 public void writeToParcelLocked(Parcel out) {
10747                     out.writeLong(mStartTimeMs);
10748                     out.writeLong(mRunningSinceMs);
10749                     out.writeInt(mRunning ? 1 : 0);
10750                     out.writeInt(mStarts);
10751                     out.writeLong(mLaunchedTimeMs);
10752                     out.writeLong(mLaunchedSinceMs);
10753                     out.writeInt(mLaunched ? 1 : 0);
10754                     out.writeInt(mLaunches);
10755                 }
10756 
getLaunchTimeToNowLocked(long batteryUptimeMs)10757                 public long getLaunchTimeToNowLocked(long batteryUptimeMs) {
10758                     if (!mLaunched) return mLaunchedTimeMs;
10759                     return mLaunchedTimeMs + batteryUptimeMs - mLaunchedSinceMs;
10760                 }
10761 
getStartTimeToNowLocked(long batteryUptimeMs)10762                 public long getStartTimeToNowLocked(long batteryUptimeMs) {
10763                     if (!mRunning) return mStartTimeMs;
10764                     return mStartTimeMs + batteryUptimeMs - mRunningSinceMs;
10765                 }
10766 
startLaunchedLocked()10767                 public void startLaunchedLocked() {
10768                     startLaunchedLocked(mBsi.mClock.uptimeMillis());
10769                 }
10770 
startLaunchedLocked(long uptimeMs)10771                 public void startLaunchedLocked(long uptimeMs) {
10772                     if (!mLaunched) {
10773                         mLaunches++;
10774                         mLaunchedSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10775                         mLaunched = true;
10776                     }
10777                 }
10778 
stopLaunchedLocked()10779                 public void stopLaunchedLocked() {
10780                     stopLaunchedLocked(mBsi.mClock.uptimeMillis());
10781                 }
10782 
stopLaunchedLocked(long uptimeMs)10783                 public void stopLaunchedLocked(long uptimeMs) {
10784                     if (mLaunched) {
10785                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10786                                 - mLaunchedSinceMs;
10787                         if (timeMs > 0) {
10788                             mLaunchedTimeMs += timeMs;
10789                         } else {
10790                             mLaunches--;
10791                         }
10792                         mLaunched = false;
10793                     }
10794                 }
10795 
startRunningLocked()10796                 public void startRunningLocked() {
10797                     startRunningLocked(mBsi.mClock.uptimeMillis());
10798                 }
10799 
startRunningLocked(long uptimeMs)10800                 public void startRunningLocked(long uptimeMs) {
10801                     if (!mRunning) {
10802                         mStarts++;
10803                         mRunningSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10804                         mRunning = true;
10805                     }
10806                 }
10807 
stopRunningLocked()10808                 public void stopRunningLocked() {
10809                     stopRunningLocked(mBsi.mClock.uptimeMillis());
10810                 }
10811 
stopRunningLocked(long uptimeMs)10812                 public void stopRunningLocked(long uptimeMs) {
10813                     if (mRunning) {
10814                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10815                                 - mRunningSinceMs;
10816                         if (timeMs > 0) {
10817                             mStartTimeMs += timeMs;
10818                         } else {
10819                             mStarts--;
10820                         }
10821                         mRunning = false;
10822                     }
10823                 }
10824 
getBatteryStats()10825                 public BatteryStatsImpl getBatteryStats() {
10826                     return mBsi;
10827                 }
10828 
10829                 @Override
getLaunches(int which)10830                 public int getLaunches(int which) {
10831                     return mLaunches;
10832                 }
10833 
10834                 @Override
getStartTime(long now, int which)10835                 public long getStartTime(long now, int which) {
10836                     return getStartTimeToNowLocked(now);
10837                 }
10838 
10839                 @Override
getStarts(int which)10840                 public int getStarts(int which) {
10841                     return mStarts;
10842                 }
10843             }
10844 
newServiceStatsLocked()10845             final Serv newServiceStatsLocked() {
10846                 return new Serv(mBsi);
10847             }
10848         }
10849 
10850         private class ChildUid {
10851             public final TimeMultiStateCounter cpuActiveCounter;
10852             public final LongArrayMultiStateCounter cpuTimeInFreqCounter;
10853 
ChildUid()10854             ChildUid() {
10855                 final long timestampMs = mBsi.mClock.elapsedRealtime();
10856                 cpuActiveCounter =
10857                         new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase, 1, timestampMs);
10858                 cpuActiveCounter.setState(0, timestampMs);
10859 
10860                 if (mBsi.trackPerProcStateCpuTimes()) {
10861                     final int cpuFreqCount = mBsi.mCpuScalingPolicies.getScalingStepCount();
10862 
10863                     cpuTimeInFreqCounter = new LongArrayMultiStateCounter(1, cpuFreqCount);
10864 
10865                     // Set initial values to all 0. This is a child UID and we want to include
10866                     // the entirety of its CPU time-in-freq stats into the parent's stats.
10867                     cpuTimeInFreqCounter.updateValues(new long[cpuFreqCount], timestampMs);
10868                 } else {
10869                     cpuTimeInFreqCounter = null;
10870                 }
10871             }
10872         }
10873 
10874         /**
10875          * Retrieve the statistics object for a particular process, creating
10876          * if needed.
10877          */
getProcessStatsLocked(String name)10878         public Proc getProcessStatsLocked(String name) {
10879             Proc ps = mProcessStats.get(name);
10880             if (ps == null) {
10881                 ps = new Proc(mBsi, name);
10882                 mProcessStats.put(name, ps);
10883             }
10884 
10885             return ps;
10886         }
10887 
10888         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState, long elapsedRealtimeMs, long uptimeMs)10889         public void updateUidProcessStateLocked(int procState,
10890                 long elapsedRealtimeMs, long uptimeMs) {
10891             int uidRunningState;
10892             // Make special note of Foreground Services
10893             final boolean userAwareService = ActivityManager.isForegroundService(procState);
10894             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
10895             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
10896                 return;
10897             }
10898 
10899             if (mProcessState != uidRunningState) {
10900                 if (mProcessState != Uid.PROCESS_STATE_NONEXISTENT) {
10901                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
10902                 }
10903                 if (uidRunningState != Uid.PROCESS_STATE_NONEXISTENT) {
10904                     if (mProcessStateTimer[uidRunningState] == null) {
10905                         makeProcessState(uidRunningState, null);
10906                     }
10907                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
10908                 }
10909 
10910                 if (!mBsi.mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)
10911                         && mBsi.trackPerProcStateCpuTimes()) {
10912                     mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs, uptimeMs);
10913 
10914                     LongArrayMultiStateCounter onBatteryCounter =
10915                             getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
10916                     LongArrayMultiStateCounter onBatteryScreenOffCounter =
10917                             getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
10918 
10919                     onBatteryCounter.setState(uidRunningState, elapsedRealtimeMs);
10920                     onBatteryScreenOffCounter.setState(uidRunningState, elapsedRealtimeMs);
10921                 }
10922 
10923                 final int prevBatteryConsumerProcessState =
10924                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState);
10925 
10926                 mProcessState = uidRunningState;
10927 
10928                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10929                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10930 
10931                 final int batteryConsumerProcessState =
10932                         mapUidProcessStateToBatteryConsumerProcessState(uidRunningState);
10933                 if (mBsi.mSystemReady) {
10934                     mBsi.mHistory.recordProcessStateChange(elapsedRealtimeMs, uptimeMs, mUid,
10935                             batteryConsumerProcessState);
10936                 }
10937                 getCpuActiveTimeCounter().setState(batteryConsumerProcessState, elapsedRealtimeMs);
10938 
10939                 getMobileRadioActiveTimeCounter()
10940                         .setState(batteryConsumerProcessState, elapsedRealtimeMs);
10941 
10942                 final ControllerActivityCounterImpl wifiControllerActivity =
10943                         getWifiControllerActivity();
10944                 if (wifiControllerActivity != null) {
10945                     wifiControllerActivity.setState(batteryConsumerProcessState, elapsedRealtimeMs);
10946                 }
10947 
10948                 final ControllerActivityCounterImpl bluetoothControllerActivity =
10949                         getBluetoothControllerActivity();
10950                 if (bluetoothControllerActivity != null) {
10951                     bluetoothControllerActivity.setState(batteryConsumerProcessState,
10952                             elapsedRealtimeMs);
10953                 }
10954 
10955                 final EnergyConsumerStats energyStats =
10956                         getOrCreateEnergyConsumerStatsIfSupportedLocked();
10957                 if (energyStats != null) {
10958                     energyStats.setState(batteryConsumerProcessState, elapsedRealtimeMs);
10959                 }
10960                 maybeScheduleExternalStatsSync(prevBatteryConsumerProcessState,
10961                         batteryConsumerProcessState);
10962             }
10963 
10964             if (userAwareService != mInForegroundService) {
10965                 if (userAwareService) {
10966                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
10967                 } else {
10968                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
10969                 }
10970                 mInForegroundService = userAwareService;
10971             }
10972         }
10973 
10974         @GuardedBy("mBsi")
maybeScheduleExternalStatsSync( @atteryConsumer.ProcessState int oldProcessState, @BatteryConsumer.ProcessState int newProcessState)10975         private void maybeScheduleExternalStatsSync(
10976                 @BatteryConsumer.ProcessState int oldProcessState,
10977                 @BatteryConsumer.ProcessState int newProcessState) {
10978             if (oldProcessState == newProcessState) {
10979                 return;
10980             }
10981             // Transitions between BACKGROUND and such non-foreground states like cached
10982             // or nonexistent do not warrant doing a sync.  If some of the stats for those
10983             // proc states bleed into the PROCESS_STATE_BACKGROUND, that's ok.
10984             if ((oldProcessState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED
10985                     && newProcessState == BatteryConsumer.PROCESS_STATE_BACKGROUND)
10986                     || (oldProcessState == BatteryConsumer.PROCESS_STATE_BACKGROUND
10987                     && newProcessState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED)) {
10988                 return;
10989             }
10990 
10991             int flags = ExternalStatsSync.UPDATE_ON_PROC_STATE_CHANGE;
10992             // Skip querying for inactive radio, where power usage is probably negligible.
10993             if (!BatteryStatsImpl.isActiveRadioPowerState(mBsi.mMobileRadioPowerState)) {
10994                 flags &= ~ExternalStatsSync.UPDATE_RADIO;
10995             }
10996 
10997             mBsi.mExternalSync.scheduleSyncDueToProcessStateChange(flags,
10998                     mBsi.mConstants.PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
10999         }
11000 
11001         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()11002         public boolean isInBackground() {
11003             // Note that PROCESS_STATE_CACHED and Uid.PROCESS_STATE_NONEXISTENT is
11004             // also considered to be 'background' for our purposes, because it's not foreground.
11005             return mProcessState >= PROCESS_STATE_BACKGROUND;
11006         }
11007 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)11008         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
11009             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
11010             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
11011         }
11012 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)11013         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
11014             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
11015             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
11016         }
11017 
getPidStats()11018         public SparseArray<? extends Pid> getPidStats() {
11019             return mPids;
11020         }
11021 
getPidStatsLocked(int pid)11022         public Pid getPidStatsLocked(int pid) {
11023             Pid p = mPids.get(pid);
11024             if (p == null) {
11025                 p = new Pid();
11026                 mPids.put(pid, p);
11027             }
11028             return p;
11029         }
11030 
11031         /**
11032          * Retrieve the statistics object for a particular service, creating
11033          * if needed.
11034          */
getPackageStatsLocked(String name)11035         public Pkg getPackageStatsLocked(String name) {
11036             Pkg ps = mPackageStats.get(name);
11037             if (ps == null) {
11038                 ps = new Pkg(mBsi);
11039                 mPackageStats.put(name, ps);
11040             }
11041 
11042             return ps;
11043         }
11044 
11045         /**
11046          * Retrieve the statistics object for a particular service, creating
11047          * if needed.
11048          */
getServiceStatsLocked(String pkg, String serv)11049         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
11050             Pkg ps = getPackageStatsLocked(pkg);
11051             Pkg.Serv ss = ps.mServiceStats.get(serv);
11052             if (ss == null) {
11053                 ss = ps.newServiceStatsLocked();
11054                 ps.mServiceStats.put(serv, ss);
11055             }
11056 
11057             return ss;
11058         }
11059 
readSyncSummaryFromParcelLocked(String name, Parcel in)11060         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
11061             DualTimer timer = mSyncStats.instantiateObject();
11062             timer.readSummaryFromParcelLocked(in);
11063             mSyncStats.add(name, timer);
11064         }
11065 
readJobSummaryFromParcelLocked(String name, Parcel in)11066         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
11067             DualTimer timer = mJobStats.instantiateObject();
11068             timer.readSummaryFromParcelLocked(in);
11069             mJobStats.add(name, timer);
11070         }
11071 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)11072         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
11073             Wakelock wl = new Wakelock(mBsi, this);
11074             mWakelockStats.add(wlName, wl);
11075             if (in.readInt() != 0) {
11076                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
11077             }
11078             if (in.readInt() != 0) {
11079                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
11080             }
11081             if (in.readInt() != 0) {
11082                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
11083             }
11084             if (in.readInt() != 0) {
11085                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
11086             }
11087         }
11088 
getSensorTimerLocked(int sensor, boolean create)11089         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
11090             Sensor se = mSensorStats.get(sensor);
11091             if (se == null) {
11092                 if (!create) {
11093                     return null;
11094                 }
11095                 se = new Sensor(mBsi, this, sensor);
11096                 mSensorStats.put(sensor, se);
11097             }
11098             DualTimer t = se.mTimer;
11099             if (t != null) {
11100                 return t;
11101             }
11102             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
11103             if (timers == null) {
11104                 timers = new ArrayList<StopwatchTimer>();
11105                 mBsi.mSensorTimers.put(sensor, timers);
11106             }
11107             t = new DualTimer(mBsi.mClock, this, BatteryStats.SENSOR, timers,
11108                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
11109             se.mTimer = t;
11110             return t;
11111         }
11112 
noteStartSyncLocked(String name, long elapsedRealtimeMs)11113         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
11114             DualTimer t = mSyncStats.startObject(name, elapsedRealtimeMs);
11115             if (t != null) {
11116                 t.startRunningLocked(elapsedRealtimeMs);
11117             }
11118         }
11119 
noteStopSyncLocked(String name, long elapsedRealtimeMs)11120         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
11121             DualTimer t = mSyncStats.stopObject(name, elapsedRealtimeMs);
11122             if (t != null) {
11123                 t.stopRunningLocked(elapsedRealtimeMs);
11124             }
11125         }
11126 
noteStartJobLocked(String name, long elapsedRealtimeMs)11127         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
11128             DualTimer t = mJobStats.startObject(name, elapsedRealtimeMs);
11129             if (t != null) {
11130                 t.startRunningLocked(elapsedRealtimeMs);
11131             }
11132         }
11133 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)11134         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
11135             DualTimer t = mJobStats.stopObject(name, elapsedRealtimeMs);
11136             if (t != null) {
11137                 t.stopRunningLocked(elapsedRealtimeMs);
11138             }
11139             if (mBsi.mOnBatteryTimeBase.isRunning()) {
11140                 SparseIntArray types = mJobCompletions.get(name);
11141                 if (types == null) {
11142                     types = new SparseIntArray();
11143                     mJobCompletions.put(name, types);
11144                 }
11145                 int last = types.get(stopReason, 0);
11146                 types.put(stopReason, last + 1);
11147             }
11148         }
11149 
getWakelockTimerLocked(Wakelock wl, int type)11150         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
11151             if (wl == null) {
11152                 return null;
11153             }
11154             switch (type) {
11155                 case WAKE_TYPE_PARTIAL: {
11156                     DualTimer t = wl.mTimerPartial;
11157                     if (t == null) {
11158                         t = new DualTimer(mBsi.mClock, this, WAKE_TYPE_PARTIAL,
11159                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
11160                                 mOnBatteryScreenOffBackgroundTimeBase);
11161                         wl.mTimerPartial = t;
11162                     }
11163                     return t;
11164                 }
11165                 case WAKE_TYPE_FULL: {
11166                     StopwatchTimer t = wl.mTimerFull;
11167                     if (t == null) {
11168                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_FULL,
11169                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
11170                         wl.mTimerFull = t;
11171                     }
11172                     return t;
11173                 }
11174                 case WAKE_TYPE_WINDOW: {
11175                     StopwatchTimer t = wl.mTimerWindow;
11176                     if (t == null) {
11177                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_WINDOW,
11178                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
11179                         wl.mTimerWindow = t;
11180                     }
11181                     return t;
11182                 }
11183                 case WAKE_TYPE_DRAW: {
11184                     StopwatchTimer t = wl.mTimerDraw;
11185                     if (t == null) {
11186                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_DRAW,
11187                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
11188                         wl.mTimerDraw = t;
11189                     }
11190                     return t;
11191                 }
11192                 default:
11193                     throw new IllegalArgumentException("type=" + type);
11194             }
11195         }
11196 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)11197         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
11198             Wakelock wl = mWakelockStats.startObject(name, elapsedRealtimeMs);
11199             if (wl != null) {
11200                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
11201             }
11202             if (type == WAKE_TYPE_PARTIAL) {
11203                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
11204                 if (pid >= 0) {
11205                     Pid p = getPidStatsLocked(pid);
11206                     if (p.mWakeNesting++ == 0) {
11207                         p.mWakeStartMs = elapsedRealtimeMs;
11208                     }
11209                 }
11210             }
11211         }
11212 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)11213         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
11214             Wakelock wl = mWakelockStats.stopObject(name, elapsedRealtimeMs);
11215             if (wl != null) {
11216                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
11217                 wlt.stopRunningLocked(elapsedRealtimeMs);
11218             }
11219             if (type == WAKE_TYPE_PARTIAL) {
11220                 if (mAggregatedPartialWakelockTimer != null) {
11221                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
11222                 }
11223                 if (pid >= 0) {
11224                     Pid p = mPids.get(pid);
11225                     if (p != null && p.mWakeNesting > 0) {
11226                         if (p.mWakeNesting-- == 1) {
11227                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
11228                             p.mWakeStartMs = 0;
11229                         }
11230                     }
11231                 }
11232             }
11233         }
11234 
reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs)11235         public void reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs) {
11236             Proc p = getProcessStatsLocked(proc);
11237             if (p != null) {
11238                 p.addExcessiveCpu(overTimeMs, usedTimeMs);
11239             }
11240         }
11241 
noteStartSensor(int sensor, long elapsedRealtimeMs)11242         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
11243             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
11244             t.startRunningLocked(elapsedRealtimeMs);
11245         }
11246 
noteStopSensor(int sensor, long elapsedRealtimeMs)11247         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
11248             // Don't create a timer if one doesn't already exist
11249             DualTimer t = getSensorTimerLocked(sensor, false);
11250             if (t != null) {
11251                 t.stopRunningLocked(elapsedRealtimeMs);
11252             }
11253         }
11254 
noteStartGps(long elapsedRealtimeMs)11255         public void noteStartGps(long elapsedRealtimeMs) {
11256             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
11257         }
11258 
noteStopGps(long elapsedRealtimeMs)11259         public void noteStopGps(long elapsedRealtimeMs) {
11260             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
11261         }
11262     }
11263 
11264     @GuardedBy("this")
getCpuScalingPolicies()11265     public CpuScalingPolicies getCpuScalingPolicies() {
11266         return mCpuScalingPolicies;
11267     }
11268 
11269     @GuardedBy("this")
getCpuTimeInFreqContainer()11270     private long[] getCpuTimeInFreqContainer() {
11271         if (mTmpCpuTimeInFreq == null) {
11272             mTmpCpuTimeInFreq = new long[mCpuScalingPolicies.getScalingStepCount()];
11273         }
11274         return mTmpCpuTimeInFreq;
11275     }
11276 
11277     WakelockStatsFrameworkEvents mFrameworkEvents = new WakelockStatsFrameworkEvents();
11278     PowerManagerFlags mPowerManagerFlags = new PowerManagerFlags();
11279 
BatteryStatsImpl(@onNull BatteryStatsConfig config, @NonNull Clock clock, @NonNull MonotonicClock monotonicClock, @Nullable File systemDir, @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback, @Nullable EnergyStatsRetriever energyStatsRetriever, @NonNull UserInfoProvider userInfoProvider, @NonNull PowerProfile powerProfile, @NonNull CpuScalingPolicies cpuScalingPolicies, @NonNull PowerStatsUidResolver powerStatsUidResolver)11280     public BatteryStatsImpl(@NonNull BatteryStatsConfig config, @NonNull Clock clock,
11281             @NonNull MonotonicClock monotonicClock, @Nullable File systemDir,
11282             @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback,
11283             @Nullable EnergyStatsRetriever energyStatsRetriever,
11284             @NonNull UserInfoProvider userInfoProvider, @NonNull PowerProfile powerProfile,
11285             @NonNull CpuScalingPolicies cpuScalingPolicies,
11286             @NonNull PowerStatsUidResolver powerStatsUidResolver) {
11287         this(config, clock, monotonicClock, systemDir,
11288                 systemDir != null ? new BatteryHistoryDirectory(new File(systemDir, HISTORY_DIR),
11289                         config.getMaxHistorySizeBytes()) : null,
11290                 handler, platformIdleStateCallback,
11291                 energyStatsRetriever, userInfoProvider, powerProfile, cpuScalingPolicies,
11292                 powerStatsUidResolver, new FrameworkStatsLogger(),
11293                 new BatteryStatsHistory.TraceDelegate(), new BatteryStatsHistory.EventLogger());
11294     }
11295 
BatteryStatsImpl(@onNull BatteryStatsConfig config, @NonNull Clock clock, @NonNull MonotonicClock monotonicClock, @Nullable File systemDir, @Nullable BatteryHistoryDirectory batteryHistoryDirectory, @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback, @Nullable EnergyStatsRetriever energyStatsRetriever, @NonNull UserInfoProvider userInfoProvider, @NonNull PowerProfile powerProfile, @NonNull CpuScalingPolicies cpuScalingPolicies, @NonNull PowerStatsUidResolver powerStatsUidResolver, @NonNull FrameworkStatsLogger frameworkStatsLogger, @NonNull BatteryStatsHistory.TraceDelegate traceDelegate, @NonNull BatteryStatsHistory.EventLogger eventLogger)11296     public BatteryStatsImpl(@NonNull BatteryStatsConfig config, @NonNull Clock clock,
11297             @NonNull MonotonicClock monotonicClock, @Nullable File systemDir,
11298             @Nullable BatteryHistoryDirectory batteryHistoryDirectory,
11299             @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback,
11300             @Nullable EnergyStatsRetriever energyStatsRetriever,
11301             @NonNull UserInfoProvider userInfoProvider, @NonNull PowerProfile powerProfile,
11302             @NonNull CpuScalingPolicies cpuScalingPolicies,
11303             @NonNull PowerStatsUidResolver powerStatsUidResolver,
11304             @NonNull FrameworkStatsLogger frameworkStatsLogger,
11305             @NonNull BatteryStatsHistory.TraceDelegate traceDelegate,
11306             @NonNull BatteryStatsHistory.EventLogger eventLogger) {
11307         mClock = clock;
11308         initKernelStatsReaders();
11309 
11310         mBatteryStatsConfig = config;
11311         mMonotonicClock = monotonicClock;
11312         mHandler = new MyHandler(handler.getLooper());
11313         mConstants = new Constants(mHandler);
11314 
11315         mPowerProfile = powerProfile;
11316         mCpuScalingPolicies = cpuScalingPolicies;
11317         mPowerStatsUidResolver = powerStatsUidResolver;
11318         mFrameworkStatsLogger = frameworkStatsLogger;
11319 
11320         initPowerProfile();
11321 
11322         if (systemDir != null) {
11323             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
11324             mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
11325             mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
11326         } else {
11327             mStatsFile = null;
11328             mCheckinFile = null;
11329             mDailyFile = null;
11330         }
11331 
11332         mBatteryHistoryDirectory = batteryHistoryDirectory;
11333         mHistory = new BatteryStatsHistory(null /* historyBuffer */, mConstants.MAX_HISTORY_BUFFER,
11334                 mBatteryHistoryDirectory, mClock, mMonotonicClock, traceDelegate, eventLogger);
11335 
11336         mCpuPowerStatsCollector = new CpuPowerStatsCollector(mPowerStatsCollectorInjector);
11337         mCpuPowerStatsCollector.addConsumer(this::recordPowerStats);
11338 
11339         mWakelockPowerStatsCollector = new WakelockPowerStatsCollector(
11340                 mPowerStatsCollectorInjector);
11341         mWakelockPowerStatsCollector.addConsumer(this::recordPowerStats);
11342 
11343         mScreenPowerStatsCollector = new ScreenPowerStatsCollector(mPowerStatsCollectorInjector);
11344         mScreenPowerStatsCollector.addConsumer(this::recordPowerStats);
11345 
11346         mMobileRadioPowerStatsCollector = new MobileRadioPowerStatsCollector(
11347                 mPowerStatsCollectorInjector, this::onMobileRadioPowerStatsRetrieved);
11348         mMobileRadioPowerStatsCollector.addConsumer(this::recordPowerStats);
11349 
11350         mWifiPowerStatsCollector = new WifiPowerStatsCollector(mPowerStatsCollectorInjector,
11351                 this::onWifiPowerStatsRetrieved);
11352         mWifiPowerStatsCollector.addConsumer(this::recordPowerStats);
11353 
11354         mBluetoothPowerStatsCollector = new BluetoothPowerStatsCollector(
11355                 mPowerStatsCollectorInjector, this::onBluetoothPowerStatsRetrieved);
11356         mBluetoothPowerStatsCollector.addConsumer(this::recordPowerStats);
11357 
11358         mCameraPowerStatsCollector = new CameraPowerStatsCollector(mPowerStatsCollectorInjector);
11359         mCameraPowerStatsCollector.addConsumer(this::recordPowerStats);
11360 
11361         mGnssPowerStatsCollector = new GnssPowerStatsCollector(mPowerStatsCollectorInjector);
11362         mGnssPowerStatsCollector.addConsumer(this::recordPowerStats);
11363 
11364         mCustomEnergyConsumerPowerStatsCollector =
11365                 new CustomEnergyConsumerPowerStatsCollector(mPowerStatsCollectorInjector);
11366         mCustomEnergyConsumerPowerStatsCollector.addConsumer(this::recordPowerStats);
11367 
11368         mStartCount++;
11369         initTimersAndCounters();
11370         mOnBattery = mOnBatteryInternal = false;
11371         long uptimeUs = mClock.uptimeMillis() * 1000;
11372         long realtimeUs = mClock.elapsedRealtime() * 1000;
11373         initTimes(uptimeUs, realtimeUs);
11374         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
11375         initDischarge(realtimeUs);
11376         updateDailyDeadlineLocked();
11377         mPlatformIdleStateCallback = platformIdleStateCallback;
11378         mEnergyConsumerRetriever = energyStatsRetriever;
11379         mUserInfoProvider = userInfoProvider;
11380 
11381         mPowerStatsUidResolver.addListener(new PowerStatsUidResolver.Listener() {
11382             @Override
11383             public void onIsolatedUidAdded(int isolatedUid, int parentUid) {
11384                 BatteryStatsImpl.this.onIsolatedUidAdded(isolatedUid, parentUid);
11385             }
11386 
11387             @Override
11388             public void onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid) {
11389                 BatteryStatsImpl.this.onBeforeIsolatedUidRemoved(isolatedUid, parentUid);
11390             }
11391 
11392             @Override
11393             public void onAfterIsolatedUidRemoved(int isolatedUid, int parentUid) {
11394                 BatteryStatsImpl.this.onAfterIsolatedUidRemoved(isolatedUid, parentUid);
11395             }
11396         });
11397 
11398         // Notify statsd that the system is initially not in doze.
11399         mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
11400         mFrameworkStatsLogger.deviceIdleModeStateChanged(mDeviceIdleMode);
11401     }
11402 
recordPowerStats(PowerStats stats)11403     private void recordPowerStats(PowerStats stats) {
11404         if (stats.durationMs > 0) {
11405             synchronized (this) {
11406                 mHistory.recordPowerStats(mClock.elapsedRealtime(), mClock.uptimeMillis(), stats);
11407             }
11408         }
11409     }
11410 
11411     @VisibleForTesting
initTimersAndCounters()11412     protected void initTimersAndCounters() {
11413         mScreenOnTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
11414         mScreenDozeTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
11415         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11416             mScreenBrightnessTimer[i] = new StopwatchTimer(mClock, null, -100 - i, null,
11417                     mOnBatteryTimeBase);
11418         }
11419 
11420         mInteractiveTimer = new StopwatchTimer(mClock, null, -10, null, mOnBatteryTimeBase);
11421         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClock, null, -2, null,
11422                 mOnBatteryTimeBase);
11423         mDeviceIdleModeLightTimer = new StopwatchTimer(mClock, null, -11, null,
11424                 mOnBatteryTimeBase);
11425         mDeviceIdleModeFullTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase);
11426         mDeviceLightIdlingTimer = new StopwatchTimer(mClock, null, -15, null, mOnBatteryTimeBase);
11427         mDeviceIdlingTimer = new StopwatchTimer(mClock, null, -12, null, mOnBatteryTimeBase);
11428         mPhoneOnTimer = new StopwatchTimer(mClock, null, -3, null, mOnBatteryTimeBase);
11429         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
11430             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -200 - i, null,
11431                     mOnBatteryTimeBase);
11432         }
11433         mPhoneSignalScanningTimer = new StopwatchTimer(mClock, null, -200 + 1, null,
11434                 mOnBatteryTimeBase);
11435         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11436             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClock, null, -300 - i, null,
11437                     mOnBatteryTimeBase);
11438         }
11439         mNrNsaTimer = new StopwatchTimer(mClock, null, -200 + 2, null, mOnBatteryTimeBase);
11440         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11441             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
11442             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
11443         }
11444         mWifiActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
11445                 NUM_WIFI_TX_LEVELS);
11446         mBluetoothActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
11447                 NUM_BT_TX_LEVELS);
11448         mModemActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
11449                 MODEM_TX_POWER_LEVEL_COUNT);
11450         mMobileRadioActiveTimer = new StopwatchTimer(mClock, null, -400, null, mOnBatteryTimeBase);
11451         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClock, null, -401, null,
11452                 mOnBatteryTimeBase);
11453         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
11454         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
11455         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
11456         mWifiMulticastWakelockTimer = new StopwatchTimer(mClock, null,
11457                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
11458         mWifiOnTimer = new StopwatchTimer(mClock, null, -4, null, mOnBatteryTimeBase);
11459         mGlobalWifiRunningTimer = new StopwatchTimer(mClock, null, -5, null, mOnBatteryTimeBase);
11460         for (int i=0; i<NUM_WIFI_STATES; i++) {
11461             mWifiStateTimer[i] = new StopwatchTimer(mClock, null, -600 - i, null,
11462                     mOnBatteryTimeBase);
11463         }
11464         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11465             mWifiSupplStateTimer[i] = new StopwatchTimer(mClock, null, -700 - i, null,
11466                     mOnBatteryTimeBase);
11467         }
11468         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11469             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -800 - i, null,
11470                     mOnBatteryTimeBase);
11471         }
11472         mWifiActiveTimer = new StopwatchTimer(mClock, null, -900, null, mOnBatteryTimeBase);
11473         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
11474             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClock, null, -1000 - i, null,
11475                     mOnBatteryTimeBase);
11476         }
11477         mAudioOnTimer = new StopwatchTimer(mClock, null, -7, null, mOnBatteryTimeBase);
11478         mVideoOnTimer = new StopwatchTimer(mClock, null, -8, null, mOnBatteryTimeBase);
11479         mFlashlightOnTimer = new StopwatchTimer(mClock, null, -9, null, mOnBatteryTimeBase);
11480         mCameraOnTimer = new StopwatchTimer(mClock, null, -13, null, mOnBatteryTimeBase);
11481         mBluetoothScanTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase);
11482         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
11483         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11484         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11485         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11486         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11487         mDischargeUnplugLevel = 0;
11488         mDischargePlugLevel = -1;
11489         mDischargeCurrentLevel = 0;
11490         mBatteryLevel = 0;
11491     }
11492 
initPowerProfile()11493     private void initPowerProfile() {
11494         int[] policies = mCpuScalingPolicies.getPolicies();
11495         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[policies.length];
11496         for (int i = 0; i < policies.length; i++) {
11497             int[] cpus = mCpuScalingPolicies.getRelatedCpus(policies[i]);
11498             int[] freqs = mCpuScalingPolicies.getFrequencies(policies[i]);
11499             // We need to initialize the KernelCpuSpeedReaders to read from
11500             // the first cpu of each core. Once we have the CpuScalingPolicy, we have access to this
11501             // information.
11502             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(cpus[0], freqs.length);
11503         }
11504 
11505         // Initialize CPU power bracket map, which combines CPU states (cluster/freq pairs)
11506         // into a small number of brackets
11507         mCpuPowerBracketMap = new int[mCpuScalingPolicies.getScalingStepCount()];
11508         int index = 0;
11509         for (int policy : policies) {
11510             int steps = mCpuScalingPolicies.getFrequencies(policy).length;
11511             for (int step = 0; step < steps; step++) {
11512                 mCpuPowerBracketMap[index++] =
11513                         mPowerProfile.getCpuPowerBracketForScalingStep(policy, step);
11514             }
11515         }
11516 
11517         if (mEstimatedBatteryCapacityMah == -1) {
11518             // Initialize the estimated battery capacity to a known preset one.
11519             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
11520         }
11521 
11522         setDisplayCountLocked(mPowerProfile.getNumDisplays());
11523     }
11524 
11525     /**
11526      * Starts tracking CPU time-in-state for threads of the system server process,
11527      * keeping a separate account of threads receiving incoming binder calls.
11528      */
startTrackingSystemServerCpuTime()11529     public void startTrackingSystemServerCpuTime() {
11530         mSystemServerCpuThreadReader.startTrackingThreadCpuTime();
11531     }
11532 
getSystemServiceCpuThreadTimes()11533     public SystemServiceCpuThreadTimes getSystemServiceCpuThreadTimes() {
11534         return mSystemServerCpuThreadReader.readAbsolute();
11535     }
11536 
setCallback(BatteryCallback cb)11537     public void setCallback(BatteryCallback cb) {
11538         mCallback = cb;
11539     }
11540 
updateCpuDetails()11541     void updateCpuDetails() {
11542         if (mCallback != null) {
11543             mCallback.batteryNeedsCpuUpdate();
11544         }
11545     }
11546 
setRadioScanningTimeoutLocked(long timeoutUs)11547     public void setRadioScanningTimeoutLocked(long timeoutUs) {
11548         if (mPhoneSignalScanningTimer != null) {
11549             mPhoneSignalScanningTimer.setTimeout(timeoutUs);
11550         }
11551     }
11552 
setExternalStatsSyncLocked(ExternalStatsSync sync)11553     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
11554         mExternalSync = sync;
11555     }
11556 
11557     /**
11558      * Initialize and set multi display timers and states.
11559      */
setDisplayCountLocked(int numDisplays)11560     public void setDisplayCountLocked(int numDisplays) {
11561         mPerDisplayBatteryStats = new DisplayBatteryStats[numDisplays];
11562         for (int i = 0; i < numDisplays; i++) {
11563             mPerDisplayBatteryStats[i] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
11564         }
11565     }
11566 
updateDailyDeadlineLocked()11567     public void updateDailyDeadlineLocked() {
11568         // Get the current time.
11569         long currentTimeMs = mDailyStartTimeMs = mClock.currentTimeMillis();
11570         Calendar calDeadline = Calendar.getInstance();
11571         calDeadline.setTimeInMillis(currentTimeMs);
11572 
11573         // Move time up to the next day, ranging from 1am to 3pm.
11574         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
11575         calDeadline.set(Calendar.MILLISECOND, 0);
11576         calDeadline.set(Calendar.SECOND, 0);
11577         calDeadline.set(Calendar.MINUTE, 0);
11578         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
11579         mNextMinDailyDeadlineMs = calDeadline.getTimeInMillis();
11580         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
11581         mNextMaxDailyDeadlineMs = calDeadline.getTimeInMillis();
11582     }
11583 
recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs)11584     public void recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs) {
11585         if (currentTimeMs >= mNextMaxDailyDeadlineMs) {
11586             recordDailyStatsLocked();
11587         } else if (settled && currentTimeMs >= mNextMinDailyDeadlineMs) {
11588             recordDailyStatsLocked();
11589         } else if (currentTimeMs < (mDailyStartTimeMs - (1000 * 60 * 60 * 24))) {
11590             recordDailyStatsLocked();
11591         }
11592     }
11593 
recordDailyStatsLocked()11594     public void recordDailyStatsLocked() {
11595         DailyItem item = new DailyItem();
11596         item.mStartTime = mDailyStartTimeMs;
11597         item.mEndTime = mClock.currentTimeMillis();
11598         boolean hasData = false;
11599         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
11600             hasData = true;
11601             item.mDischargeSteps = new LevelStepTracker(
11602                     mDailyDischargeStepTracker.mNumStepDurations,
11603                     mDailyDischargeStepTracker.mStepDurations);
11604         }
11605         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
11606             hasData = true;
11607             item.mChargeSteps = new LevelStepTracker(
11608                     mDailyChargeStepTracker.mNumStepDurations,
11609                     mDailyChargeStepTracker.mStepDurations);
11610         }
11611         if (mDailyPackageChanges != null) {
11612             hasData = true;
11613             item.mPackageChanges = mDailyPackageChanges;
11614             mDailyPackageChanges = null;
11615         }
11616         mDailyDischargeStepTracker.init();
11617         mDailyChargeStepTracker.init();
11618         updateDailyDeadlineLocked();
11619 
11620         if (hasData) {
11621             final long startTimeMs = SystemClock.uptimeMillis();
11622             mDailyItems.add(item);
11623             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
11624                 mDailyItems.remove(0);
11625             }
11626             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
11627             try {
11628                 TypedXmlSerializer out = Xml.resolveSerializer(memStream);
11629                 writeDailyItemsLocked(out);
11630                 final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
11631                 BackgroundThread.getHandler().post(new Runnable() {
11632                     @Override
11633                     public void run() {
11634                         synchronized (mCheckinFile) {
11635                             final long startTimeMs2 = SystemClock.uptimeMillis();
11636                             FileOutputStream stream = null;
11637                             try {
11638                                 stream = mDailyFile.startWrite();
11639                                 memStream.writeTo(stream);
11640                                 stream.flush();
11641                                 mDailyFile.finishWrite(stream);
11642                                 mFrameworkStatsLogger.writeCommitSysConfigFile("batterystats-daily",
11643                                         initialTimeMs + SystemClock.uptimeMillis() - startTimeMs2);
11644                             } catch (IOException e) {
11645                                 Slog.w("BatteryStats",
11646                                         "Error writing battery daily items", e);
11647                                 mDailyFile.failWrite(stream);
11648                             }
11649                         }
11650                     }
11651                 });
11652             } catch (IOException e) {
11653             }
11654         }
11655     }
11656 
writeDailyItemsLocked(TypedXmlSerializer out)11657     private void writeDailyItemsLocked(TypedXmlSerializer out) throws IOException {
11658         StringBuilder sb = new StringBuilder(64);
11659         out.startDocument(null, true);
11660         out.startTag(null, "daily-items");
11661         for (int i=0; i<mDailyItems.size(); i++) {
11662             final DailyItem dit = mDailyItems.get(i);
11663             out.startTag(null, "item");
11664             out.attributeLong(null, "start", dit.mStartTime);
11665             out.attributeLong(null, "end", dit.mEndTime);
11666             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
11667             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
11668             if (dit.mPackageChanges != null) {
11669                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
11670                     PackageChange pc = dit.mPackageChanges.get(j);
11671                     if (pc.mUpdate) {
11672                         out.startTag(null, "upd");
11673                         out.attribute(null, "pkg", pc.mPackageName);
11674                         out.attributeLong(null, "ver", pc.mVersionCode);
11675                         out.endTag(null, "upd");
11676                     } else {
11677                         out.startTag(null, "rem");
11678                         out.attribute(null, "pkg", pc.mPackageName);
11679                         out.endTag(null, "rem");
11680                     }
11681                 }
11682             }
11683             out.endTag(null, "item");
11684         }
11685         out.endTag(null, "daily-items");
11686         out.endDocument();
11687     }
11688 
writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)11689     private void writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps,
11690             StringBuilder tmpBuilder) throws IOException {
11691         if (steps != null) {
11692             out.startTag(null, tag);
11693             out.attributeInt(null, "n", steps.mNumStepDurations);
11694             for (int i=0; i<steps.mNumStepDurations; i++) {
11695                 out.startTag(null, "s");
11696                 tmpBuilder.setLength(0);
11697                 steps.encodeEntryAt(i, tmpBuilder);
11698                 out.attribute(null, "v", tmpBuilder.toString());
11699                 out.endTag(null, "s");
11700             }
11701             out.endTag(null, tag);
11702         }
11703     }
11704 
11705     @GuardedBy("this")
readDailyStatsLocked()11706     public void readDailyStatsLocked() {
11707         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
11708         mDailyItems.clear();
11709         FileInputStream stream;
11710         try {
11711             stream = mDailyFile.openRead();
11712         } catch (FileNotFoundException e) {
11713             return;
11714         }
11715         try {
11716             TypedXmlPullParser parser = Xml.resolvePullParser(stream);
11717             readDailyItemsLocked(parser);
11718         } catch (IOException e) {
11719         } finally {
11720             try {
11721                 stream.close();
11722             } catch (IOException e) {
11723             }
11724         }
11725     }
11726 
readDailyItemsLocked(TypedXmlPullParser parser)11727     private void readDailyItemsLocked(TypedXmlPullParser parser) {
11728         try {
11729             int type;
11730             while ((type = parser.next()) != XmlPullParser.START_TAG
11731                     && type != XmlPullParser.END_DOCUMENT) {
11732                 ;
11733             }
11734 
11735             if (type != XmlPullParser.START_TAG) {
11736                 throw new IllegalStateException("no start tag found");
11737             }
11738 
11739             int outerDepth = parser.getDepth();
11740             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11741                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11742                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11743                     continue;
11744                 }
11745 
11746                 String tagName = parser.getName();
11747                 if (tagName.equals("item")) {
11748                     readDailyItemTagLocked(parser);
11749                 } else {
11750                     Slog.w(TAG, "Unknown element under <daily-items>: "
11751                             + parser.getName());
11752                     XmlUtils.skipCurrentTag(parser);
11753                 }
11754             }
11755 
11756         } catch (IllegalStateException e) {
11757             Slog.w(TAG, "Failed parsing daily " + e);
11758         } catch (NullPointerException e) {
11759             Slog.w(TAG, "Failed parsing daily " + e);
11760         } catch (NumberFormatException e) {
11761             Slog.w(TAG, "Failed parsing daily " + e);
11762         } catch (XmlPullParserException e) {
11763             Slog.w(TAG, "Failed parsing daily " + e);
11764         } catch (IOException e) {
11765             Slog.w(TAG, "Failed parsing daily " + e);
11766         } catch (IndexOutOfBoundsException e) {
11767             Slog.w(TAG, "Failed parsing daily " + e);
11768         }
11769     }
11770 
readDailyItemTagLocked(TypedXmlPullParser parser)11771     void readDailyItemTagLocked(TypedXmlPullParser parser) throws NumberFormatException,
11772             XmlPullParserException, IOException {
11773         DailyItem dit = new DailyItem();
11774         dit.mStartTime = parser.getAttributeLong(null, "start", 0);
11775         dit.mEndTime = parser.getAttributeLong(null, "end", 0);
11776         int outerDepth = parser.getDepth();
11777         int type;
11778         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11779                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11780             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11781                 continue;
11782             }
11783 
11784             String tagName = parser.getName();
11785             if (tagName.equals("dis")) {
11786                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
11787             } else if (tagName.equals("chg")) {
11788                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
11789             } else if (tagName.equals("upd")) {
11790                 if (dit.mPackageChanges == null) {
11791                     dit.mPackageChanges = new ArrayList<>();
11792                 }
11793                 PackageChange pc = new PackageChange();
11794                 pc.mUpdate = true;
11795                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11796                 pc.mVersionCode = parser.getAttributeLong(null, "ver", 0);
11797                 dit.mPackageChanges.add(pc);
11798                 XmlUtils.skipCurrentTag(parser);
11799             } else if (tagName.equals("rem")) {
11800                 if (dit.mPackageChanges == null) {
11801                     dit.mPackageChanges = new ArrayList<>();
11802                 }
11803                 PackageChange pc = new PackageChange();
11804                 pc.mUpdate = false;
11805                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11806                 dit.mPackageChanges.add(pc);
11807                 XmlUtils.skipCurrentTag(parser);
11808             } else {
11809                 Slog.w(TAG, "Unknown element under <item>: "
11810                         + parser.getName());
11811                 XmlUtils.skipCurrentTag(parser);
11812             }
11813         }
11814         mDailyItems.add(dit);
11815     }
11816 
readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge, String tag)11817     void readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge,
11818             String tag)
11819             throws NumberFormatException, XmlPullParserException, IOException {
11820         final int num = parser.getAttributeInt(null, "n", -1);
11821         if (num == -1) {
11822             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
11823             XmlUtils.skipCurrentTag(parser);
11824             return;
11825         }
11826         LevelStepTracker steps = new LevelStepTracker(num);
11827         if (isCharge) {
11828             dit.mChargeSteps = steps;
11829         } else {
11830             dit.mDischargeSteps = steps;
11831         }
11832         int i = 0;
11833         int outerDepth = parser.getDepth();
11834         int type;
11835         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11836                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11837             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11838                 continue;
11839             }
11840 
11841             String tagName = parser.getName();
11842             if ("s".equals(tagName)) {
11843                 if (i < num) {
11844                     String valueAttr = parser.getAttributeValue(null, "v");
11845                     if (valueAttr != null) {
11846                         steps.decodeEntryAt(i, valueAttr);
11847                         i++;
11848                     }
11849                 }
11850             } else {
11851                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
11852                         + parser.getName());
11853                 XmlUtils.skipCurrentTag(parser);
11854             }
11855         }
11856         steps.mNumStepDurations = i;
11857     }
11858 
11859     @Override
getDailyItemLocked(int daysAgo)11860     public DailyItem getDailyItemLocked(int daysAgo) {
11861         int index = mDailyItems.size()-1-daysAgo;
11862         return index >= 0 ? mDailyItems.get(index) : null;
11863     }
11864 
11865     @Override
getCurrentDailyStartTime()11866     public long getCurrentDailyStartTime() {
11867         return mDailyStartTimeMs;
11868     }
11869 
11870     @Override
getNextMinDailyDeadline()11871     public long getNextMinDailyDeadline() {
11872         return mNextMinDailyDeadlineMs;
11873     }
11874 
11875     @Override
getNextMaxDailyDeadline()11876     public long getNextMaxDailyDeadline() {
11877         return mNextMaxDailyDeadlineMs;
11878     }
11879 
getHistoryTotalSize()11880     public int getHistoryTotalSize() {
11881         return mBatteryHistoryDirectory.getMaxHistorySize();
11882     }
11883 
getHistoryUsedSize()11884     public int getHistoryUsedSize() {
11885         return mHistory.getHistoryUsedSize();
11886     }
11887 
11888     /**
11889      * Creates an iterator for battery stats history.
11890      */
11891     @Override
iterateBatteryStatsHistory(long startTimeMs, long endTimeMs)11892     public BatteryStatsHistoryIterator iterateBatteryStatsHistory(long startTimeMs,
11893             long endTimeMs) {
11894         return mHistory.iterate(startTimeMs, endTimeMs);
11895     }
11896 
11897     @Override
getHistoryStringPoolSize()11898     public int getHistoryStringPoolSize() {
11899         return mHistory.getHistoryStringPoolSize();
11900     }
11901 
11902     @Override
getHistoryStringPoolBytes()11903     public int getHistoryStringPoolBytes() {
11904         return mHistory.getHistoryStringPoolBytes();
11905     }
11906 
11907     @Override
getHistoryTagPoolString(int index)11908     public String getHistoryTagPoolString(int index) {
11909         return mHistory.getHistoryTagPoolString(index);
11910     }
11911 
11912     @Override
getHistoryTagPoolUid(int index)11913     public int getHistoryTagPoolUid(int index) {
11914         return mHistory.getHistoryTagPoolUid(index);
11915     }
11916 
11917     @Override
getStartCount()11918     public int getStartCount() {
11919         return mStartCount;
11920     }
11921 
isOnBattery()11922     public boolean isOnBattery() {
11923         return mOnBattery;
11924     }
11925 
isCharging()11926     public boolean isCharging() {
11927         return mCharging;
11928     }
11929 
initTimes(long uptimeUs, long realtimeUs)11930     void initTimes(long uptimeUs, long realtimeUs) {
11931         mStartClockTimeMs = mClock.currentTimeMillis();
11932         mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
11933         mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
11934         mRealtimeUs = 0;
11935         mUptimeUs = 0;
11936         mRealtimeStartUs = realtimeUs;
11937         mUptimeStartUs = uptimeUs;
11938         mMonotonicStartTime = mMonotonicClock.monotonicTime();
11939     }
11940 
initDischarge(long elapsedRealtimeUs)11941     void initDischarge(long elapsedRealtimeUs) {
11942         mLowDischargeAmountSinceCharge = 0;
11943         mHighDischargeAmountSinceCharge = 0;
11944         mDischargeAmountScreenOn = 0;
11945         mDischargeAmountScreenOnSinceCharge = 0;
11946         mDischargeAmountScreenOff = 0;
11947         mDischargeAmountScreenOffSinceCharge = 0;
11948         mDischargeAmountScreenDoze = 0;
11949         mDischargeAmountScreenDozeSinceCharge = 0;
11950         mDischargeStepTracker.init();
11951         mChargeStepTracker.init();
11952         mDischargeScreenOffCounter.reset(false, elapsedRealtimeUs);
11953         mDischargeScreenDozeCounter.reset(false, elapsedRealtimeUs);
11954         mDischargeLightDozeCounter.reset(false, elapsedRealtimeUs);
11955         mDischargeDeepDozeCounter.reset(false, elapsedRealtimeUs);
11956         mDischargeCounter.reset(false, elapsedRealtimeUs);
11957     }
11958 
11959     /**
11960      * Associates the BatteryStatsImpl object with a BatteryUsageStatsProvider and PowerStatsStore
11961      * to allow for a snapshot of battery usage stats to be taken and stored just before battery
11962      * reset.
11963      */
saveBatteryUsageStatsOnReset( @onNull BatteryUsageStatsProvider batteryUsageStatsProvider, @NonNull PowerStatsStore powerStatsStore, boolean accumulateBatteryUsageStats)11964     public void saveBatteryUsageStatsOnReset(
11965             @NonNull BatteryUsageStatsProvider batteryUsageStatsProvider,
11966             @NonNull PowerStatsStore powerStatsStore,
11967             boolean accumulateBatteryUsageStats) {
11968         mSaveBatteryUsageStatsOnReset = true;
11969         mBatteryUsageStatsProvider = batteryUsageStatsProvider;
11970         mPowerStatsStore = powerStatsStore;
11971         mAccumulateBatteryUsageStats = accumulateBatteryUsageStats;
11972     }
11973 
11974     /**
11975      * Enables or disables battery history reset at the beginning of a battery stats session.
11976      */
resetBatteryHistoryOnNewSession(boolean enabled)11977     public void resetBatteryHistoryOnNewSession(boolean enabled) {
11978         mResetBatteryHistoryOnNewSession = enabled;
11979     }
11980 
11981     /**
11982      * Enables or disables battery history file compression.
11983      */
setBatteryHistoryCompressionEnabled(boolean enabled)11984     public void setBatteryHistoryCompressionEnabled(boolean enabled) {
11985         mBatteryHistoryDirectory.setFileCompressionEnabled(enabled);
11986     }
11987 
11988     @GuardedBy("this")
resetAllStatsAndHistoryLocked(int reason)11989     public void resetAllStatsAndHistoryLocked(int reason) {
11990         final long mSecUptime = mClock.uptimeMillis();
11991         long uptimeUs = mSecUptime * 1000;
11992         long mSecRealtime = mClock.elapsedRealtime();
11993         long realtimeUs = mSecRealtime * 1000;
11994         resetAllStatsLocked(mSecUptime, mSecRealtime, reason);
11995         pullPendingStateUpdatesLocked();
11996         mHistory.writeHistoryItem(mSecRealtime, mSecUptime);
11997         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel = mBatteryLevel;
11998         mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
11999         mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
12000         if (!mBatteryPluggedIn) {
12001             if (Display.isOnState(mScreenState)) {
12002                 mDischargeScreenOnUnplugLevel = mBatteryLevel;
12003                 mDischargeScreenDozeUnplugLevel = 0;
12004                 mDischargeScreenOffUnplugLevel = 0;
12005             } else if (Display.isDozeState(mScreenState)) {
12006                 mDischargeScreenOnUnplugLevel = 0;
12007                 mDischargeScreenDozeUnplugLevel = mBatteryLevel;
12008                 mDischargeScreenOffUnplugLevel = 0;
12009             } else {
12010                 mDischargeScreenOnUnplugLevel = 0;
12011                 mDischargeScreenDozeUnplugLevel = 0;
12012                 mDischargeScreenOffUnplugLevel = mBatteryLevel;
12013             }
12014             mDischargeAmountScreenOn = 0;
12015             mDischargeAmountScreenOff = 0;
12016             mDischargeAmountScreenDoze = 0;
12017         }
12018         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
12019     }
12020 
12021     /**
12022      * Starts a new battery stats session, resetting counters and timers. If this method is called
12023      * before MIN_BATTERY_SESSION_DURATION_MILLIS from the beginning of the current session, the
12024      * call is ignored.
12025      */
startNewSession(int reason)12026     public void startNewSession(int reason) {
12027         if (mMonotonicClock.monotonicTime()
12028                 < mMonotonicStartTime + MIN_BATTERY_SESSION_DURATION_MILLIS) {
12029             Slog.i(TAG, "Battery session session duration is too short, ignoring reset request");
12030             return;
12031         }
12032 
12033         mHandler.post(()-> {
12034             saveBatteryUsageStatsOnReset();
12035             synchronized (BatteryStatsImpl.this) {
12036                 resetAllStatsLocked(mClock.uptimeMillis(), mClock.elapsedRealtime(), reason);
12037             }
12038         });
12039     }
12040 
12041     @GuardedBy("this")
resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis, int resetReason)12042     private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis,
12043             int resetReason) {
12044         final long uptimeUs = uptimeMillis * 1000;
12045         final long elapsedRealtimeUs = elapsedRealtimeMillis * 1000;
12046         mStartCount = 0;
12047         initTimes(uptimeUs, elapsedRealtimeUs);
12048         mScreenOnTimer.reset(false, elapsedRealtimeUs);
12049         mScreenDozeTimer.reset(false, elapsedRealtimeUs);
12050         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
12051             mScreenBrightnessTimer[i].reset(false, elapsedRealtimeUs);
12052         }
12053 
12054         final int numDisplays = mPerDisplayBatteryStats.length;
12055         for (int i = 0; i < numDisplays; i++) {
12056             mPerDisplayBatteryStats[i].reset(elapsedRealtimeUs);
12057         }
12058 
12059         if (mPowerProfile != null) {
12060             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
12061         } else {
12062             mEstimatedBatteryCapacityMah = -1;
12063         }
12064         mLastLearnedBatteryCapacityUah = -1;
12065         mMinLearnedBatteryCapacityUah = -1;
12066         mMaxLearnedBatteryCapacityUah = -1;
12067         mInteractiveTimer.reset(false, elapsedRealtimeUs);
12068         mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs);
12069         mLastIdleTimeStartMs = elapsedRealtimeMillis;
12070         mLongestLightIdleTimeMs = 0;
12071         mLongestFullIdleTimeMs = 0;
12072         mDeviceIdleModeLightTimer.reset(false, elapsedRealtimeUs);
12073         mDeviceIdleModeFullTimer.reset(false, elapsedRealtimeUs);
12074         mDeviceLightIdlingTimer.reset(false, elapsedRealtimeUs);
12075         mDeviceIdlingTimer.reset(false, elapsedRealtimeUs);
12076         mPhoneOnTimer.reset(false, elapsedRealtimeUs);
12077         mAudioOnTimer.reset(false, elapsedRealtimeUs);
12078         mVideoOnTimer.reset(false, elapsedRealtimeUs);
12079         mFlashlightOnTimer.reset(false, elapsedRealtimeUs);
12080         mCameraOnTimer.reset(false, elapsedRealtimeUs);
12081         mBluetoothScanTimer.reset(false, elapsedRealtimeUs);
12082         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
12083             mPhoneSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
12084         }
12085         mPhoneSignalScanningTimer.reset(false, elapsedRealtimeUs);
12086         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
12087             mPhoneDataConnectionsTimer[i].reset(false, elapsedRealtimeUs);
12088         }
12089         mNrNsaTimer.reset(false, elapsedRealtimeUs);
12090         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
12091             mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs);
12092             mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs);
12093         }
12094         for (int i = 0; i < RADIO_ACCESS_TECHNOLOGY_COUNT; i++) {
12095             final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[i];
12096             if (stats == null) continue;
12097             stats.reset(elapsedRealtimeUs);
12098         }
12099         mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs);
12100         mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs);
12101         mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs);
12102         mMobileRadioActiveUnknownTime.reset(false, elapsedRealtimeUs);
12103         mMobileRadioActiveUnknownCount.reset(false, elapsedRealtimeUs);
12104         mWifiOnTimer.reset(false, elapsedRealtimeUs);
12105         mGlobalWifiRunningTimer.reset(false, elapsedRealtimeUs);
12106         for (int i=0; i<NUM_WIFI_STATES; i++) {
12107             mWifiStateTimer[i].reset(false, elapsedRealtimeUs);
12108         }
12109         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12110             mWifiSupplStateTimer[i].reset(false, elapsedRealtimeUs);
12111         }
12112         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12113             mWifiSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
12114         }
12115         mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs);
12116         mWifiActiveTimer.reset(false, elapsedRealtimeUs);
12117         mWifiActivity.reset(false, elapsedRealtimeUs);
12118         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
12119             mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs);
12120         }
12121         mBluetoothActivity.reset(false, elapsedRealtimeUs);
12122         mModemActivity.reset(false, elapsedRealtimeUs);
12123         mNumConnectivityChange = 0;
12124 
12125         for (int i=0; i<mUidStats.size(); i++) {
12126             if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs, resetReason)) {
12127                 mUidStats.valueAt(i).detachFromTimeBase();
12128                 mUidStats.remove(mUidStats.keyAt(i));
12129                 i--;
12130             }
12131         }
12132 
12133         if (mRpmStats.size() > 0) {
12134             for (SamplingTimer timer : mRpmStats.values()) {
12135                 mOnBatteryTimeBase.remove(timer);
12136             }
12137             mRpmStats.clear();
12138         }
12139         if (mScreenOffRpmStats.size() > 0) {
12140             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
12141                 mOnBatteryScreenOffTimeBase.remove(timer);
12142             }
12143             mScreenOffRpmStats.clear();
12144         }
12145 
12146         if (mKernelWakelockStats.size() > 0) {
12147             for (SamplingTimer timer : mKernelWakelockStats.values()) {
12148                 mOnBatteryScreenOffTimeBase.remove(timer);
12149             }
12150             mKernelWakelockStats.clear();
12151         }
12152 
12153         if (mKernelMemoryStats.size() > 0) {
12154             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
12155                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
12156             }
12157             mKernelMemoryStats.clear();
12158         }
12159 
12160         if (mWakeupReasonStats.size() > 0) {
12161             for (SamplingTimer timer : mWakeupReasonStats.values()) {
12162                 mOnBatteryTimeBase.remove(timer);
12163             }
12164             mWakeupReasonStats.clear();
12165         }
12166 
12167         mStepDetailsProvider.reset();
12168 
12169         if (mTmpRailStats != null) {
12170             mTmpRailStats.reset();
12171         }
12172 
12173         EnergyConsumerStats.resetIfNotNull(mGlobalEnergyConsumerStats);
12174 
12175         if (!Flags.disableSystemServicePowerAttr()) {
12176             resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
12177         }
12178 
12179         mNumAllUidCpuTimeReads = 0;
12180         mNumUidsRemoved = 0;
12181 
12182         initDischarge(elapsedRealtimeUs);
12183 
12184         if ((resetReason != RESET_REASON_FULL_CHARGE
12185                 && resetReason != RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION)
12186                 || mResetBatteryHistoryOnNewSession) {
12187             mHistory.reset();
12188         }
12189 
12190         // Store the empty state to disk to ensure consistency
12191         writeSyncLocked();
12192 
12193         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
12194             schedulePowerStatsSampleCollection();
12195         }
12196 
12197         // Flush external data, gathering snapshots, but don't process it since it is pre-reset data
12198         mIgnoreNextExternalStats = true;
12199         mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ON_RESET);
12200 
12201         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
12202     }
12203 
saveBatteryUsageStatsOnReset()12204     private void saveBatteryUsageStatsOnReset() {
12205         if (!mSaveBatteryUsageStatsOnReset) {
12206             return;
12207         }
12208 
12209         if (mAccumulateBatteryUsageStats) {
12210             mBatteryUsageStatsProvider.accumulateBatteryUsageStats(getBatteryStatsSession(),
12211                     mHandler);
12212         } else {
12213             final BatteryUsageStats batteryUsageStats;
12214             synchronized (this) {
12215                 batteryUsageStats = mBatteryUsageStatsProvider.getBatteryUsageStats(this,
12216                         new BatteryUsageStatsQuery.Builder()
12217                                 .setMaxStatsAgeMs(0)
12218                                 .includePowerModels()
12219                                 .includeProcessStateData()
12220                                 .build());
12221             }
12222 
12223             // TODO(b/188068523): BatteryUsageStats should use monotonic time for start and end
12224             // Once that change is made, we will be able to use the BatteryUsageStats' monotonic
12225             // start time
12226             long monotonicStartTime =
12227                     mMonotonicClock.monotonicTime() - batteryUsageStats.getStatsDuration();
12228             commitMonotonicClock();
12229             mPowerStatsStore.storeBatteryUsageStatsAsync(monotonicStartTime, batteryUsageStats);
12230         }
12231     }
12232 
12233     @GuardedBy("this")
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)12234     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
12235         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
12236             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
12237                 // Not recording process starts/stops.
12238                 continue;
12239             }
12240             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
12241             if (active == null) {
12242                 continue;
12243             }
12244             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
12245                 SparseIntArray uids = ent.getValue();
12246                 for (int j=0; j<uids.size(); j++) {
12247                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
12248                             uids.keyAt(j));
12249                 }
12250             }
12251         }
12252     }
12253 
12254     @GuardedBy("this")
updateDischargeScreenLevelsLocked(int oldState, int newState)12255     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
12256         updateOldDischargeScreenLevelLocked(oldState);
12257         updateNewDischargeScreenLevelLocked(newState);
12258     }
12259 
12260     @GuardedBy("this")
updateOldDischargeScreenLevelLocked(int state)12261     private void updateOldDischargeScreenLevelLocked(int state) {
12262         if (Display.isOnState(state)) {
12263             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
12264             if (diff > 0) {
12265                 mDischargeAmountScreenOn += diff;
12266                 mDischargeAmountScreenOnSinceCharge += diff;
12267             }
12268         } else if (Display.isDozeState(state)) {
12269             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
12270             if (diff > 0) {
12271                 mDischargeAmountScreenDoze += diff;
12272                 mDischargeAmountScreenDozeSinceCharge += diff;
12273             }
12274         } else if (Display.isOffState(state)) {
12275             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
12276             if (diff > 0) {
12277                 mDischargeAmountScreenOff += diff;
12278                 mDischargeAmountScreenOffSinceCharge += diff;
12279             }
12280         }
12281     }
12282 
12283     @GuardedBy("this")
updateNewDischargeScreenLevelLocked(int state)12284     private void updateNewDischargeScreenLevelLocked(int state) {
12285         if (Display.isOnState(state)) {
12286             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
12287             mDischargeScreenOffUnplugLevel = 0;
12288             mDischargeScreenDozeUnplugLevel = 0;
12289         } else if (Display.isDozeState(state)) {
12290             mDischargeScreenOnUnplugLevel = 0;
12291             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
12292             mDischargeScreenOffUnplugLevel = 0;
12293         } else if (Display.isOffState(state)) {
12294             mDischargeScreenOnUnplugLevel = 0;
12295             mDischargeScreenDozeUnplugLevel = 0;
12296             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
12297         }
12298     }
12299 
12300     @GuardedBy("this")
pullPendingStateUpdatesLocked()12301     public void pullPendingStateUpdatesLocked() {
12302         if (mOnBatteryInternal) {
12303             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
12304         }
12305     }
12306 
12307     private final Object mWifiNetworkLock = new Object();
12308 
12309     @GuardedBy("mWifiNetworkLock")
12310     private String[] mWifiIfaces = EmptyArray.STRING;
12311 
12312     @GuardedBy("mWifiNetworkLock")
12313     private NetworkStats mLastWifiNetworkStats;
12314 
12315     private final Object mModemNetworkLock = new Object();
12316 
12317     @GuardedBy("mModemNetworkLock")
12318     private String[] mModemIfaces = EmptyArray.STRING;
12319 
12320     @GuardedBy("mModemNetworkLock")
12321     private NetworkStats mLastModemNetworkStats;
12322 
12323     @VisibleForTesting
readMobileNetworkStatsLocked( @onNull NetworkStatsManager networkStatsManager)12324     protected NetworkStats readMobileNetworkStatsLocked(
12325             @NonNull NetworkStatsManager networkStatsManager) {
12326         return networkStatsManager.getMobileUidStats();
12327     }
12328 
12329     @VisibleForTesting
readWifiNetworkStatsLocked( @onNull NetworkStatsManager networkStatsManager)12330     protected NetworkStats readWifiNetworkStatsLocked(
12331             @NonNull NetworkStatsManager networkStatsManager) {
12332         return networkStatsManager.getWifiUidStats();
12333     }
12334 
12335     @VisibleForTesting
networkStatsDelta(@onNull NetworkStats stats, @Nullable NetworkStats oldStats)12336     protected NetworkStats networkStatsDelta(@NonNull NetworkStats stats,
12337             @Nullable NetworkStats oldStats) {
12338         if (oldStats == null) {
12339             return stats;
12340         }
12341         return stats.subtract(oldStats);
12342     }
12343 
12344     /**
12345      * Distribute WiFi energy info and network traffic to apps.
12346      *
12347      * @param info The energy information from the WiFi controller.
12348      */
12349     @GuardedBy("this")
updateWifiState(@ullable final WifiActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager)12350     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
12351             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
12352             @NonNull NetworkStatsManager networkStatsManager) {
12353         if (DEBUG_ENERGY) {
12354             synchronized (mWifiNetworkLock) {
12355                 Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
12356             }
12357         }
12358 
12359         NetworkStats delta;
12360         // Grab a separate lock to acquire the network stats, which may do I/O.
12361         synchronized (mWifiNetworkLock) {
12362             final NetworkStats latestStats = readWifiNetworkStatsLocked(networkStatsManager);
12363             if (latestStats != null) {
12364                 delta = networkStatsDelta(latestStats, mLastWifiNetworkStats);
12365                 mLastWifiNetworkStats = latestStats;
12366             } else {
12367                 delta = null;
12368             }
12369         }
12370         updateWifiBatteryStats(info, delta, consumedChargeUC, elapsedRealtimeMs, uptimeMs);
12371     }
12372 
onWifiPowerStatsRetrieved(WifiActivityEnergyInfo wifiActivityEnergyInfo, NetworkStats networkStatsDelta, long elapsedRealtimeMs, long uptimeMs)12373     private void onWifiPowerStatsRetrieved(WifiActivityEnergyInfo wifiActivityEnergyInfo,
12374             NetworkStats networkStatsDelta, long elapsedRealtimeMs, long uptimeMs) {
12375         // Do not populate consumed energy, because energy attribution is done by
12376         // WifiPowerStatsProcessor.
12377         updateWifiBatteryStats(wifiActivityEnergyInfo, networkStatsDelta, POWER_DATA_UNAVAILABLE,
12378                 elapsedRealtimeMs, uptimeMs);
12379     }
12380 
updateWifiBatteryStats(WifiActivityEnergyInfo info, NetworkStats delta, long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)12381     private void updateWifiBatteryStats(WifiActivityEnergyInfo info,
12382             NetworkStats delta, long consumedChargeUC, long elapsedRealtimeMs,
12383             long uptimeMs) {
12384         synchronized (this) {
12385             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12386                 if (mIgnoreNextExternalStats) {
12387                     // TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
12388                     //  global one) here like we do for display. But I'm not sure it's worth the
12389                     //  complicated code for a codepath that shouldn't ever actually happen in real
12390                     //  life.
12391                 }
12392                 return;
12393             }
12394 
12395             final SparseDoubleArray uidEstimatedConsumptionMah =
12396                     (mGlobalEnergyConsumerStats != null
12397                             && mWifiPowerCalculator != null && consumedChargeUC > 0) ?
12398                             new SparseDoubleArray() : null;
12399             double totalEstimatedConsumptionMah = 0;
12400 
12401             SparseLongArray rxPackets = new SparseLongArray();
12402             SparseLongArray txPackets = new SparseLongArray();
12403             SparseLongArray rxTimesMs = new SparseLongArray();
12404             SparseLongArray txTimesMs = new SparseLongArray();
12405             long totalTxPackets = 0;
12406             long totalRxPackets = 0;
12407             if (delta != null) {
12408                 for (NetworkStats.Entry entry : delta) {
12409                     if (DEBUG_ENERGY) {
12410                         Slog.d(TAG, "Wifi uid " + entry.getUid()
12411                                 + ": delta rx=" + entry.getRxBytes()
12412                                 + " tx=" + entry.getTxBytes()
12413                                 + " rxPackets=" + entry.getRxPackets()
12414                                 + " txPackets=" + entry.getTxPackets());
12415                     }
12416 
12417                     if (entry.getRxBytes() == 0 && entry.getTxBytes() == 0) {
12418                         // Skip the lookup below since there is no work to do.
12419                         continue;
12420                     }
12421 
12422                     final int uid = mapUid(entry.getUid());
12423                     final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
12424                     if (entry.getRxBytes() != 0) {
12425                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.getRxBytes(),
12426                                 entry.getRxPackets());
12427                         if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
12428                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.getRxBytes(),
12429                                     entry.getRxPackets());
12430                         }
12431                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
12432                                 entry.getRxBytes());
12433                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
12434                                 entry.getRxPackets());
12435 
12436                         rxPackets.incrementValue(uid, entry.getRxPackets());
12437 
12438                         // Sum the total number of packets so that the Rx Power can
12439                         // be evenly distributed amongst the apps.
12440                         totalRxPackets += entry.getRxPackets();
12441                     }
12442 
12443                     if (entry.getTxBytes() != 0) {
12444                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.getTxBytes(),
12445                                 entry.getTxPackets());
12446                         if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
12447                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.getTxBytes(),
12448                                     entry.getTxPackets());
12449                         }
12450                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
12451                                 entry.getTxBytes());
12452                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
12453                                 entry.getTxPackets());
12454 
12455                         txPackets.incrementValue(uid, entry.getTxPackets());
12456 
12457                         // Sum the total number of packets so that the Tx Power can
12458                         // be evenly distributed amongst the apps.
12459                         totalTxPackets += entry.getTxPackets();
12460                     }
12461 
12462                     // Calculate consumed energy for this uid. Only do so if WifiReporting isn't
12463                     // enabled (if it is, we'll do it later instead using info).
12464                     if (uidEstimatedConsumptionMah != null && info == null && !mHasWifiReporting) {
12465                         final long uidRunningMs = u.mWifiRunningTimer
12466                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12467                         if (uidRunningMs > 0) u.mWifiRunningTimer.setMark(elapsedRealtimeMs);
12468 
12469                         final long uidScanMs = u.mWifiScanTimer
12470                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12471                         if (uidScanMs > 0) u.mWifiScanTimer.setMark(elapsedRealtimeMs);
12472 
12473                         long uidBatchScanMs = 0;
12474                         for (int bn = 0; bn < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bn++) {
12475                             if (u.mWifiBatchedScanTimer[bn] != null) {
12476                                 long bnMs = u.mWifiBatchedScanTimer[bn]
12477                                         .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12478                                 if (bnMs > 0) {
12479                                     u.mWifiBatchedScanTimer[bn].setMark(elapsedRealtimeMs);
12480                                 }
12481                                 uidBatchScanMs += bnMs;
12482                             }
12483                         }
12484 
12485                         uidEstimatedConsumptionMah.incrementValue(u.getUid(),
12486                                 mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
12487                                         entry.getRxPackets(), entry.getTxPackets(),
12488                                         uidRunningMs, uidScanMs, uidBatchScanMs));
12489                     }
12490                 }
12491                 delta = null;
12492             }
12493 
12494             if (info != null) {
12495                 mHasWifiReporting = true;
12496 
12497                 // Measured in mAms
12498                 final long txTimeMs = info.getControllerTxDurationMillis();
12499                 final long rxTimeMs = info.getControllerRxDurationMillis();
12500                 final long scanTimeMs = info.getControllerScanDurationMillis();
12501                 final long idleTimeMs = info.getControllerIdleDurationMillis();
12502                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
12503 
12504                 long leftOverRxTimeMs = rxTimeMs;
12505                 long leftOverTxTimeMs = txTimeMs;
12506 
12507                 if (DEBUG_ENERGY) {
12508                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
12509                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
12510                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
12511                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
12512                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
12513                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
12514                 }
12515 
12516                 long totalWifiLockTimeMs = 0;
12517                 long totalScanTimeMs = 0;
12518 
12519                 // On the first pass, collect some totals so that we can normalize power
12520                 // calculations if we need to.
12521                 final int uidStatsSize = mUidStats.size();
12522                 for (int i = 0; i < uidStatsSize; i++) {
12523                     final Uid uid = mUidStats.valueAt(i);
12524 
12525                     // Sum the total scan power for all apps.
12526                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
12527                             elapsedRealtimeMs * 1000) / 1000;
12528 
12529                     // Sum the total time holding wifi lock for all apps.
12530                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
12531                             elapsedRealtimeMs * 1000) / 1000;
12532                 }
12533 
12534                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
12535                     Slog.d(TAG,
12536                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
12537                                     + rxTimeMs + " ms). Normalizing scan time.");
12538                 }
12539                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
12540                     Slog.d(TAG,
12541                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
12542                                     + txTimeMs + " ms). Normalizing scan time.");
12543                 }
12544 
12545                 // Actually assign and distribute power usage to apps.
12546                 for (int i = 0; i < uidStatsSize; i++) {
12547                     final Uid uid = mUidStats.valueAt(i);
12548 
12549                     final long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
12550                             elapsedRealtimeMs * 1000) / 1000;
12551                     long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
12552                     long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
12553                     if (scanTimeSinceMarkMs > 0) {
12554                         // Set the new mark so that next time we get new data since this point.
12555                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
12556 
12557                         // Our total scan time is more than the reported Tx/Rx time.
12558                         // This is possible because the cost of a scan is approximate.
12559                         // Let's normalize the result so that we evenly blame each app
12560                         // scanning.
12561                         //
12562                         // This means that we may have apps that transmitted/received packets not be
12563                         // blamed for this, but this is fine as scans are relatively more expensive.
12564                         if (totalScanTimeMs > rxTimeMs) {
12565                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
12566                                     totalScanTimeMs;
12567                         }
12568                         if (totalScanTimeMs > txTimeMs) {
12569                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
12570                                     totalScanTimeMs;
12571                         }
12572 
12573                         if (DEBUG_ENERGY) {
12574                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
12575                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
12576                                     + scanTxTimeSinceMarkMs + " ms)");
12577                         }
12578 
12579                         rxTimesMs.incrementValue(uid.getUid(), scanRxTimeSinceMarkMs);
12580                         txTimesMs.incrementValue(uid.getUid(), scanTxTimeSinceMarkMs);
12581 
12582                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
12583                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
12584                     }
12585 
12586                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
12587                     // lock.
12588                     long myIdleTimeMs = 0;
12589                     final long wifiLockTimeSinceMarkMs =
12590                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
12591                                     elapsedRealtimeMs * 1000) / 1000;
12592                     if (wifiLockTimeSinceMarkMs > 0) {
12593                         // Set the new mark so that next time we get new data since this point.
12594                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
12595 
12596                         myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) / totalWifiLockTimeMs;
12597                         if (DEBUG_ENERGY) {
12598                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
12599                                     + myIdleTimeMs + " ms");
12600                         }
12601                         uid.getOrCreateWifiControllerActivityLocked().getOrCreateIdleTimeCounter()
12602                                 .increment(myIdleTimeMs, elapsedRealtimeMs);
12603                     }
12604 
12605                     if (uidEstimatedConsumptionMah != null) {
12606                         double uidEstMah = mWifiPowerCalculator.calcPowerFromControllerDataMah(
12607                                 scanRxTimeSinceMarkMs, scanTxTimeSinceMarkMs, myIdleTimeMs);
12608                         uidEstimatedConsumptionMah.incrementValue(uid.getUid(), uidEstMah);
12609                     }
12610                 }
12611 
12612                 if (DEBUG_ENERGY) {
12613                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
12614                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
12615                 }
12616 
12617                 // Distribute the remaining Tx power appropriately between all apps that transmitted
12618                 // packets.
12619                 if (totalTxPackets != 0 && leftOverTxTimeMs != 0) {
12620                     for (int i = 0; i < txPackets.size(); i++) {
12621                         final int uid = txPackets.keyAt(i);
12622                         final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
12623                                 / totalTxPackets;
12624                         txTimesMs.incrementValue(uid, myTxTimeMs);
12625                     }
12626                 }
12627 
12628                 // Distribute the remaining Rx power appropriately between all apps that received
12629                 // packets.
12630                 if (totalRxPackets != 0 && leftOverRxTimeMs != 0) {
12631                     for (int i = 0; i < rxPackets.size(); i++) {
12632                         final int uid = rxPackets.keyAt(i);
12633                         final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
12634                                 / totalRxPackets;
12635                         rxTimesMs.incrementValue(uid, myRxTimeMs);
12636                     }
12637                 }
12638 
12639                 for (int i = 0; i < txTimesMs.size(); i++) {
12640                     final int uid = txTimesMs.keyAt(i);
12641                     final long myTxTimeMs = txTimesMs.valueAt(i);
12642                     if (DEBUG_ENERGY) {
12643                         Slog.d(TAG, "  TxTime for UID " + uid + ": " + myTxTimeMs + " ms");
12644                     }
12645                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
12646                             .getOrCreateWifiControllerActivityLocked()
12647                             .getOrCreateTxTimeCounters()[0]
12648                             .increment(myTxTimeMs, elapsedRealtimeMs);
12649                     if (uidEstimatedConsumptionMah != null) {
12650                         uidEstimatedConsumptionMah.incrementValue(uid,
12651                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
12652                                         0, myTxTimeMs, 0));
12653                     }
12654                 }
12655 
12656                 for (int i = 0; i < rxTimesMs.size(); i++) {
12657                     final int uid = rxTimesMs.keyAt(i);
12658                     final long myRxTimeMs = rxTimesMs.valueAt(i);
12659                     if (DEBUG_ENERGY) {
12660                         Slog.d(TAG, "  RxTime for UID " + uid + ": " + myRxTimeMs + " ms");
12661                     }
12662 
12663                     getUidStatsLocked(rxTimesMs.keyAt(i), elapsedRealtimeMs, uptimeMs)
12664                             .getOrCreateWifiControllerActivityLocked()
12665                             .getOrCreateRxTimeCounter()
12666                             .increment(myRxTimeMs, elapsedRealtimeMs);
12667                     if (uidEstimatedConsumptionMah != null) {
12668                         uidEstimatedConsumptionMah.incrementValue(uid,
12669                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
12670                                         myRxTimeMs, 0, 0));
12671                     }
12672                 }
12673 
12674                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
12675 
12676                 // Update WiFi controller stats.
12677                 mWifiActivity.getOrCreateRxTimeCounter().increment(
12678                         info.getControllerRxDurationMillis(), elapsedRealtimeMs);
12679                 mWifiActivity.getOrCreateTxTimeCounters()[0].increment(
12680                         info.getControllerTxDurationMillis(), elapsedRealtimeMs);
12681                 mWifiActivity.getScanTimeCounter().addCountLocked(
12682                         info.getControllerScanDurationMillis());
12683                 mWifiActivity.getOrCreateIdleTimeCounter().increment(
12684                         info.getControllerIdleDurationMillis(), elapsedRealtimeMs);
12685 
12686                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12687                 final double opVolt = mPowerProfile.getAveragePower(
12688                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12689                 double controllerMaMs = 0;
12690                 if (opVolt != 0) {
12691                     // We store the power drain as mAms.
12692                     controllerMaMs = info.getControllerEnergyUsedMicroJoules() / opVolt;
12693                     mWifiActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
12694                 }
12695                 // Converting uWs to mAms.
12696                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
12697                 long monitoredRailChargeConsumedMaMs = mTmpRailStats != null
12698                         ? (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt)
12699                         : 0L;
12700                 mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
12701                         monitoredRailChargeConsumedMaMs);
12702                 mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
12703                         (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
12704                 if (mTmpRailStats != null) {
12705                     mTmpRailStats.resetWifiTotalEnergyUsed();
12706                 }
12707 
12708                 if (uidEstimatedConsumptionMah != null) {
12709                     totalEstimatedConsumptionMah = Math.max(controllerMaMs / MILLISECONDS_IN_HOUR,
12710                             mWifiPowerCalculator.calcPowerFromControllerDataMah(
12711                                     rxTimeMs, txTimeMs, idleTimeMs));
12712                 }
12713             }
12714 
12715             // Update the EnergyConsumerStats information.
12716             if (uidEstimatedConsumptionMah != null) {
12717                 mGlobalEnergyConsumerStats.updateStandardBucket(
12718                         EnergyConsumerStats.POWER_BUCKET_WIFI, consumedChargeUC);
12719 
12720                 // Now calculate the consumption for each uid, according to its proportional usage.
12721                 if (!mHasWifiReporting) {
12722                     final long globalTimeMs = mGlobalWifiRunningTimer
12723                             .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12724                     mGlobalWifiRunningTimer.setMark(elapsedRealtimeMs);
12725                     totalEstimatedConsumptionMah = mWifiPowerCalculator
12726                             .calcGlobalPowerWithoutControllerDataMah(globalTimeMs);
12727                 }
12728                 distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_WIFI,
12729                         consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah,
12730                         elapsedRealtimeMs);
12731             }
12732         }
12733     }
12734 
12735     private ModemActivityInfo mLastModemActivityInfo = null;
12736 
12737     /**
12738      * Distribute Cell radio energy info and network traffic to apps.
12739      */
noteModemControllerActivity(@ullable final ModemActivityInfo activityInfo, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager)12740     public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo,
12741             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
12742             @NonNull NetworkStatsManager networkStatsManager) {
12743         if (DEBUG_ENERGY) {
12744             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
12745         }
12746         ModemActivityInfo deltaInfo = mLastModemActivityInfo == null
12747                 ? (activityInfo == null ? null : activityInfo.getDelta(activityInfo))
12748                 : mLastModemActivityInfo.getDelta(activityInfo);
12749         mLastModemActivityInfo = activityInfo;
12750 
12751         // Grab a separate lock to acquire the network stats, which may do I/O.
12752         NetworkStats delta = null;
12753         synchronized (mModemNetworkLock) {
12754             final NetworkStats latestStats = readMobileNetworkStatsLocked(networkStatsManager);
12755             if (latestStats != null) {
12756                 delta = networkStatsDelta(latestStats, mLastModemNetworkStats);
12757                 mLastModemNetworkStats = latestStats;
12758             }
12759         }
12760 
12761         updateCellularBatteryStats(deltaInfo, delta, consumedChargeUC, elapsedRealtimeMs, uptimeMs);
12762     }
12763 
onMobileRadioPowerStatsRetrieved(ModemActivityInfo modemActivityInfo, NetworkStats networkStatsDelta, long elapsedRealtimeMs, long uptimeMs)12764     private void onMobileRadioPowerStatsRetrieved(ModemActivityInfo modemActivityInfo,
12765             NetworkStats networkStatsDelta, long elapsedRealtimeMs, long uptimeMs) {
12766         // Do not populate consumed energy, because energy attribution is done by
12767         // MobileRadioPowerStatsProcessor.
12768         updateCellularBatteryStats(modemActivityInfo, networkStatsDelta, POWER_DATA_UNAVAILABLE,
12769                 elapsedRealtimeMs, uptimeMs);
12770     }
12771 
updateCellularBatteryStats(@ullable ModemActivityInfo deltaInfo, @Nullable NetworkStats delta, long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)12772     private void updateCellularBatteryStats(@Nullable ModemActivityInfo deltaInfo,
12773             @Nullable NetworkStats delta, long consumedChargeUC, long elapsedRealtimeMs,
12774             long uptimeMs) {
12775         // Add modem tx power to history.
12776         addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs);
12777 
12778         synchronized (this) {
12779             final long totalRadioDurationMs =
12780                     mMobileRadioActiveTimer.getTimeSinceMarkLocked(
12781                             elapsedRealtimeMs * 1000) / 1000;
12782             mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
12783             final long phoneOnDurationMs = Math.min(totalRadioDurationMs,
12784                     mPhoneOnTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000);
12785             mPhoneOnTimer.setMark(elapsedRealtimeMs);
12786 
12787             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12788                 return;
12789             }
12790 
12791             final SparseDoubleArray uidEstimatedConsumptionMah;
12792             final long dataConsumedChargeUC;
12793             if (consumedChargeUC > 0 && isMobileRadioEnergyConsumerSupportedLocked()) {
12794                 final long phoneConsumedChargeUC;
12795                 if (totalRadioDurationMs == 0) {
12796                     phoneConsumedChargeUC = 0;
12797                 } else {
12798                     // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the
12799                     // numerator for long rounding.
12800                     phoneConsumedChargeUC =
12801                             (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2)
12802                                     / totalRadioDurationMs;
12803                 }
12804                 dataConsumedChargeUC = consumedChargeUC - phoneConsumedChargeUC;
12805 
12806                 mGlobalEnergyConsumerStats.updateStandardBucket(
12807                         EnergyConsumerStats.POWER_BUCKET_PHONE, phoneConsumedChargeUC);
12808                 mGlobalEnergyConsumerStats.updateStandardBucket(
12809                         EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, dataConsumedChargeUC);
12810                 uidEstimatedConsumptionMah = new SparseDoubleArray();
12811             } else {
12812                 uidEstimatedConsumptionMah = null;
12813                 dataConsumedChargeUC = POWER_DATA_UNAVAILABLE;
12814             }
12815 
12816             RxTxConsumption rxTxConsumption = null;
12817             boolean attributeWithModemActivityInfo = false;
12818             if (deltaInfo != null) {
12819                 mHasModemReporting = true;
12820                 mModemActivity.getOrCreateIdleTimeCounter()
12821                         .increment(deltaInfo.getIdleTimeMillis(), elapsedRealtimeMs);
12822                 mModemActivity.getSleepTimeCounter().addCountLocked(
12823                         deltaInfo.getSleepTimeMillis());
12824                 mModemActivity.getOrCreateRxTimeCounter()
12825                         .increment(deltaInfo.getReceiveTimeMillis(), elapsedRealtimeMs);
12826                 for (int lvl = 0; lvl < MODEM_TX_POWER_LEVEL_COUNT; lvl++) {
12827                     mModemActivity.getOrCreateTxTimeCounters()[lvl]
12828                             .increment(deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl),
12829                                     elapsedRealtimeMs);
12830                 }
12831 
12832                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12833                 final double opVolt = mPowerProfile.getAveragePower(
12834                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12835                 if (opVolt != 0) {
12836                     double energyUsed =
12837                             deltaInfo.getSleepTimeMillis() *
12838                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
12839                             + deltaInfo.getIdleTimeMillis() *
12840                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
12841                             + deltaInfo.getReceiveTimeMillis() *
12842                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
12843                     for (int i = 0; i < Math.min(MODEM_TX_POWER_LEVEL_COUNT,
12844                             CELL_SIGNAL_STRENGTH_LEVEL_COUNT); i++) {
12845                         energyUsed += deltaInfo.getTransmitDurationMillisAtPowerLevel(i)
12846                                 * mPowerProfile.getAveragePower(
12847                                         PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
12848                     }
12849 
12850                     // We store the power drain as mAms.
12851                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
12852                     // Converting uWs to mAms.
12853                     // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
12854                     long monitoredRailChargeConsumedMaMs =
12855                             (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
12856                     mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
12857                             monitoredRailChargeConsumedMaMs);
12858                     mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
12859                             (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
12860                     mTmpRailStats.resetCellularTotalEnergyUsed();
12861                 }
12862 
12863                 rxTxConsumption = incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs);
12864 
12865                 attributeWithModemActivityInfo = mConstants.PER_UID_MODEM_MODEL
12866                         == PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX
12867                         && rxTxConsumption != null;
12868             }
12869             long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
12870                     elapsedRealtimeMs * 1000);
12871             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
12872 
12873             long totalRxPackets = 0;
12874             long totalTxPackets = 0;
12875             if (delta != null) {
12876                 for (NetworkStats.Entry entry : delta) {
12877                     if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
12878                         continue;
12879                     }
12880 
12881                     if (DEBUG_ENERGY) {
12882                         Slog.d(TAG, "Mobile uid " + entry.getUid() + ": delta rx="
12883                                 + entry.getRxBytes() + " tx=" + entry.getTxBytes()
12884                                 + " rxPackets=" + entry.getRxPackets()
12885                                 + " txPackets=" + entry.getTxPackets());
12886                     }
12887 
12888                     totalRxPackets += entry.getRxPackets();
12889                     totalTxPackets += entry.getTxPackets();
12890 
12891                     final Uid u = getUidStatsLocked(
12892                             mapUid(entry.getUid()), elapsedRealtimeMs, uptimeMs);
12893                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.getRxBytes(),
12894                             entry.getRxPackets());
12895                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.getTxBytes(),
12896                             entry.getTxPackets());
12897                     if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
12898                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
12899                                 entry.getRxBytes(), entry.getRxPackets());
12900                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
12901                                 entry.getTxBytes(), entry.getTxPackets());
12902                     }
12903 
12904                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
12905                             entry.getRxBytes());
12906                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12907                             entry.getTxBytes());
12908                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
12909                             entry.getRxPackets());
12910                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12911                             entry.getTxPackets());
12912                 }
12913 
12914                 // Now distribute proportional blame to the apps that did networking.
12915                 long totalPackets = totalRxPackets + totalTxPackets;
12916                 if (totalPackets > 0) {
12917                     for (NetworkStats.Entry entry : delta) {
12918                         if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
12919                             continue;
12920                         }
12921 
12922                         final Uid u = getUidStatsLocked(mapUid(entry.getUid()),
12923                                 elapsedRealtimeMs, uptimeMs);
12924 
12925                         // Distribute total radio active time in to this app.
12926                         final long appPackets = entry.getRxPackets() + entry.getTxPackets();
12927                         final long appRadioTimeUs =
12928                                 (totalAppRadioTimeUs * appPackets) / totalPackets;
12929                         u.noteMobileRadioActiveTimeLocked(appRadioTimeUs, elapsedRealtimeMs);
12930 
12931                         if (uidEstimatedConsumptionMah != null) {
12932                             final double uidConsumptionMah;
12933                             if (attributeWithModemActivityInfo) {
12934                                 // Distribute measured mobile radio charge consumption based on
12935                                 // rx/tx packets and estimated rx/tx charge consumption.
12936                                 uidConsumptionMah = smearModemActivityInfoRxTxConsumptionMah(
12937                                         rxTxConsumption, entry.getRxPackets(), entry.getTxPackets(),
12938                                         totalRxPackets, totalTxPackets);
12939                             } else {
12940                                 // Distribute mobile radio charge consumption based on app radio
12941                                 // active time
12942                                 uidConsumptionMah =
12943                                     mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12944                                                 appRadioTimeUs / 1000);
12945                             }
12946                             uidEstimatedConsumptionMah.incrementValue(u.getUid(),
12947                                     uidConsumptionMah);
12948                         }
12949 
12950                         // Remove this app from the totals, so that we don't lose any time
12951                         // due to rounding.
12952                         totalAppRadioTimeUs -= appRadioTimeUs;
12953                         totalPackets -= appPackets;
12954 
12955                         if (deltaInfo != null) {
12956                             ControllerActivityCounterImpl activityCounter =
12957                                     u.getOrCreateModemControllerActivityLocked();
12958                             if (totalRxPackets > 0 && entry.getRxPackets() > 0) {
12959                                 final long rxMs = (entry.getRxPackets()
12960                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
12961                                 activityCounter.getOrCreateRxTimeCounter()
12962                                         .increment(rxMs, elapsedRealtimeMs);
12963                             }
12964 
12965                             if (totalTxPackets > 0 && entry.getTxPackets() > 0) {
12966                                 for (int lvl = 0; lvl < MODEM_TX_POWER_LEVEL_COUNT;
12967                                         lvl++) {
12968                                     long txMs = entry.getTxPackets()
12969                                             * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
12970                                     txMs /= totalTxPackets;
12971                                     activityCounter.getOrCreateTxTimeCounters()[lvl]
12972                                             .increment(txMs, elapsedRealtimeMs);
12973                                 }
12974                             }
12975                         }
12976                     }
12977                 }
12978 
12979                 if (totalAppRadioTimeUs > 0) {
12980                     // Whoops, there is some radio time we can't blame on an app!
12981                     mMobileRadioActiveUnknownTime.addCountLocked(totalAppRadioTimeUs);
12982                     mMobileRadioActiveUnknownCount.addCountLocked(1);
12983                 }
12984 
12985                 // Update the EnergyConsumerStats information.
12986                 if (uidEstimatedConsumptionMah != null) {
12987                     double totalEstimatedConsumptionMah = 0.0;
12988                     if (attributeWithModemActivityInfo) {
12989                         // Estimate inactive modem power consumption and combine with previously
12990                         // estimated active power consumption for an estimate of total modem
12991                         // power consumption.
12992                         final long sleepTimeMs = deltaInfo.getSleepTimeMillis();
12993                         final long idleTimeMs = deltaInfo.getIdleTimeMillis();
12994                         final double inactiveConsumptionMah =
12995                                 mMobileRadioPowerCalculator.calcInactiveStatePowerMah(sleepTimeMs,
12996                                         idleTimeMs);
12997                         totalEstimatedConsumptionMah += inactiveConsumptionMah;
12998                         totalEstimatedConsumptionMah += rxTxConsumption.rxConsumptionMah;
12999                         totalEstimatedConsumptionMah += rxTxConsumption.txConsumptionMah;
13000                     } else {
13001                         // Estimate total active radio power consumption since last mark.
13002                         totalEstimatedConsumptionMah +=
13003                                 mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
13004                                         totalRadioDurationMs);
13005 
13006                         // Estimate idle power consumption at each signal strength level
13007                         final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
13008                         for (int lvl = 0; lvl < numSignalStrengthLevels; lvl++) {
13009                             final long strengthLevelDurationMs =
13010                                     mPhoneSignalStrengthsTimer[lvl].getTimeSinceMarkLocked(
13011                                             elapsedRealtimeMs * 1000) / 1000;
13012                             mPhoneSignalStrengthsTimer[lvl].setMark(elapsedRealtimeMs);
13013 
13014                             totalEstimatedConsumptionMah +=
13015                                     mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
13016                                             strengthLevelDurationMs, lvl);
13017                         }
13018 
13019                         // Estimate total active radio power consumption since last mark.
13020                         final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
13021                                 elapsedRealtimeMs * 1000) / 1000;
13022                         mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs);
13023                         totalEstimatedConsumptionMah +=
13024                                 mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
13025                     }
13026                     distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
13027                             dataConsumedChargeUC, uidEstimatedConsumptionMah,
13028                             totalEstimatedConsumptionMah, elapsedRealtimeMs);
13029                 }
13030             }
13031         }
13032     }
13033 
13034     private static class RxTxConsumption {
13035         public final double rxConsumptionMah;
13036         public final long rxDurationMs;
13037         public final double txConsumptionMah;
13038         public final long txDurationMs;
13039 
13040         /**
13041          * Represents the ratio between time spent transmitting and the total active time.
13042          */
13043         public final double txToTotalRatio;
13044 
RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs)13045         RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs) {
13046             rxConsumptionMah = rxMah;
13047             rxDurationMs = rxMs;
13048             txConsumptionMah = txMah;
13049             txDurationMs = txMs;
13050 
13051             final long activeDurationMs = txDurationMs + rxDurationMs;
13052             if (activeDurationMs == 0) {
13053                 txToTotalRatio = 0.0;
13054             } else {
13055                 txToTotalRatio = ((double) txDurationMs) / activeDurationMs;
13056             }
13057         }
13058     }
13059 
13060     @GuardedBy("this")
13061     @Nullable
incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs)13062     private RxTxConsumption incrementPerRatDataLocked(ModemActivityInfo deltaInfo,
13063             long elapsedRealtimeMs) {
13064         double rxConsumptionMah = 0.0;
13065         long rxDurationMs = 0;
13066         double txConsumptionMah = 0.0;
13067         long txDurationMs = 0;
13068 
13069         final int infoSize = deltaInfo.getSpecificInfoLength();
13070         if (infoSize == 1 && deltaInfo.getSpecificInfoRat(0)
13071                 == AccessNetworkConstants.AccessNetworkType.UNKNOWN
13072                 && deltaInfo.getSpecificInfoFrequencyRange(0)
13073                 == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
13074             // Specific info data unavailable. Proportionally smear Rx and Tx times across each RAT.
13075             final int levelCount = CELL_SIGNAL_STRENGTH_LEVEL_COUNT;
13076             long[] perSignalStrengthActiveTimeMs = new long[levelCount];
13077             long totalActiveTimeMs = 0;
13078 
13079             for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13080                 final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13081                 if (ratStats == null) continue;
13082 
13083                 final int freqCount = ratStats.getFrequencyRangeCount();
13084                 for (int freq = 0; freq < freqCount; freq++) {
13085                     for (int level = 0; level < levelCount; level++) {
13086                         final long durationMs = ratStats.getTimeSinceMark(freq, level,
13087                                 elapsedRealtimeMs);
13088                         perSignalStrengthActiveTimeMs[level] += durationMs;
13089                         totalActiveTimeMs += durationMs;
13090                     }
13091                 }
13092             }
13093             if (totalActiveTimeMs != 0) {
13094                 // Smear the provided Tx/Rx durations across each RAT, frequency, and signal
13095                 // strength.
13096                 for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13097                     final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13098                     if (ratStats == null) continue;
13099 
13100                     final int freqCount = ratStats.getFrequencyRangeCount();
13101                     for (int freq = 0; freq < freqCount; freq++) {
13102                         long frequencyDurationMs = 0;
13103                         for (int level = 0; level < levelCount; level++) {
13104                             final long durationMs = ratStats.getTimeSinceMark(freq, level,
13105                                     elapsedRealtimeMs);
13106                             final long totalLvlDurationMs =
13107                                     perSignalStrengthActiveTimeMs[level];
13108                             if (totalLvlDurationMs == 0) continue;
13109                             final long totalTxLvlDurations =
13110                                     deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
13111                             // Smear HAL provided Tx power level duration based on active modem
13112                             // duration in a given state. (Add totalLvlDurationMs / 2 before
13113                             // the integer division with totalLvlDurationMs for rounding.)
13114                             final long proportionalTxDurationMs =
13115                                     (durationMs * totalTxLvlDurations
13116                                             + (totalLvlDurationMs / 2)) / totalLvlDurationMs;
13117                             ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
13118                             frequencyDurationMs += durationMs;
13119 
13120                             if (isMobileRadioEnergyConsumerSupportedLocked()) {
13121                                 // Accumulate the power cost of time spent transmitting in a
13122                                 // particular state.
13123                                 final double txStatePowerConsumptionMah =
13124                                         mMobileRadioPowerCalculator.calcTxStatePowerMah(rat, freq,
13125                                                 level, proportionalTxDurationMs);
13126                                 txConsumptionMah += txStatePowerConsumptionMah;
13127                                 txDurationMs += proportionalTxDurationMs;
13128                             }
13129                         }
13130                         final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
13131                         // Smear HAL provided Rx power duration based on active modem
13132                         // duration in a given state.  (Add totalActiveTimeMs / 2 before the
13133                         // integer division with totalActiveTimeMs for rounding.)
13134                         final long proportionalRxDurationMs =
13135                                 (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
13136                                         / 2)) / totalActiveTimeMs;
13137                         ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
13138 
13139                         if (isMobileRadioEnergyConsumerSupportedLocked()) {
13140                             // Accumulate the power cost of time spent receiving in a particular
13141                             // state.
13142                             final double rxStatePowerConsumptionMah =
13143                                     mMobileRadioPowerCalculator.calcRxStatePowerMah(rat, freq,
13144                                             proportionalRxDurationMs);
13145                             rxConsumptionMah += rxStatePowerConsumptionMah;
13146                             rxDurationMs += proportionalRxDurationMs;
13147                         }
13148                     }
13149 
13150                 }
13151             }
13152         } else {
13153             // Specific data available.
13154             for (int index = 0; index < infoSize; index++) {
13155                 final int rat = deltaInfo.getSpecificInfoRat(index);
13156                 final int freq = deltaInfo.getSpecificInfoFrequencyRange(index);
13157 
13158                 // Map RadioAccessNetworkType to course grain RadioAccessTechnology.
13159                 final int ratBucket = MobileRadioPowerStatsLayout
13160                         .mapRadioAccessNetworkTypeToRadioAccessTechnology(rat);
13161                 final RadioAccessTechnologyBatteryStats ratStats = getRatBatteryStatsLocked(
13162                         ratBucket);
13163 
13164                 final long rxTimeMs = deltaInfo.getReceiveTimeMillis(rat, freq);
13165                 final int[] txTimesMs = deltaInfo.getTransmitTimeMillis(rat, freq);
13166                 ratStats.incrementRxDuration(freq, rxTimeMs);
13167                 if (isMobileRadioEnergyConsumerSupportedLocked()) {
13168                     // Accumulate the power cost of time spent receiving in a particular state.
13169                     final double rxStatePowerConsumptionMah =
13170                             mMobileRadioPowerCalculator.calcRxStatePowerMah(ratBucket, freq,
13171                                     rxTimeMs);
13172                     rxConsumptionMah += rxStatePowerConsumptionMah;
13173                     rxDurationMs += rxTimeMs;
13174                 }
13175 
13176                 final int numTxLvl = txTimesMs.length;
13177                 for (int lvl = 0; lvl < numTxLvl; lvl++) {
13178                     final long txTimeMs = txTimesMs[lvl];
13179                     ratStats.incrementTxDuration(freq, lvl, txTimeMs);
13180                     if (isMobileRadioEnergyConsumerSupportedLocked()) {
13181                         // Accumulate the power cost of time spent transmitting in a particular
13182                         // state.
13183                         final double txStatePowerConsumptionMah =
13184                                 mMobileRadioPowerCalculator.calcTxStatePowerMah(ratBucket, freq,
13185                                         lvl, txTimeMs);
13186                         txConsumptionMah += txStatePowerConsumptionMah;
13187                         txDurationMs += txTimeMs;
13188                     }
13189                 }
13190             }
13191         }
13192 
13193         for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13194             final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13195             if (ratStats == null) continue;
13196             ratStats.setMark(elapsedRealtimeMs);
13197         }
13198 
13199         if (isMobileRadioEnergyConsumerSupportedLocked()) {
13200             return new RxTxConsumption(rxConsumptionMah, rxDurationMs, txConsumptionMah,
13201                     txDurationMs);
13202         } else {
13203             return null;
13204         }
13205     }
13206 
13207     /**
13208      * Smear modem Rx/Tx power consumption calculated from {@link ModemActivityInfo} using Rx/Tx
13209      * packets.
13210      *
13211      * @return the combine Rx/Tx smeared power consumption in milliamp-hours.
13212      */
smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption, long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets)13213     private double smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption,
13214             long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets) {
13215         // Distribute measured mobile radio charge consumption based on
13216         // rx/tx packets and estimated rx/tx charge consumption.
13217         double consumptionMah = 0.0;
13218         if (totalRxPackets != 0) {
13219             // Proportionally distribute receive battery consumption.
13220             consumptionMah += rxTxConsumption.rxConsumptionMah * rxPackets
13221                     / totalRxPackets;
13222         }
13223         if (totalTxPackets != 0 || (totalRxPackets != 0 && rxTxConsumption.txToTotalRatio != 0.0)) {
13224             // ModemActivityInfo Tx time represents time spent both transmitting and receiving.
13225             // There is currently no way to distinguish how many Rx packets were received during
13226             // Rx time vs Tx time.
13227             // Assumption: The number of packets received while transmitting is proportional
13228             // to the time spent transmitting over total active time.
13229             final double totalPacketsDuringTxTime =
13230                     totalTxPackets + rxTxConsumption.txToTotalRatio * totalRxPackets;
13231             final double packetsDuringTxTime =
13232                     txPackets + rxTxConsumption.txToTotalRatio * rxPackets;
13233             consumptionMah += rxTxConsumption.txConsumptionMah * packetsDuringTxTime
13234                     / totalPacketsDuringTxTime;
13235         }
13236         return consumptionMah;
13237     }
13238 
13239     /**
13240      * Add modem tx power to history
13241      * Device is said to be in high cellular transmit power when it has spent most of the transmit
13242      * time at the highest power level.
13243      * @param activityInfo
13244      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo, long elapsedRealtimeMs, long uptimeMs)13245     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo,
13246             long elapsedRealtimeMs, long uptimeMs) {
13247         if (activityInfo == null) {
13248             return;
13249         }
13250         int levelMaxTimeSpent = 0;
13251         for (int i = 1; i < MODEM_TX_POWER_LEVEL_COUNT; i++) {
13252             if (activityInfo.getTransmitDurationMillisAtPowerLevel(i)
13253                     > activityInfo.getTransmitDurationMillisAtPowerLevel(levelMaxTimeSpent)) {
13254                 levelMaxTimeSpent = i;
13255             }
13256         }
13257         if (levelMaxTimeSpent == MODEM_TX_POWER_LEVEL_COUNT - 1) {
13258             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
13259                     HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG);
13260         }
13261     }
13262 
13263     private final class BluetoothActivityInfoCache {
13264         long idleTimeMs;
13265         long rxTimeMs;
13266         long txTimeMs;
13267         long energy;
13268 
13269         SparseLongArray uidRxBytes = new SparseLongArray();
13270         SparseLongArray uidTxBytes = new SparseLongArray();
13271 
set(BluetoothActivityEnergyInfo info)13272         void set(BluetoothActivityEnergyInfo info) {
13273             idleTimeMs = info.getControllerIdleTimeMillis();
13274             rxTimeMs = info.getControllerRxTimeMillis();
13275             txTimeMs = info.getControllerTxTimeMillis();
13276             energy = info.getControllerEnergyUsed();
13277             if (!info.getUidTraffic().isEmpty()) {
13278                 for (UidTraffic traffic : info.getUidTraffic()) {
13279                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
13280                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
13281                 }
13282             }
13283         }
13284 
reset()13285         void reset() {
13286             idleTimeMs = 0;
13287             rxTimeMs = 0;
13288             txTimeMs = 0;
13289             energy = 0;
13290             uidRxBytes.clear();
13291             uidTxBytes.clear();
13292         }
13293     }
13294 
13295     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
13296             = new BluetoothActivityInfoCache();
13297 
onBluetoothPowerStatsRetrieved(BluetoothActivityEnergyInfo info, long elapsedRealtimeMs, long uptimeMs)13298     private void onBluetoothPowerStatsRetrieved(BluetoothActivityEnergyInfo info,
13299             long elapsedRealtimeMs, long uptimeMs) {
13300         // Do not populate consumed energy, because energy attribution is done by
13301         // BluetoothPowerStatsProcessor.
13302         updateBluetoothStateLocked(info, POWER_DATA_UNAVAILABLE, elapsedRealtimeMs, uptimeMs);
13303     }
13304 
13305     /**
13306      * Distribute Bluetooth energy info and network traffic to apps.
13307      *
13308      * @param info The accumulated energy information from the bluetooth controller.
13309      */
13310     @GuardedBy("this")
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)13311     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
13312             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
13313         if (DEBUG_ENERGY) {
13314             Slog.d(TAG, "Updating bluetooth stats: " + info);
13315         }
13316 
13317         if (info == null) {
13318             return;
13319         }
13320 
13321         if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
13322             mLastBluetoothActivityInfo.set(info);
13323             return;
13324         }
13325 
13326         mHasBluetoothReporting = true;
13327 
13328         if (info.getControllerRxTimeMillis() < mLastBluetoothActivityInfo.rxTimeMs
13329                 || info.getControllerTxTimeMillis() < mLastBluetoothActivityInfo.txTimeMs
13330                 || info.getControllerIdleTimeMillis() < mLastBluetoothActivityInfo.idleTimeMs
13331                 || info.getControllerEnergyUsed() < mLastBluetoothActivityInfo.energy) {
13332             // A drop in accumulated Bluetooth stats is a sign of a Bluetooth crash.
13333             // Reset the preserved previous snapshot in order to restart accumulating deltas.
13334             mLastBluetoothActivityInfo.reset();
13335         }
13336 
13337         final long rxTimeMs =
13338                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
13339         final long txTimeMs =
13340                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
13341         final long idleTimeMs =
13342                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
13343 
13344         if (DEBUG_ENERGY) {
13345             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
13346             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
13347             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
13348             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
13349         }
13350 
13351         final SparseDoubleArray uidEstimatedConsumptionMah =
13352                 (mGlobalEnergyConsumerStats != null
13353                         && mBluetoothPowerCalculator != null && consumedChargeUC > 0) ?
13354                         new SparseDoubleArray() : null;
13355         long totalScanTimeMs = 0;
13356 
13357         final int uidCount = mUidStats.size();
13358         for (int i = 0; i < uidCount; i++) {
13359             final Uid u = mUidStats.valueAt(i);
13360             if (u.mBluetoothScanTimer == null) {
13361                 continue;
13362             }
13363 
13364             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
13365                     elapsedRealtimeMs * 1000) / 1000;
13366         }
13367 
13368         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
13369         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
13370 
13371         if (DEBUG_ENERGY) {
13372             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
13373                     + " TX=" + normalizeScanTxTime);
13374         }
13375 
13376         long leftOverRxTimeMs = rxTimeMs;
13377         long leftOverTxTimeMs = txTimeMs;
13378 
13379         final SparseLongArray rxTimesMs = new SparseLongArray(uidCount);
13380         final SparseLongArray txTimesMs = new SparseLongArray(uidCount);
13381 
13382         for (int i = 0; i < uidCount; i++) {
13383             final Uid u = mUidStats.valueAt(i);
13384             if (u.mBluetoothScanTimer == null) {
13385                 continue;
13386             }
13387 
13388             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
13389                     elapsedRealtimeMs * 1000) / 1000;
13390             if (scanTimeSinceMarkMs > 0) {
13391                 // Set the new mark so that next time we get new data since this point.
13392                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
13393 
13394                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
13395                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
13396 
13397                 if (normalizeScanRxTime) {
13398                     // Scan time is longer than the total rx time in the controller,
13399                     // so distribute the scan time proportionately. This means regular traffic
13400                     // will not blamed, but scans are more expensive anyways.
13401                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
13402                 }
13403 
13404                 if (normalizeScanTxTime) {
13405                     // Scan time is longer than the total tx time in the controller,
13406                     // so distribute the scan time proportionately. This means regular traffic
13407                     // will not blamed, but scans are more expensive anyways.
13408                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
13409                 }
13410 
13411                 rxTimesMs.incrementValue(u.getUid(), scanTimeRxSinceMarkMs);
13412                 txTimesMs.incrementValue(u.getUid(), scanTimeTxSinceMarkMs);
13413 
13414                 if (uidEstimatedConsumptionMah != null) {
13415                     uidEstimatedConsumptionMah.incrementValue(u.getUid(),
13416                             mBluetoothPowerCalculator.calculatePowerMah(
13417                                     scanTimeRxSinceMarkMs, scanTimeTxSinceMarkMs, 0));
13418                 }
13419 
13420                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
13421                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
13422             }
13423         }
13424 
13425         if (DEBUG_ENERGY) {
13426             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
13427                     + leftOverTxTimeMs);
13428         }
13429 
13430         //
13431         // Now distribute blame to apps that did bluetooth traffic.
13432         //
13433 
13434         long totalTxBytes = 0;
13435         long totalRxBytes = 0;
13436 
13437         final List<UidTraffic> uidTraffic = info.getUidTraffic();
13438         final int numUids = uidTraffic.size();
13439         for (int i = 0; i < numUids; i++) {
13440             final UidTraffic traffic = uidTraffic.get(i);
13441             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
13442                     traffic.getUid());
13443             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
13444                     traffic.getUid());
13445 
13446             // Add to the global counters.
13447             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
13448             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
13449 
13450             // Add to the UID counters.
13451             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()), elapsedRealtimeMs, uptimeMs);
13452             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
13453             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
13454 
13455             // Calculate the total traffic.
13456             totalRxBytes += rxBytes;
13457             totalTxBytes += txBytes;
13458         }
13459 
13460         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
13461                 || leftOverTxTimeMs != 0)) {
13462             for (int i = 0; i < numUids; i++) {
13463                 final UidTraffic traffic = uidTraffic.get(i);
13464                 final int uid = traffic.getUid();
13465                 final long rxBytes =
13466                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
13467                 final long txBytes =
13468                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
13469 
13470                 final Uid u = getUidStatsLocked(mapUid(uid), elapsedRealtimeMs, uptimeMs);
13471                 final ControllerActivityCounterImpl counter =
13472                         u.getOrCreateBluetoothControllerActivityLocked();
13473 
13474                 if (totalRxBytes > 0 && rxBytes > 0) {
13475                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
13476                     rxTimesMs.incrementValue(uid, timeRxMs);
13477                 }
13478 
13479                 if (totalTxBytes > 0 && txBytes > 0) {
13480                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
13481                     txTimesMs.incrementValue(uid, timeTxMs);
13482                 }
13483             }
13484 
13485             for (int i = 0; i < txTimesMs.size(); i++) {
13486                 final int uid = txTimesMs.keyAt(i);
13487                 final long myTxTimeMs = txTimesMs.valueAt(i);
13488                 if (DEBUG_ENERGY) {
13489                     Slog.d(TAG, "  TxTime for UID " + uid + ": " + myTxTimeMs + " ms");
13490                 }
13491                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
13492                         .getOrCreateBluetoothControllerActivityLocked()
13493                         .getOrCreateTxTimeCounters()[0]
13494                         .increment(myTxTimeMs, elapsedRealtimeMs);
13495                 if (uidEstimatedConsumptionMah != null) {
13496                     uidEstimatedConsumptionMah.incrementValue(uid,
13497                             mBluetoothPowerCalculator.calculatePowerMah(0, myTxTimeMs, 0));
13498                 }
13499             }
13500 
13501             for (int i = 0; i < rxTimesMs.size(); i++) {
13502                 final int uid = rxTimesMs.keyAt(i);
13503                 final long myRxTimeMs = rxTimesMs.valueAt(i);
13504                 if (DEBUG_ENERGY) {
13505                     Slog.d(TAG, "  RxTime for UID " + uid + ": " + myRxTimeMs + " ms");
13506                 }
13507 
13508                 getUidStatsLocked(rxTimesMs.keyAt(i), elapsedRealtimeMs, uptimeMs)
13509                         .getOrCreateBluetoothControllerActivityLocked()
13510                         .getOrCreateRxTimeCounter()
13511                         .increment(myRxTimeMs, elapsedRealtimeMs);
13512                 if (uidEstimatedConsumptionMah != null) {
13513                     uidEstimatedConsumptionMah.incrementValue(uid,
13514                             mBluetoothPowerCalculator.calculatePowerMah(myRxTimeMs, 0, 0));
13515                 }
13516             }
13517         }
13518 
13519         mBluetoothActivity.getOrCreateRxTimeCounter().increment(rxTimeMs, elapsedRealtimeMs);
13520         mBluetoothActivity.getOrCreateTxTimeCounters()[0].increment(txTimeMs, elapsedRealtimeMs);
13521         mBluetoothActivity.getOrCreateIdleTimeCounter().increment(idleTimeMs, elapsedRealtimeMs);
13522 
13523         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
13524         final double opVolt = mPowerProfile.getAveragePower(
13525                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
13526         double controllerMaMs = 0;
13527         if (opVolt != 0) {
13528             controllerMaMs = (info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
13529                     / opVolt;
13530             // We store the power drain as mAms.
13531             mBluetoothActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
13532         }
13533 
13534         // Update the EnergyConsumerStats information.
13535         if (uidEstimatedConsumptionMah != null) {
13536             mGlobalEnergyConsumerStats.updateStandardBucket(
13537                     EnergyConsumerStats.POWER_BUCKET_BLUETOOTH, consumedChargeUC);
13538 
13539             double totalEstimatedMah
13540                     = mBluetoothPowerCalculator.calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
13541             totalEstimatedMah = Math.max(totalEstimatedMah, controllerMaMs / MILLISECONDS_IN_HOUR);
13542             distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
13543                     consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedMah,
13544                     elapsedRealtimeMs);
13545         }
13546 
13547         mLastBluetoothActivityInfo.set(info);
13548     }
13549     /**
13550      * Read Resource Power Manager (RPM) state and voter times.
13551      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
13552      * instead of fetching it anew.
13553      *
13554      * Note: This should be called without synchronizing this BatteryStatsImpl object
13555      */
fillLowPowerStats()13556     public void fillLowPowerStats() {
13557         if (mPlatformIdleStateCallback == null) return;
13558 
13559         RpmStats rpmStats = new RpmStats();
13560         long now = SystemClock.elapsedRealtime();
13561         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
13562             mPlatformIdleStateCallback.fillLowPowerStats(rpmStats);
13563             synchronized (this) {
13564                 mTmpRpmStats = rpmStats;
13565                 mLastRpmStatsUpdateTimeMs = now;
13566             }
13567         }
13568     }
13569 
13570     /**
13571      * Record Resource Power Manager (RPM) state and voter times.
13572      * TODO(b/185252376): Remove this logging. PowerStatsService logs the same data more
13573      * efficiently.
13574      */
updateRpmStatsLocked(long elapsedRealtimeUs)13575     public void updateRpmStatsLocked(long elapsedRealtimeUs) {
13576         if (mTmpRpmStats == null) return;
13577 
13578         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
13579                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
13580 
13581             // Update values for this platform state.
13582             final String pName = pstate.getKey();
13583             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
13584             final int pCount = pstate.getValue().mCount;
13585             getRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
13586             if (SCREEN_OFF_RPM_STATS_ENABLED) {
13587                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
13588             }
13589 
13590             // Update values for each voter of this platform state.
13591             for (Map.Entry<String, RpmStats.PowerStateElement> voter
13592                     : pstate.getValue().mVoters.entrySet()) {
13593                 final String vName = pName + "." + voter.getKey();
13594                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
13595                 final int vCount = voter.getValue().mCount;
13596                 getRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
13597                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
13598                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
13599                 }
13600             }
13601         }
13602 
13603         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
13604                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
13605 
13606             final String subsysName = subsys.getKey();
13607             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
13608                     : subsys.getValue().mStates.entrySet()) {
13609                 final String name = subsysName + "." + sstate.getKey();
13610                 final long timeUs = sstate.getValue().mTimeMs * 1000;
13611                 final int count = sstate.getValue().mCount;
13612                 getRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
13613                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
13614                     getScreenOffRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
13615                 }
13616             }
13617         }
13618     }
13619 
13620     /**
13621      * Accumulate Cpu charge consumption and distribute it to the correct state and the apps.
13622      * Only call if device is on battery.
13623      *
13624      * @param clusterChargeUC amount of charge (microcoulombs) consumed by each Cpu Cluster
13625      * @param accumulator collection of calculated uid cpu power consumption to smear
13626      *                    clusterChargeUC against.
13627      */
13628     @GuardedBy("this")
13629     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
updateCpuEnergyConsumerStatsLocked(@onNull long[] clusterChargeUC, @NonNull CpuDeltaPowerAccumulator accumulator)13630     private void updateCpuEnergyConsumerStatsLocked(@NonNull long[] clusterChargeUC,
13631             @NonNull CpuDeltaPowerAccumulator accumulator) {
13632         if (DEBUG_ENERGY) {
13633             Slog.d(TAG, "Updating cpu cluster stats: " + Arrays.toString(clusterChargeUC));
13634         }
13635         if (mGlobalEnergyConsumerStats == null) {
13636             return;
13637         }
13638 
13639         final int numClusters = clusterChargeUC.length;
13640         long totalCpuChargeUC = 0;
13641         for (int i = 0; i < numClusters; i++) {
13642             totalCpuChargeUC += clusterChargeUC[i];
13643         }
13644         if (totalCpuChargeUC <= 0) return;
13645 
13646         final long timestampMs = mClock.elapsedRealtime();
13647 
13648         mGlobalEnergyConsumerStats.updateStandardBucket(EnergyConsumerStats.POWER_BUCKET_CPU,
13649                 totalCpuChargeUC, timestampMs);
13650 
13651         // Calculate the microcoulombs/milliamp-hour charge ratio for each
13652         // cluster to normalize  each uid's estimated power usage against actual power usage for
13653         // a given cluster.
13654         final double[] clusterChargeRatio = new double[numClusters];
13655         for (int cluster = 0; cluster < numClusters; cluster++) {
13656 
13657             final double totalClusterChargeMah = accumulator.totalClusterChargesMah[cluster];
13658             if (totalClusterChargeMah <= 0.0) {
13659                 // This cluster did not have any work on it, since last update.
13660                 // Avoid dividing by zero.
13661                 clusterChargeRatio[cluster] = 0.0;
13662             } else {
13663                 clusterChargeRatio[cluster] =
13664                         clusterChargeUC[cluster] / accumulator.totalClusterChargesMah[cluster];
13665             }
13666         }
13667 
13668         // Assign and distribute power usage to apps based on their calculated cpu cluster charge.
13669         final long uidChargeArraySize = accumulator.perUidCpuClusterChargesMah.size();
13670         for (int i = 0; i < uidChargeArraySize; i++) {
13671             final Uid uid = accumulator.perUidCpuClusterChargesMah.keyAt(i);
13672             final double[] uidClusterChargesMah = accumulator.perUidCpuClusterChargesMah.valueAt(i);
13673 
13674             // Iterate each cpu cluster and sum the proportional cpu cluster charge to
13675             // get the total cpu charge consumed by a uid.
13676             long uidCpuChargeUC = 0;
13677             for (int cluster = 0; cluster < numClusters; cluster++) {
13678                 final double uidClusterChargeMah = uidClusterChargesMah[cluster];
13679 
13680                 // Proportionally allocate the cpu cluster charge to a uid using the
13681                 // cluster charge/charge ratio. Add 0.5 to round the proportional
13682                 // charge double to the nearest long value.
13683                 final long uidClusterChargeUC =
13684                         (long) (uidClusterChargeMah * clusterChargeRatio[cluster]
13685                                 + 0.5);
13686 
13687                 uidCpuChargeUC += uidClusterChargeUC;
13688             }
13689 
13690             if (uidCpuChargeUC < 0) {
13691                 Slog.wtf(TAG, "Unexpected proportional EnergyConsumer charge "
13692                         + "(" + uidCpuChargeUC + ") for uid " + uid.mUid);
13693                 continue;
13694             }
13695 
13696             uid.addChargeToStandardBucketLocked(uidCpuChargeUC,
13697                     EnergyConsumerStats.POWER_BUCKET_CPU, timestampMs);
13698         }
13699     }
13700 
13701     /**
13702      * Accumulate Display charge consumption and distribute it to the correct state and the apps.
13703      *
13704      * NOTE: The algorithm used makes the strong assumption that app foreground activity time
13705      * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported).
13706      * To the extent that those assumptions are violated, the algorithm will err.
13707      *
13708      * @param chargesUC amount of charge (microcoulombs) used by each Display since this was last
13709      *                 called.
13710      * @param screenStates each screen state at the time this data collection was scheduled
13711      */
13712     @GuardedBy("this")
updateDisplayEnergyConsumerStatsLocked(long[] chargesUC, int[] screenStates, long elapsedRealtimeMs)13713     public void updateDisplayEnergyConsumerStatsLocked(long[] chargesUC, int[] screenStates,
13714             long elapsedRealtimeMs) {
13715         if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + Arrays.toString(chargesUC));
13716         if (mGlobalEnergyConsumerStats == null) {
13717             return;
13718         }
13719 
13720         final int numDisplays;
13721         if (mPerDisplayBatteryStats.length == screenStates.length) {
13722             numDisplays = screenStates.length;
13723         } else {
13724             // if this point is reached, it will be reached every display state change.
13725             // Rate limit the wtf logging to once every 100 display updates.
13726             if (mDisplayMismatchWtfCount++ % 100 == 0) {
13727                 Slog.wtf(TAG, "Mismatch between PowerProfile reported display count ("
13728                         + mPerDisplayBatteryStats.length
13729                         + ") and PowerStatsHal reported display count (" + screenStates.length
13730                         + ")");
13731             }
13732             // Keep the show going, use the shorter of the two.
13733             numDisplays = mPerDisplayBatteryStats.length < screenStates.length
13734                     ? mPerDisplayBatteryStats.length : screenStates.length;
13735         }
13736 
13737         final int[] oldScreenStates = new int[numDisplays];
13738         for (int i = 0; i < numDisplays; i++) {
13739             final int screenState = screenStates[i];
13740             oldScreenStates[i] = mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement;
13741             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
13742         }
13743 
13744         if (!mOnBatteryInternal) {
13745             // There's nothing further to update.
13746             return;
13747         }
13748         if (mIgnoreNextExternalStats) {
13749             // Although under ordinary resets we won't get here, and typically a new sync will
13750             // happen right after the reset, strictly speaking we need to set all mark times to now.
13751             final int uidStatsSize = mUidStats.size();
13752             for (int i = 0; i < uidStatsSize; i++) {
13753                 final Uid uid = mUidStats.valueAt(i);
13754                 uid.markProcessForegroundTimeUs(elapsedRealtimeMs, false);
13755             }
13756             return;
13757         }
13758 
13759         long totalScreenOnChargeUC = 0;
13760         for (int i = 0; i < numDisplays; i++) {
13761             final long chargeUC = chargesUC[i];
13762             if (chargeUC <= 0) {
13763                 // There's nothing further to update.
13764                 continue;
13765             }
13766 
13767             final @StandardPowerBucket int powerBucket =
13768                     EnergyConsumerStats.getDisplayPowerBucket(oldScreenStates[i]);
13769             mGlobalEnergyConsumerStats.updateStandardBucket(powerBucket, chargeUC);
13770             if (powerBucket == EnergyConsumerStats.POWER_BUCKET_SCREEN_ON) {
13771                 totalScreenOnChargeUC += chargeUC;
13772             }
13773         }
13774 
13775         // Now we blame individual apps, but only if the display was ON.
13776         if (totalScreenOnChargeUC <= 0) {
13777             return;
13778         }
13779         // TODO(b/175726779): Consider unifying the code with the non-rail display power blaming.
13780 
13781         // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is
13782         // 'double counted' and will simply exceed the realtime that elapsed.
13783         // TODO(b/175726779): collect per display uid visibility for display power attribution.
13784 
13785         // Collect total time since mark so that we can normalize power.
13786         final SparseDoubleArray fgTimeUsArray = new SparseDoubleArray();
13787         final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
13788         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
13789         final int uidStatsSize = mUidStats.size();
13790         for (int i = 0; i < uidStatsSize; i++) {
13791             final Uid uid = mUidStats.valueAt(i);
13792             final long fgTimeUs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true);
13793             if (fgTimeUs == 0) continue;
13794             fgTimeUsArray.put(uid.getUid(), (double) fgTimeUs);
13795         }
13796         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON,
13797                 totalScreenOnChargeUC, fgTimeUsArray, 0, elapsedRealtimeMs);
13798     }
13799 
13800     /**
13801      * Accumulate GNSS charge consumption and distribute it to the correct state and the apps.
13802      *
13803      * @param chargeUC amount of charge (microcoulombs) used by GNSS since this was last called.
13804      */
13805     @GuardedBy("this")
13806     public void updateGnssEnergyConsumerStatsLocked(long chargeUC, long elapsedRealtimeMs) {
13807         if (DEBUG_ENERGY) Slog.d(TAG, "Updating gnss stats: " + chargeUC);
13808         if (mGlobalEnergyConsumerStats == null) {
13809             return;
13810         }
13811 
13812         if (!mOnBatteryInternal || chargeUC <= 0) {
13813             // There's nothing further to update.
13814             return;
13815         }
13816         if (mIgnoreNextExternalStats) {
13817             // Although under ordinary resets we won't get here, and typically a new sync will
13818             // happen right after the reset, strictly speaking we need to set all mark times to now.
13819             final int uidStatsSize = mUidStats.size();
13820             for (int i = 0; i < uidStatsSize; i++) {
13821                 final Uid uid = mUidStats.valueAt(i);
13822                 uid.markGnssTimeUs(elapsedRealtimeMs);
13823             }
13824             return;
13825         }
13826 
13827         mGlobalEnergyConsumerStats.updateStandardBucket(EnergyConsumerStats.POWER_BUCKET_GNSS,
13828                 chargeUC);
13829 
13830         // Collect the per uid time since mark so that we can normalize power.
13831         final SparseDoubleArray gnssTimeUsArray = new SparseDoubleArray();
13832         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
13833         final int uidStatsSize = mUidStats.size();
13834         for (int i = 0; i < uidStatsSize; i++) {
13835             final Uid uid = mUidStats.valueAt(i);
13836             final long gnssTimeUs = uid.markGnssTimeUs(elapsedRealtimeMs);
13837             if (gnssTimeUs == 0) continue;
13838             gnssTimeUsArray.put(uid.getUid(), (double) gnssTimeUs);
13839         }
13840         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_GNSS, chargeUC,
13841                 gnssTimeUsArray, 0, elapsedRealtimeMs);
13842     }
13843 
13844     /**
13845      * Accumulate camera charge consumption and distribute it to the correct state and the apps.
13846      *
13847      * @param chargeUC amount of charge (microcoulombs) used by the camera since this was last
13848      *         called.
13849      */
13850     @GuardedBy("this")
13851     public void updateCameraEnergyConsumerStatsLocked(long chargeUC, long elapsedRealtimeMs) {
13852         if (DEBUG_ENERGY) Slog.d(TAG, "Updating camera stats: " + chargeUC);
13853         if (mGlobalEnergyConsumerStats == null) {
13854             return;
13855         }
13856 
13857         if (!mOnBatteryInternal || chargeUC <= 0) {
13858             // There's nothing further to update.
13859             return;
13860         }
13861 
13862         if (mIgnoreNextExternalStats) {
13863             // Although under ordinary resets we won't get here, and typically a new sync will
13864             // happen right after the reset, strictly speaking we need to set all mark times to now.
13865             final int uidStatsSize = mUidStats.size();
13866             for (int i = 0; i < uidStatsSize; i++) {
13867                 final Uid uid = mUidStats.valueAt(i);
13868                 uid.markCameraTimeUs(elapsedRealtimeMs);
13869             }
13870             return;
13871         }
13872 
13873         mGlobalEnergyConsumerStats.updateStandardBucket(
13874                 EnergyConsumerStats.POWER_BUCKET_CAMERA, chargeUC);
13875 
13876         // Collect the per uid time since mark so that we can normalize power.
13877         final SparseDoubleArray cameraTimeUsArray = new SparseDoubleArray();
13878 
13879         // Note: Iterating over all UIDs may be suboptimal.
13880         final int uidStatsSize = mUidStats.size();
13881         for (int i = 0; i < uidStatsSize; i++) {
13882             final Uid uid = mUidStats.valueAt(i);
13883             final long cameraTimeUs = uid.markCameraTimeUs(elapsedRealtimeMs);
13884             if (cameraTimeUs == 0) continue;
13885             cameraTimeUsArray.put(uid.getUid(), (double) cameraTimeUs);
13886         }
13887         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_CAMERA, chargeUC,
13888                 cameraTimeUsArray, 0, elapsedRealtimeMs);
13889     }
13890 
13891     /**
13892      * Accumulate Custom power bucket charge, globally and for each app.
13893      *
13894      * @param totalChargeUC charge (microcoulombs) used for this bucket since this was last called.
13895      * @param uidCharges map of uid->charge (microcoulombs) for this bucket since last called.
13896      *                    Data inside uidCharges will not be modified (treated immutable).
13897      *                    Uids not already known to BatteryStats will be ignored.
13898      */
13899     @GuardedBy("this")
13900     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToCustomBucketLocked
13901     public void updateCustomEnergyConsumerStatsLocked(int customPowerBucket,
13902             long totalChargeUC, @Nullable SparseLongArray uidCharges) {
13903         if (DEBUG_ENERGY) {
13904             Slog.d(TAG, "Updating attributed EnergyConsumer stats for custom bucket "
13905                     + customPowerBucket
13906                     + " with total charge " + totalChargeUC
13907                     + " and uid charges " + uidCharges);
13908         }
13909         if (mGlobalEnergyConsumerStats == null) return;
13910         if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalChargeUC <= 0) return;
13911 
13912         mGlobalEnergyConsumerStats.updateCustomBucket(customPowerBucket, totalChargeUC,
13913                 mClock.elapsedRealtime());
13914 
13915         if (uidCharges == null) return;
13916         final int numUids = uidCharges.size();
13917         for (int i = 0; i < numUids; i++) {
13918             final int uidInt = mapUid(uidCharges.keyAt(i));
13919             final long uidChargeUC = uidCharges.valueAt(i);
13920             if (uidChargeUC == 0) continue;
13921 
13922             final Uid uidObj = getAvailableUidStatsLocked(uidInt);
13923             if (uidObj != null) {
13924                 uidObj.addChargeToCustomBucketLocked(uidChargeUC, customPowerBucket);
13925             } else {
13926                 // Ignore any uid not already known to BatteryStats, rather than creating a new Uid.
13927                 // Otherwise we could end up reviving dead Uids. Note that the CPU data is updated
13928                 // first, so any uid that has used any CPU should already be known to BatteryStats.
13929                 // Recently removed uids (especially common for isolated uids) can reach this path
13930                 // and are ignored.
13931                 if (!Process.isIsolated(uidInt)) {
13932                     Slog.w(TAG, "Received EnergyConsumer charge " + totalChargeUC
13933                             + " for custom bucket " + customPowerBucket + " for non-existent uid "
13934                             + uidInt);
13935                 }
13936             }
13937         }
13938     }
13939 
13940     /**
13941      * Attributes energy (for the given bucket) to each uid according to the following formula:
13942      *     blamedEnergy[uid] = totalEnergy * ratioNumerators[uid] / ratioDenominator;
13943      * <p>Does nothing if ratioDenominator is 0.
13944      *
13945      * <p>Here, ratioDenominator = max(sumOfAllRatioNumerators, minRatioDenominator),
13946      * so if given minRatioDenominator <= 0, then sumOfAllRatioNumerators will be used implicitly.
13947      *
13948      * <p>Note that ratioNumerators and minRatioDenominator must use the same units, but need not
13949      * use the same units as totalConsumedChargeUC (which must be in microcoulombs).
13950      *
13951      * <p>A consequence of minRatioDenominator is that the sum over all uids might be less than
13952      * totalConsumedChargeUC. This is intentional; the remainder is purposefully unnaccounted rather
13953      * than incorrectly blamed on uids, and implies unknown (non-uid) sources of drain.
13954      *
13955      * <p>All uids in ratioNumerators must exist in mUidStats already.
13956      */
13957     @GuardedBy("this")
13958     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
13959     private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket,
13960             long totalConsumedChargeUC, SparseDoubleArray ratioNumerators,
13961             double minRatioDenominator, long timestampMs) {
13962 
13963         // If the sum of all app usage was greater than the total, use that instead:
13964         double sumRatioNumerators = 0;
13965         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
13966             sumRatioNumerators += ratioNumerators.valueAt(i);
13967         }
13968         final double ratioDenominator = Math.max(sumRatioNumerators, minRatioDenominator);
13969         if (ratioDenominator <= 0) return;
13970 
13971         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
13972             final Uid uid = getAvailableUidStatsLocked(ratioNumerators.keyAt(i));
13973             final double ratioNumerator = ratioNumerators.valueAt(i);
13974             final long uidActualUC
13975                     = (long) (totalConsumedChargeUC * ratioNumerator / ratioDenominator + 0.5);
13976             uid.addChargeToStandardBucketLocked(uidActualUC, bucket, timestampMs);
13977         }
13978     }
13979 
13980     /**
13981      * Read and record Rail Energy data.
13982      */
13983     public void updateRailStatsLocked() {
13984         if (mCustomEnergyConsumerPowerStatsCollector.isEnabled()) {
13985             mCustomEnergyConsumerPowerStatsCollector.schedule();
13986             return;
13987         }
13988 
13989         if (mEnergyConsumerRetriever == null || !mTmpRailStats.isRailStatsAvailable()) {
13990             return;
13991         }
13992         mEnergyConsumerRetriever.fillRailDataStats(mTmpRailStats);
13993     }
13994 
13995     /** Informs that external stats data has been completely flushed. */
13996     public void informThatAllExternalStatsAreFlushed() {
13997         synchronized (this) {
13998             // Any data from the pre-reset era is flushed, so we can henceforth process future data.
13999             mIgnoreNextExternalStats = false;
14000         }
14001     }
14002 
14003     /**
14004      * Read and distribute kernel wake lock use across apps.
14005      */
14006     public void updateKernelWakelocksLocked(long elapsedRealtimeUs) {
14007         if (mKernelWakelockReader == null) {
14008             return;
14009         }
14010 
14011         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
14012                 mTmpWakelockStats);
14013         if (wakelockStats == null) {
14014             // Not crashing might make board bringup easier.
14015             Slog.w(TAG, "Couldn't get kernel wake lock stats");
14016             return;
14017         }
14018 
14019         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
14020             String name = ent.getKey();
14021             KernelWakelockStats.Entry kws = ent.getValue();
14022 
14023             SamplingTimer kwlt = mKernelWakelockStats.get(name);
14024             if (kwlt == null) {
14025                 kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
14026                 mKernelWakelockStats.put(name, kwlt);
14027             }
14028 
14029             kwlt.update(kws.totalTimeUs, kws.activeTimeUs, kws.count, elapsedRealtimeUs);
14030             kwlt.setUpdateVersion(kws.version);
14031         }
14032 
14033         int numWakelocksSetStale = 0;
14034         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
14035         // this time.
14036         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14037             SamplingTimer st = ent.getValue();
14038             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
14039                 st.endSample(elapsedRealtimeUs);
14040                 numWakelocksSetStale++;
14041             }
14042         }
14043 
14044         if (DEBUG) {
14045             // Record whether we've seen a non-zero time (for debugging b/22716723).
14046             if (wakelockStats.isEmpty()) {
14047                 Slog.wtf(TAG, "All kernel wakelocks had time of zero");
14048             }
14049 
14050             if (numWakelocksSetStale == mKernelWakelockStats.size()) {
14051                 Slog.wtf(TAG, "All kernel wakelocks were set stale. new version="
14052                         + wakelockStats.kernelWakelockVersion);
14053             }
14054         }
14055     }
14056 
14057     // We use an anonymous class to access these variables,
14058     // so they can't live on the stack or they'd have to be
14059     // final MutableLong objects (more allocations).
14060     // Used in updateCpuTimeLocked().
14061     long mTempTotalCpuUserTimeUs;
14062     long mTempTotalCpuSystemTimeUs;
14063     long[][] mWakeLockAllocationsUs;
14064 
14065     /**
14066      * Reads the newest memory stats from the kernel.
14067      */
14068     public void updateKernelMemoryBandwidthLocked(long elapsedRealtimeUs) {
14069         mKernelMemoryBandwidthStats.updateStats();
14070         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
14071         final int bandwidthEntryCount = bandwidthEntries.size();
14072         int index;
14073         for (int i = 0; i < bandwidthEntryCount; i++) {
14074             SamplingTimer timer;
14075             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
14076                 timer = mKernelMemoryStats.valueAt(index);
14077             } else {
14078                 timer = new SamplingTimer(mClock, mOnBatteryTimeBase);
14079                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
14080             }
14081             timer.update(bandwidthEntries.valueAt(i), 1, elapsedRealtimeUs);
14082             if (DEBUG_MEMORY) {
14083                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
14084                         + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i),
14085                         mKernelMemoryStats.get(
14086                                 bandwidthEntries.keyAt(i)).mBaseReportedTotalTimeUs,
14087                         mKernelMemoryStats.size()));
14088             }
14089         }
14090     }
14091 
14092     public boolean isOnBatteryLocked() {
14093         return mOnBatteryTimeBase.isRunning();
14094     }
14095 
14096     public boolean isOnBatteryScreenOffLocked() {
14097         return mOnBatteryScreenOffTimeBase.isRunning();
14098     }
14099 
14100     /**
14101      * Object for calculating and accumulating the estimated cpu power used while reading the
14102      * various cpu kernel files.
14103      */
14104     @VisibleForTesting
14105     public static class CpuDeltaPowerAccumulator {
14106         // Keeps track of total charge used per cluster.
14107         public final double[] totalClusterChargesMah;
14108         // Keeps track of charge used per cluster per uid.
14109         public final ArrayMap<Uid, double[]> perUidCpuClusterChargesMah;
14110 
14111         private final CpuPowerCalculator mCalculator;
14112         private Uid mCachedUid = null;
14113         private double[] mUidClusterCache = null;
14114 
14115         CpuDeltaPowerAccumulator(CpuPowerCalculator calculator, int nClusters) {
14116             mCalculator = calculator;
14117             totalClusterChargesMah = new double[nClusters];
14118             perUidCpuClusterChargesMah = new ArrayMap<>();
14119         }
14120 
14121         /** Add per cpu cluster durations to the currently cached uid. */
14122         public void addCpuClusterDurationsMs(Uid uid, long[] durationsMs) {
14123             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
14124             for (int cluster = 0; cluster < durationsMs.length; cluster++) {
14125                 final double estimatedDeltaMah = mCalculator.calculatePerCpuClusterPowerMah(cluster,
14126                         durationsMs[cluster]);
14127                 uidChargesMah[cluster] += estimatedDeltaMah;
14128                 totalClusterChargesMah[cluster] += estimatedDeltaMah;
14129             }
14130         }
14131 
14132         /** Add per speed per cpu cluster durations to the currently cached uid. */
14133         public void addCpuClusterSpeedDurationsMs(Uid uid, int cluster, int speed,
14134                 long durationsMs) {
14135             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
14136             final double estimatedDeltaMah = mCalculator.calculatePerCpuFreqPowerMah(cluster, speed,
14137                     durationsMs);
14138             uidChargesMah[cluster] += estimatedDeltaMah;
14139             totalClusterChargesMah[cluster] += estimatedDeltaMah;
14140         }
14141 
14142         private double[] getOrCreateUidCpuClusterCharges(Uid uid) {
14143             // Repeated additions on the same uid is very likely.
14144             // Skip a lookup if getting the same uid as the last get.
14145             if (uid == mCachedUid) return mUidClusterCache;
14146 
14147             double[] uidChargesMah = perUidCpuClusterChargesMah.get(uid);
14148             if (uidChargesMah == null) {
14149                 uidChargesMah = new double[totalClusterChargesMah.length];
14150                 perUidCpuClusterChargesMah.put(uid, uidChargesMah);
14151             }
14152             mCachedUid = uid;
14153             mUidClusterCache = uidChargesMah;
14154             return uidChargesMah;
14155         }
14156     }
14157 
14158     /**
14159      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
14160      * and we are on battery with screen off, we give more of the cpu time to those apps holding
14161      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
14162      * It's possible this will be invoked after the internal battery/screen states are updated, so
14163      * passing the appropriate battery/screen states to try attribute the cpu times to correct
14164      * buckets.
14165      */
14166     @GuardedBy("this")
14167     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff,
14168             long[] cpuClusterChargeUC) {
14169         if (DEBUG_ENERGY_CPU) {
14170             Slog.d(TAG, "!Cpu updating!");
14171         }
14172 
14173         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
14174         // usually holding the wakelock on behalf of an app.
14175         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
14176         ArrayList<StopwatchTimer> partialTimersToConsider = null;
14177         if (onBatteryScreenOff) {
14178             partialTimersToConsider = new ArrayList<>();
14179             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
14180                 final StopwatchTimer timer = mPartialTimers.get(i);
14181                 // Since the collection and blaming of wakelocks can be scheduled to run after
14182                 // some delay, the mPartialTimers list may have new entries. We can't blame
14183                 // the newly added timer for past cpu time, so we only consider timers that
14184                 // were present for one round of collection. Once a timer has gone through
14185                 // a round of collection, its mInList field is set to true.
14186                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
14187                     partialTimersToConsider.add(timer);
14188                 }
14189             }
14190         }
14191         markPartialTimersAsEligible();
14192 
14193         // When the battery is not on, we don't attribute the cpu times to any timers but we still
14194         // need to take the snapshots.
14195         if (!onBattery) {
14196             mCpuUidUserSysTimeReader.readDelta(false, null);
14197             mCpuUidFreqTimeReader.readDelta(false, null);
14198             mNumAllUidCpuTimeReads += 2;
14199             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
14200                 mCpuUidActiveTimeReader.readDelta(false, null);
14201                 mCpuUidClusterTimeReader.readDelta(false, null);
14202                 mNumAllUidCpuTimeReads += 2;
14203             }
14204             for (int i = mKernelCpuSpeedReaders.length - 1; i >= 0; --i) {
14205                 if (mKernelCpuSpeedReaders[i] != null) {
14206                     mKernelCpuSpeedReaders[i].readDelta();
14207                 }
14208             }
14209             if (!Flags.disableSystemServicePowerAttr()) {
14210                 mSystemServerCpuThreadReader.readDelta();
14211             }
14212             return;
14213         }
14214 
14215         mUserInfoProvider.refreshUserIds();
14216         final SparseLongArray updatedUids = mCpuUidFreqTimeReader.allUidTimesAvailable()
14217                 ? null : new SparseLongArray();
14218 
14219         final CpuDeltaPowerAccumulator powerAccumulator;
14220         if (mGlobalEnergyConsumerStats != null
14221                 && mGlobalEnergyConsumerStats.isStandardBucketSupported(
14222                 EnergyConsumerStats.POWER_BUCKET_CPU)) {
14223             if (cpuClusterChargeUC == null) {
14224                 Slog.wtf(TAG,
14225                         "POWER_BUCKET_CPU supported but no EnergyConsumer Cpu Cluster charge "
14226                                 + "reported on updateCpuTimeLocked!");
14227                 powerAccumulator = null;
14228             } else {
14229                 if (mCpuPowerCalculator == null) {
14230                     mCpuPowerCalculator = new CpuPowerCalculator(mCpuScalingPolicies,
14231                             mPowerProfile);
14232                 }
14233                 // Cpu EnergyConsumer is supported, create an object to accumulate the estimated
14234                 // charge consumption since the last cpu update
14235                 powerAccumulator = new CpuDeltaPowerAccumulator(mCpuPowerCalculator,
14236                         mCpuScalingPolicies.getPolicies().length);
14237             }
14238         } else {
14239             powerAccumulator = null;
14240         }
14241 
14242         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
14243         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
14244         // freqs, so no need to approximate these values.
14245         if (updatedUids != null) {
14246             updateClusterSpeedTimes(updatedUids, onBattery, powerAccumulator);
14247         }
14248         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff,
14249                 powerAccumulator);
14250         mNumAllUidCpuTimeReads += 2;
14251         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
14252             // Cpu Active times do not get any info ony how to attribute Cpu Cluster
14253             // charge, so not need to provide the powerAccumulator
14254             readKernelUidCpuActiveTimesLocked(onBattery);
14255             readKernelUidCpuClusterTimesLocked(onBattery, powerAccumulator);
14256             mNumAllUidCpuTimeReads += 2;
14257         }
14258 
14259         if (!Flags.disableSystemServicePowerAttr()) {
14260             updateSystemServerThreadStats();
14261         }
14262 
14263         if (powerAccumulator != null) {
14264             updateCpuEnergyConsumerStatsLocked(cpuClusterChargeUC, powerAccumulator);
14265         }
14266     }
14267 
14268     /**
14269      * Estimates the proportion of the System Server CPU activity (per cluster per speed)
14270      * spent on handling incoming binder calls.
14271      */
14272     @VisibleForTesting
14273     public void updateSystemServerThreadStats() {
14274         // There are some simplifying assumptions made in this algorithm
14275         // 1) We assume that if a thread handles incoming binder calls, all of its activity
14276         //    is spent doing that.  Most incoming calls are handled by threads allocated
14277         //    by the native layer in the binder thread pool, so this assumption is reasonable.
14278         // 2) We use the aggregate CPU time spent in different threads as a proxy for the CPU
14279         //    cost. In reality, in multi-core CPUs, the CPU cost may not be linearly
14280         //    affected by additional threads.
14281 
14282         SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes =
14283                     mSystemServerCpuThreadReader.readDelta();
14284         if (systemServiceCpuThreadTimes == null) {
14285             return;
14286         }
14287 
14288         if (mBinderThreadCpuTimesUs == null) {
14289             mBinderThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
14290         }
14291         mBinderThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
14292 
14293         if (DEBUG_BINDER_STATS) {
14294             Slog.d(TAG, "System server threads per CPU cluster (incoming binder threads)");
14295             long binderThreadTimeMs = 0;
14296             final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked(
14297                     BatteryStats.STATS_SINCE_CHARGED);
14298             int index = 0;
14299             int[] policies = mCpuScalingPolicies.getPolicies();
14300             for (int policy : policies) {
14301                 StringBuilder sb = new StringBuilder();
14302                 sb.append("policy").append(policy).append(": [");
14303                 int numSpeeds = mCpuScalingPolicies.getFrequencies(policy).length;
14304                 for (int speed = 0; speed < numSpeeds; speed++) {
14305                     if (speed != 0) {
14306                         sb.append(", ");
14307                     }
14308                     long binderCountMs = binderThreadCpuTimesUs[index] / 1000;
14309                     sb.append(TextUtils.formatSimple("%10d", binderCountMs));
14310 
14311                     binderThreadTimeMs += binderCountMs;
14312                     index++;
14313                 }
14314                 Slog.d(TAG, sb.toString());
14315             }
14316         }
14317     }
14318 
14319     /**
14320      * Mark the current partial timers as gone through a collection so that they will be
14321      * considered in the next cpu times distribution to wakelock holders.
14322      */
14323     @VisibleForTesting
14324     public void markPartialTimersAsEligible() {
14325         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
14326             // No difference, so each timer is now considered for the next collection.
14327             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
14328                 mPartialTimers.get(i).mInList = true;
14329             }
14330         } else {
14331             // The lists are different, meaning we added (or removed a timer) since the last
14332             // collection.
14333             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
14334                 mLastPartialTimers.get(i).mInList = false;
14335             }
14336             mLastPartialTimers.clear();
14337 
14338             // Mark the current timers as gone through a collection.
14339             final int numPartialTimers = mPartialTimers.size();
14340             for (int i = 0; i < numPartialTimers; ++i) {
14341                 final StopwatchTimer timer = mPartialTimers.get(i);
14342                 timer.mInList = true;
14343                 mLastPartialTimers.add(timer);
14344             }
14345         }
14346     }
14347 
14348     /**
14349      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
14350      * calculate cpu times spent by each uid at different frequencies. Will also add estimated
14351      * power consumptions, if powerAccumulator data structure is provided.
14352      *
14353      * @param updatedUids  The uids for which times spent at different frequencies are calculated.
14354      * @param onBattery whether or not this is onBattery
14355      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
14356      */
14357     @VisibleForTesting
14358     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery,
14359             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
14360         long totalCpuClustersTimeMs = 0;
14361         // Read the time spent for each cluster at various cpu frequencies.
14362         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
14363         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
14364             if (mKernelCpuSpeedReaders[cluster] != null) {
14365                 clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
14366                 if (clusterSpeedTimesMs[cluster] != null) {
14367                     for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
14368                         totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
14369                     }
14370                 }
14371             }
14372         }
14373         if (totalCpuClustersTimeMs != 0) {
14374             // We have cpu times per freq aggregated over all uids but we need the times per uid.
14375             // So, we distribute total time spent by an uid to different cpu freqs based on the
14376             // amount of time cpu was running at that freq.
14377             final int updatedUidsCount = updatedUids.size();
14378             final long elapsedRealtimeMs = mClock.elapsedRealtime();
14379             final long uptimeMs = mClock.uptimeMillis();
14380             for (int i = 0; i < updatedUidsCount; ++i) {
14381                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i), elapsedRealtimeMs, uptimeMs);
14382                 final long appCpuTimeUs = updatedUids.valueAt(i);
14383                 // Add the cpu speeds to this UID.
14384                 int[] policies = mCpuScalingPolicies.getPolicies();
14385                 if (u.mCpuClusterSpeedTimesUs == null ||
14386                         u.mCpuClusterSpeedTimesUs.length != policies.length) {
14387                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[policies.length][];
14388                 }
14389 
14390                 for (int cluster = 0; cluster < policies.length; cluster++) {
14391                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
14392                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
14393                             u.mCpuClusterSpeedTimesUs[cluster].length) {
14394                         u.mCpuClusterSpeedTimesUs[cluster]
14395                                 = new LongSamplingCounter[speedsInCluster];
14396                     }
14397 
14398                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
14399                     for (int speed = 0; speed < speedsInCluster; speed++) {
14400                         if (cpuSpeeds[speed] == null) {
14401                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
14402                         }
14403                         final long deltaSpeedCount = appCpuTimeUs
14404                                 * clusterSpeedTimesMs[cluster][speed]
14405                                 / totalCpuClustersTimeMs;
14406                         cpuSpeeds[speed].addCountLocked(deltaSpeedCount, onBattery);
14407 
14408                         if (powerAccumulator != null) {
14409                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14410                                     speed, deltaSpeedCount);
14411                         }
14412                     }
14413                 }
14414             }
14415         }
14416     }
14417 
14418     /**
14419      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
14420      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
14421      * wakelock holders.
14422      *
14423      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
14424      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
14425      */
14426     @VisibleForTesting
14427     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
14428             @Nullable SparseLongArray updatedUids, boolean onBattery) {
14429         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
14430         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
14431         final long startTimeMs = mClock.uptimeMillis();
14432         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14433 
14434         mCpuUidUserSysTimeReader.readDelta(false, (uid, timesUs) -> {
14435             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
14436 
14437             uid = mapUid(uid);
14438             if (Process.isIsolated(uid)) {
14439                 // This could happen if the isolated uid mapping was removed before that process
14440                 // was actually killed.
14441                 if (DEBUG) Slog.d(TAG, "Got readings for an isolated uid: " + uid);
14442                 return;
14443             }
14444             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14445                 if (DEBUG) Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
14446                 return;
14447             }
14448             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
14449 
14450             // Accumulate the total system and user time.
14451             mTempTotalCpuUserTimeUs += userTimeUs;
14452             mTempTotalCpuSystemTimeUs += systemTimeUs;
14453 
14454             StringBuilder sb = null;
14455             if (DEBUG_ENERGY_CPU) {
14456                 sb = new StringBuilder();
14457                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
14458                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
14459                 sb.append(" s=");
14460                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
14461                 sb.append("\n");
14462             }
14463 
14464             if (numWakelocks > 0) {
14465                 // We have wakelocks being held, so only give a portion of the
14466                 // time to the process. The rest will be distributed among wakelock
14467                 // holders.
14468                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
14469                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
14470             }
14471 
14472             if (sb != null) {
14473                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
14474                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
14475                 sb.append(" s=");
14476                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
14477                 Slog.d(TAG, sb.toString());
14478             }
14479 
14480             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
14481             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
14482             if (updatedUids != null) {
14483                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
14484             }
14485         });
14486 
14487         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14488         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14489             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
14490         }
14491 
14492         if (numWakelocks > 0) {
14493             // Distribute a portion of the total cpu time to wakelock holders.
14494             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
14495             mTempTotalCpuSystemTimeUs =
14496                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
14497 
14498             for (int i = 0; i < numWakelocks; ++i) {
14499                 final StopwatchTimer timer = partialTimers.get(i);
14500                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
14501                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
14502 
14503                 if (DEBUG_ENERGY_CPU) {
14504                     final StringBuilder sb = new StringBuilder();
14505                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
14506                             .append(": u=");
14507                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
14508                     sb.append(" s=");
14509                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
14510                     Slog.d(TAG, sb.toString());
14511                 }
14512 
14513                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
14514                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
14515                 if (updatedUids != null) {
14516                     final int uid = timer.mUid.getUid();
14517                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
14518                 }
14519 
14520                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
14521                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
14522 
14523                 mTempTotalCpuUserTimeUs -= userTimeUs;
14524                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
14525             }
14526         }
14527     }
14528 
14529     /**
14530      * Take a snapshot of the cpu times spent by each uid in each freq and update the
14531      * corresponding counters.  Will also add estimated power consumptions, if powerAccumulator
14532      * data structure is provided.
14533      *
14534      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
14535      * @param onBattery whether or not this is onBattery
14536      * @param onBatteryScreenOff whether or not this is onBattery with the screen off.
14537      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
14538      */
14539     @VisibleForTesting
14540     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
14541             boolean onBattery, boolean onBatteryScreenOff,
14542             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
14543         final boolean perClusterTimesAvailable =
14544                 mCpuUidFreqTimeReader.perClusterTimesAvailable();
14545         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
14546         final int[] policies = mCpuScalingPolicies.getPolicies();
14547         final int numClusters = policies.length;
14548         mWakeLockAllocationsUs = null;
14549         final long startTimeMs = mClock.uptimeMillis();
14550         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14551         // If power is being accumulated for attribution, data needs to be read immediately.
14552         final boolean forceRead = powerAccumulator != null;
14553         mCpuUidFreqTimeReader.readDelta(forceRead, (uid, cpuFreqTimeMs) -> {
14554             uid = mapUid(uid);
14555             if (Process.isIsolated(uid)) {
14556                 if (DEBUG) Slog.d(TAG, "Got freq readings for an isolated uid: " + uid);
14557                 return;
14558             }
14559             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14560                 if (DEBUG) Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
14561                 return;
14562             }
14563             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
14564             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
14565                 detachIfNotNull(u.mCpuFreqTimeMs);
14566                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
14567             }
14568             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
14569             if (u.mScreenOffCpuFreqTimeMs == null ||
14570                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
14571                 detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
14572                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
14573                         mOnBatteryScreenOffTimeBase);
14574             }
14575             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
14576 
14577             if (perClusterTimesAvailable) {
14578                 if (u.mCpuClusterSpeedTimesUs == null ||
14579                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
14580                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
14581                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
14582                 }
14583                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
14584                     mWakeLockAllocationsUs = new long[numClusters][];
14585                 }
14586 
14587                 int freqIndex = 0;
14588                 for (int cluster = 0; cluster < numClusters; cluster++) {
14589                     final int[] freqs = mCpuScalingPolicies.getFrequencies(policies[cluster]);
14590                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
14591                             u.mCpuClusterSpeedTimesUs[cluster].length != freqs.length) {
14592                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
14593                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[freqs.length];
14594                     }
14595                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
14596                         mWakeLockAllocationsUs[cluster] = new long[freqs.length];
14597                     }
14598                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
14599                     for (int speed = 0; speed < freqs.length; ++speed) {
14600                         if (cpuTimesUs[speed] == null) {
14601                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
14602                         }
14603                         final long appAllocationUs;
14604                         if (mWakeLockAllocationsUs != null) {
14605                             appAllocationUs =
14606                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
14607                             mWakeLockAllocationsUs[cluster][speed] +=
14608                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
14609                         } else {
14610                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
14611                         }
14612                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
14613 
14614                         if (powerAccumulator != null) {
14615                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14616                                     speed, appAllocationUs / 1000);
14617                         }
14618                         freqIndex++;
14619                     }
14620                 }
14621             }
14622         });
14623 
14624         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14625         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14626             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
14627         }
14628 
14629         if (mWakeLockAllocationsUs != null) {
14630             for (int i = 0; i < numWakelocks; ++i) {
14631                 final Uid u = partialTimers.get(i).mUid;
14632                 if (u.mCpuClusterSpeedTimesUs == null ||
14633                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
14634                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
14635                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
14636                 }
14637 
14638                 for (int cluster = 0; cluster < numClusters; ++cluster) {
14639                     final int speedsInCluster =
14640                             mCpuScalingPolicies.getFrequencies(policies[cluster]).length;
14641                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
14642                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
14643                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
14644                         u.mCpuClusterSpeedTimesUs[cluster]
14645                                 = new LongSamplingCounter[speedsInCluster];
14646                     }
14647                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
14648                     for (int speed = 0; speed < speedsInCluster; ++speed) {
14649                         if (cpuTimeUs[speed] == null) {
14650                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
14651                         }
14652                         final long allocationUs =
14653                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
14654                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
14655                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
14656 
14657                         if (powerAccumulator != null) {
14658                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14659                                     speed, allocationUs / 1000);
14660                         }
14661                     }
14662                 }
14663             }
14664         }
14665     }
14666 
14667     /**
14668      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
14669      * counters.
14670      */
14671     @VisibleForTesting
14672     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
14673         final long startTimeMs = mClock.uptimeMillis();
14674         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14675         mCpuUidActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
14676             final int parentUid = mapUid(uid);
14677             if (Process.isIsolated(parentUid)) {
14678                 if (DEBUG) Slog.w(TAG, "Got active times for an isolated uid: " + uid);
14679                 return;
14680             }
14681             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14682                 if (DEBUG) Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
14683                 return;
14684             }
14685             final Uid u = getUidStatsLocked(parentUid, elapsedRealtimeMs, startTimeMs);
14686             if (parentUid == uid) {
14687                 u.getCpuActiveTimeCounter().update(cpuActiveTimesMs, elapsedRealtimeMs);
14688             } else {
14689                 final SparseArray<Uid.ChildUid> childUids = u.mChildUids;
14690                 if (childUids == null) {
14691                     return;
14692                 }
14693 
14694                 Uid.ChildUid childUid = childUids.get(uid);
14695                 if (childUid != null) {
14696                     final long delta =
14697                             childUid.cpuActiveCounter.update(cpuActiveTimesMs, elapsedRealtimeMs);
14698                     u.getCpuActiveTimeCounter().increment(delta, elapsedRealtimeMs);
14699                 }
14700             }
14701         });
14702 
14703         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14704         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14705             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
14706         }
14707     }
14708 
14709     /**
14710      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
14711      * counters. Will also add estimated power consumptions, if powerAccumulator data structure
14712      * is provided.
14713      *
14714      * @param onBattery whether or not this is onBattery
14715      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
14716      */
14717     @VisibleForTesting
14718     public void readKernelUidCpuClusterTimesLocked(boolean onBattery,
14719             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
14720         final long startTimeMs = mClock.uptimeMillis();
14721         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14722         // If power is being accumulated for attribution, data needs to be read immediately.
14723         final boolean forceRead = powerAccumulator != null;
14724         mCpuUidClusterTimeReader.readDelta(forceRead, (uid, cpuClusterTimesMs) -> {
14725             uid = mapUid(uid);
14726             if (Process.isIsolated(uid)) {
14727                 if (DEBUG) Slog.w(TAG, "Got cluster times for an isolated uid: " + uid);
14728                 return;
14729             }
14730             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14731                 if (DEBUG) Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
14732                 return;
14733             }
14734             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
14735             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
14736 
14737             if (powerAccumulator != null) {
14738                 powerAccumulator.addCpuClusterDurationsMs(u, cpuClusterTimesMs);
14739             }
14740         });
14741 
14742         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14743         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14744             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
14745         }
14746     }
14747 
14748     boolean setChargingLocked(boolean charging) {
14749         // if the device is no longer charging, remove the callback
14750         // if the device is now charging, it means that this is either called
14751         // 1. directly when level >= 90
14752         // 2. or from within the runnable that we deferred
14753         // For 1. if we have an existing callback, remove it, since we will immediately send a
14754         // ACTION_CHARGING
14755         // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
14756         mHandler.removeCallbacks(mDeferSetCharging);
14757         if (mCharging != charging) {
14758             mCharging = charging;
14759             mHistory.setChargingState(charging);
14760             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
14761             return true;
14762         }
14763         return false;
14764     }
14765 
14766     /**
14767      * Notifies BatteryStatsImpl that the system server is ready.
14768      */
14769     public void onSystemReady(Context context) {
14770         if (mCpuUidFreqTimeReader != null) {
14771             mCpuUidFreqTimeReader.onSystemReady();
14772         }
14773 
14774         mStepDetailsProvider.onSystemReady();
14775 
14776         mPowerStatsCollectorInjector.setContext(context);
14777 
14778         mCpuPowerStatsCollector.setEnabled(
14779                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU));
14780         mCpuPowerStatsCollector.schedule();
14781 
14782         mWakelockPowerStatsCollector.setEnabled(
14783                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_WAKELOCK));
14784         mWakelockPowerStatsCollector.schedule();
14785 
14786         mScreenPowerStatsCollector.setEnabled(
14787                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_SCREEN));
14788         mScreenPowerStatsCollector.schedule();
14789 
14790         mMobileRadioPowerStatsCollector.setEnabled(
14791                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO));
14792         mMobileRadioPowerStatsCollector.schedule();
14793 
14794         mWifiPowerStatsCollector.setEnabled(
14795                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI));
14796         mWifiPowerStatsCollector.schedule();
14797 
14798         mBluetoothPowerStatsCollector.setEnabled(
14799                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_BLUETOOTH));
14800         mBluetoothPowerStatsCollector.schedule();
14801 
14802         mCameraPowerStatsCollector.setEnabled(
14803                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CAMERA));
14804         mCameraPowerStatsCollector.schedule();
14805 
14806         mGnssPowerStatsCollector.setEnabled(
14807                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_GNSS));
14808         mGnssPowerStatsCollector.schedule();
14809 
14810         mCustomEnergyConsumerPowerStatsCollector.setEnabled(
14811                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_ANY));
14812         mCustomEnergyConsumerPowerStatsCollector.schedule();
14813 
14814         mSystemReady = true;
14815     }
14816 
14817     /**
14818      * Returns a PowerStatsCollector for the specified power component or null if unavailable.
14819      */
14820     @Nullable
14821     PowerStatsCollector getPowerStatsCollector(
14822             @BatteryConsumer.PowerComponent int powerComponent) {
14823         switch (powerComponent) {
14824             case BatteryConsumer.POWER_COMPONENT_CPU:
14825                 return mCpuPowerStatsCollector;
14826             case BatteryConsumer.POWER_COMPONENT_WAKELOCK:
14827                 return mWakelockPowerStatsCollector;
14828             case BatteryConsumer.POWER_COMPONENT_SCREEN:
14829                 return mScreenPowerStatsCollector;
14830             case BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO:
14831                 return mMobileRadioPowerStatsCollector;
14832             case BatteryConsumer.POWER_COMPONENT_WIFI:
14833                 return mWifiPowerStatsCollector;
14834             case BatteryConsumer.POWER_COMPONENT_BLUETOOTH:
14835                 return mBluetoothPowerStatsCollector;
14836             case BatteryConsumer.POWER_COMPONENT_CAMERA:
14837                 return mCameraPowerStatsCollector;
14838             case BatteryConsumer.POWER_COMPONENT_GNSS:
14839                 return mGnssPowerStatsCollector;
14840         }
14841         return null;
14842     }
14843 
14844 
14845     /**
14846      * Force recording of all history events regardless of the "charging" state.
14847      */
14848     @VisibleForTesting
14849     public void forceRecordAllHistory() {
14850         mHistory.forceRecordAllHistory();
14851         mRecordAllHistory = true;
14852     }
14853 
14854     /**
14855      * Might reset battery stats if conditions are met. Assumed the device is currently plugged in.
14856      */
14857     @VisibleForTesting
14858     @GuardedBy("this")
14859     public void maybeResetWhilePluggedInLocked() {
14860         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14861         if (shouldResetWhilePluggedInLocked(elapsedRealtimeMs)) {
14862             Slog.i(TAG,
14863                     "Resetting due to long plug in duration. elapsed time = " + elapsedRealtimeMs
14864                             + " ms, last plug in time = " + mBatteryPluggedInRealTimeMs
14865                             + " ms, last reset time = " + mRealtimeStartUs / 1000);
14866             startNewSession(RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION);
14867         }
14868 
14869         scheduleNextResetWhilePluggedInCheck();
14870     }
14871 
14872     @GuardedBy("this")
14873     private void scheduleNextResetWhilePluggedInCheck() {
14874         if (mAlarmManager == null) return;
14875         final long timeoutMs = mClock.currentTimeMillis()
14876                 + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14877                 * DateUtils.HOUR_IN_MILLIS;
14878         Calendar nextAlarm = Calendar.getInstance();
14879         nextAlarm.setTimeInMillis(timeoutMs);
14880 
14881         // Find the 2 AM the same day as the end of the minimum duration.
14882         // This logic does not handle a Daylight Savings transition, or a timezone change
14883         // while the alarm has been set. The need to reset after a long period while plugged
14884         // in is not strict enough to warrant a well architected out solution.
14885         nextAlarm.set(Calendar.MILLISECOND, 0);
14886         nextAlarm.set(Calendar.SECOND, 0);
14887         nextAlarm.set(Calendar.MINUTE, 0);
14888         nextAlarm.set(Calendar.HOUR_OF_DAY, 2);
14889         long possibleNextTimeMs = nextAlarm.getTimeInMillis();
14890         if (possibleNextTimeMs < timeoutMs) {
14891             // The 2AM on the day of the timeout, move on the next day.
14892             possibleNextTimeMs += DateUtils.DAY_IN_MILLIS;
14893         }
14894         final long nextTimeMs = possibleNextTimeMs;
14895         final AlarmManager am = mAlarmManager;
14896         mHandler.post(() -> am.setWindow(AlarmManager.RTC, nextTimeMs,
14897                 DateUtils.HOUR_IN_MILLIS,
14898                 TAG, mLongPlugInAlarmHandler, mHandler));
14899     }
14900 
14901 
14902     @GuardedBy("this")
14903     private boolean shouldResetWhilePluggedInLocked(long elapsedRealtimeMs) {
14904         if (mNoAutoReset) return false;
14905         if (!mSystemReady) return false;
14906         if (!mHistory.isResetEnabled()) return false;
14907 
14908         final long pluggedInThresholdMs = mBatteryPluggedInRealTimeMs
14909                 + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14910                 * DateUtils.HOUR_IN_MILLIS;
14911         if (elapsedRealtimeMs >= pluggedInThresholdMs) {
14912             // The device has been plugged in for a long time.
14913             final long resetThresholdMs = mRealtimeStartUs / 1000
14914                     + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14915                     * DateUtils.HOUR_IN_MILLIS;
14916             if (elapsedRealtimeMs >= resetThresholdMs) {
14917                 // And it has been a long time since the last reset.
14918                 return true;
14919             }
14920         }
14921 
14922         return false;
14923     }
14924 
14925     @GuardedBy("this")
14926     private boolean shouldResetOnUnplugLocked(int batteryStatus, int batteryLevel) {
14927         if (mNoAutoReset) return false;
14928         if (!mSystemReady) return false;
14929         if (!mHistory.isResetEnabled()) return false;
14930         if (mBatteryStatsConfig.shouldResetOnUnplugHighBatteryLevel()) {
14931             // Allow resetting due to currently being at high battery level
14932             if (batteryStatus == BatteryManager.BATTERY_STATUS_FULL) return true;
14933             if (batteryLevel >= 90) return true;
14934         }
14935         if (mBatteryStatsConfig.shouldResetOnUnplugAfterSignificantCharge()) {
14936             // Allow resetting after a significant charge (from a very low level to a now very
14937             // high level).
14938             if (mDischargePlugLevel < 20 && batteryLevel >= 80) return true;
14939         }
14940         if (getHighDischargeAmountSinceCharge() >= 200) {
14941             // Reset the stats if battery got partially charged and discharged repeatedly without
14942             // ever reaching the full charge.
14943             // This reset is done in order to prevent stats sessions from going on forever.
14944             // Exceedingly long battery sessions would lead to an overflow of
14945             // data structures such as mWakeupReasonStats.
14946             return true;
14947         }
14948 
14949         return false;
14950     }
14951 
14952     @GuardedBy("this")
14953     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
14954             final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
14955         boolean doWrite = false;
14956         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
14957         m.arg1 = onBattery ? 1 : 0;
14958         mHandler.sendMessage(m);
14959 
14960         final long uptimeUs = mSecUptime * 1000;
14961         final long realtimeUs = mSecRealtime * 1000;
14962         final int screenState = mScreenState;
14963         if (onBattery) {
14964             boolean reset = false;
14965             if (shouldResetOnUnplugLocked(oldStatus, level)) {
14966                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
14967                         + " dischargeLevel=" + mDischargePlugLevel
14968                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
14969                         + " highAmount=" + getHighDischargeAmountSinceCharge());
14970                 // Before we write, collect a snapshot of the final aggregated
14971                 // stats to be reported in the next checkin.  Only do this if we have
14972                 // a sufficient amount of data to make it interesting.
14973                 if (getLowDischargeAmountSinceCharge() >= 20) {
14974                     final long startTimeMs = SystemClock.uptimeMillis();
14975                     final Parcel parcel = Parcel.obtain();
14976                     writeSummaryToParcel(parcel, true);
14977                     final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
14978                     BackgroundThread.getHandler().post(new Runnable() {
14979                         @Override public void run() {
14980                             synchronized (mCheckinFile) {
14981                                 final long startTimeMs2 = SystemClock.uptimeMillis();
14982                                 FileOutputStream stream = null;
14983                                 try {
14984                                     stream = mCheckinFile.startWrite();
14985                                     stream.write(parcel.marshall());
14986                                     stream.flush();
14987                                     mCheckinFile.finishWrite(stream);
14988                                     mFrameworkStatsLogger.writeCommitSysConfigFile(
14989                                             "batterystats-checkin",
14990                                             initialTimeMs + SystemClock.uptimeMillis()
14991                                                     - startTimeMs2);
14992                                 } catch (IOException e) {
14993                                     Slog.w("BatteryStats",
14994                                             "Error writing checkin battery statistics", e);
14995                                     mCheckinFile.failWrite(stream);
14996                                 } finally {
14997                                     parcel.recycle();
14998                                 }
14999                             }
15000                         }
15001                     });
15002                 }
15003                 doWrite = true;
15004                 startNewSession(RESET_REASON_FULL_CHARGE);
15005                 if (chargeUah > 0 && level > 0) {
15006                     // Only use the reported coulomb charge value if it is supported and reported.
15007                     mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
15008                 }
15009                 reset = true;
15010                 mDischargeStepTracker.init();
15011             }
15012             if (mCharging) {
15013                 setChargingLocked(false);
15014             }
15015             mOnBattery = mOnBatteryInternal = true;
15016             mLastDischargeStepLevel = level;
15017             mMinDischargeStepLevel = level;
15018             mDischargeStepTracker.clearTime();
15019             mDailyDischargeStepTracker.clearTime();
15020             mInitStepMode = mCurStepMode;
15021             mModStepMode = 0;
15022             pullPendingStateUpdatesLocked();
15023             if (reset) {
15024                 mHistory.startRecordingHistory(mSecRealtime, mSecUptime, reset);
15025                 initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
15026             }
15027             mBatteryPluggedIn = false;
15028             if (mAlarmManager != null) {
15029                 final AlarmManager am = mAlarmManager;
15030                 mHandler.post(() -> {
15031                     // No longer plugged in. Cancel the long plug in alarm.
15032                     am.cancel(mLongPlugInAlarmHandler);
15033                 });
15034             }
15035             mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
15036             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
15037             if (Display.isOnState(screenState)) {
15038                 mDischargeScreenOnUnplugLevel = level;
15039                 mDischargeScreenDozeUnplugLevel = 0;
15040                 mDischargeScreenOffUnplugLevel = 0;
15041             } else if (Display.isDozeState(screenState)) {
15042                 mDischargeScreenOnUnplugLevel = 0;
15043                 mDischargeScreenDozeUnplugLevel = level;
15044                 mDischargeScreenOffUnplugLevel = 0;
15045             } else {
15046                 mDischargeScreenOnUnplugLevel = 0;
15047                 mDischargeScreenDozeUnplugLevel = 0;
15048                 mDischargeScreenOffUnplugLevel = level;
15049             }
15050             mDischargeAmountScreenOn = 0;
15051             mDischargeAmountScreenDoze = 0;
15052             mDischargeAmountScreenOff = 0;
15053             updateTimeBasesLocked(true, screenState, uptimeUs, realtimeUs);
15054         } else {
15055             mOnBattery = mOnBatteryInternal = false;
15056             pullPendingStateUpdatesLocked();
15057             mBatteryPluggedIn = true;
15058             mBatteryPluggedInRealTimeMs = mSecRealtime;
15059             mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
15060             mDischargeCurrentLevel = mDischargePlugLevel = level;
15061             if (level < mDischargeUnplugLevel) {
15062                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
15063                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
15064             }
15065             updateDischargeScreenLevelsLocked(screenState, screenState);
15066             updateTimeBasesLocked(false, screenState, uptimeUs, realtimeUs);
15067             mChargeStepTracker.init();
15068             mLastChargeStepLevel = level;
15069             mMaxChargeStepLevel = level;
15070             mInitStepMode = mCurStepMode;
15071             mModStepMode = 0;
15072             scheduleNextResetWhilePluggedInCheck();
15073         }
15074         if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
15075             if (mStatsFile != null && !mHistory.isReadOnly()) {
15076                 writeAsyncLocked();
15077             }
15078         }
15079     }
15080 
15081     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
15082         if (mExternalSync != null) {
15083             mExternalSync.scheduleSync(reason, updateFlags);
15084         }
15085     }
15086 
15087     // This should probably be exposed in the API, though it's not critical
15088     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
15089 
15090     @GuardedBy("this")
15091     public void setBatteryStateLocked(final int status, final int health, final int plugType,
15092             final int level, final int temp, final int voltageMv, final int chargeUah,
15093             final int chargeFullUah, final long chargeTimeToFullSeconds,
15094             final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) {
15095 
15096         reportChangesToStatsLog(status, plugType, level);
15097 
15098         boolean requestStepDetails = false;
15099         final boolean onBattery = isOnBattery(plugType, status);
15100         if (!mHaveBatteryLevel) {
15101             mHaveBatteryLevel = true;
15102             // We start out assuming that the device is plugged in (not
15103             // on battery).  If our first report is now that we are indeed
15104             // plugged in, then twiddle our state to correctly reflect that
15105             // since we won't be going through the full setOnBattery().
15106             if (onBattery == mOnBattery) {
15107                 mHistory.setPluggedInState(!onBattery);
15108             }
15109             mBatteryStatus = status;
15110             mBatteryLevel = level;
15111             mBatteryChargeUah = chargeUah;
15112 
15113             // Always start out assuming charging, that will be updated later.
15114             mHistory.setBatteryState(true /* charging */, status, level, chargeUah);
15115 
15116             mMaxChargeStepLevel = mMinDischargeStepLevel =
15117                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
15118             requestStepDetails = true;
15119         } else if (mBatteryLevel != level || mOnBattery != onBattery) {
15120             recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
15121         }
15122         int oldStatus = mBatteryStatus;
15123         if (onBattery) {
15124             mDischargeCurrentLevel = level;
15125             if (!mHistory.isRecordingHistory()) {
15126                 mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
15127             }
15128         } else if (level < 96 &&
15129                 status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
15130             if (!mHistory.isRecordingHistory()) {
15131                 mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
15132             }
15133         }
15134         if (mDischargePlugLevel < 0) {
15135             mDischargePlugLevel = level;
15136         }
15137 
15138         if (onBattery != mOnBattery) {
15139             mBatteryLevel = level;
15140             mBatteryStatus = status;
15141             mBatteryHealth = health;
15142             mBatteryPlugType = plugType;
15143             mBatteryTemperature = temp;
15144             mBatteryVoltageMv = voltageMv;
15145             mHistory.setBatteryState(status, level, health, plugType, temp, voltageMv, chargeUah);
15146             if (chargeUah < mBatteryChargeUah) {
15147                 // Only record discharges
15148                 final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
15149                 mDischargeCounter.addCountLocked(chargeDiff);
15150                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
15151                 if (Display.isDozeState(mScreenState)) {
15152                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
15153                 }
15154                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
15155                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
15156                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
15157                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
15158                 }
15159             }
15160             mBatteryChargeUah = chargeUah;
15161             setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
15162             requestStepDetails = true;
15163         } else {
15164             boolean changed = false;
15165             if (mBatteryLevel != level) {
15166                 mBatteryLevel = level;
15167                 changed = true;
15168                 requestStepDetails = true;
15169             }
15170             if (mBatteryStatus != status) {
15171                 mBatteryStatus = status;
15172                 changed = true;
15173             }
15174             if (mBatteryHealth != health) {
15175                 mBatteryHealth = health;
15176                 changed = true;
15177             }
15178             if (mBatteryPlugType != plugType) {
15179                 mBatteryPlugType = plugType;
15180                 changed = true;
15181             }
15182             if (temp >= (mBatteryTemperature + 10)
15183                     || temp <= (mBatteryTemperature - 10)) {
15184                 mBatteryTemperature = temp;
15185                 changed = true;
15186             }
15187             if (voltageMv > (mBatteryVoltageMv + 20)
15188                     || voltageMv < (mBatteryVoltageMv - 20)) {
15189                 mBatteryVoltageMv = voltageMv;
15190                 changed = true;
15191             }
15192             if (chargeUah >= (mBatteryChargeUah + 10)
15193                     || chargeUah <= (mBatteryChargeUah - 10)) {
15194                 if (chargeUah < mBatteryChargeUah) {
15195                     // Only record discharges
15196                     final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
15197                     mDischargeCounter.addCountLocked(chargeDiff);
15198                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
15199                     if (Display.isDozeState(mScreenState)) {
15200                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
15201                     }
15202                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
15203                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
15204                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
15205                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
15206                     }
15207                 }
15208                 mBatteryChargeUah = chargeUah;
15209                 changed = true;
15210             }
15211 
15212             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
15213                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
15214                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
15215             if (onBattery) {
15216                 changed |= setChargingLocked(false);
15217                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
15218                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
15219                             modeBits, elapsedRealtimeMs);
15220                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
15221                             modeBits, elapsedRealtimeMs);
15222                     mLastDischargeStepLevel = level;
15223                     mMinDischargeStepLevel = level;
15224                     mInitStepMode = mCurStepMode;
15225                     mModStepMode = 0;
15226                 }
15227             } else {
15228                 if (level >= mConstants.BATTERY_CHARGING_ENFORCE_LEVEL) {
15229                     // If the battery level is at least Constants.BATTERY_CHARGING_ENFORCE_LEVEL,
15230                     // always consider the device to be charging even if it happens to go down a
15231                     // level.
15232                     changed |= setChargingLocked(true);
15233                 } else if (!mCharging) {
15234                     if (mLastChargeStepLevel < level) {
15235                         // We have not reported that we are charging, but the level has gone up,
15236                         // but we would like to not have tons of activity from charging-constraint
15237                         // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
15238                         if (!mHandler.hasCallbacks(mDeferSetCharging)) {
15239                             mHandler.postDelayed(
15240                                     mDeferSetCharging,
15241                                     mConstants.BATTERY_CHARGED_DELAY_MS);
15242                         }
15243                     } else if (mLastChargeStepLevel > level) {
15244                         // if we had deferred a runnable due to charge level increasing, but then
15245                         // later the charge level drops (could be due to thermal issues), we don't
15246                         // want to trigger the deferred runnable, so remove it here
15247                         mHandler.removeCallbacks(mDeferSetCharging);
15248                     }
15249                 } else {
15250                     if (mLastChargeStepLevel > level) {
15251                         // We had reported that the device was charging, but here we are with
15252                         // power connected and the level going down.  Looks like the current
15253                         // power supplied isn't enough, so consider the device to now be
15254                         // discharging.
15255                         changed |= setChargingLocked(false);
15256                     }
15257                 }
15258                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
15259                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
15260                             modeBits, elapsedRealtimeMs);
15261                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
15262                             modeBits, elapsedRealtimeMs);
15263                     mMaxChargeStepLevel = level;
15264                     mInitStepMode = mCurStepMode;
15265                     mModStepMode = 0;
15266                 }
15267                 mLastChargeStepLevel = level;
15268             }
15269             if (changed) {
15270                 mHistory.setBatteryState(mBatteryStatus, mBatteryLevel, mBatteryHealth,
15271                         mBatteryPlugType, mBatteryTemperature, mBatteryVoltageMv,
15272                         mBatteryChargeUah);
15273                 mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
15274             }
15275         }
15276         mLastLearnedBatteryCapacityUah = chargeFullUah;
15277         if (mMinLearnedBatteryCapacityUah == -1) {
15278             mMinLearnedBatteryCapacityUah = chargeFullUah;
15279         } else {
15280             mMinLearnedBatteryCapacityUah = Math.min(mMinLearnedBatteryCapacityUah, chargeFullUah);
15281         }
15282         mMaxLearnedBatteryCapacityUah = Math.max(mMaxLearnedBatteryCapacityUah, chargeFullUah);
15283 
15284         mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
15285 
15286         if (mAccumulateBatteryUsageStats) {
15287             mBatteryUsageStatsProvider.accumulateBatteryUsageStatsAsync(this, mHandler);
15288         }
15289         if (requestStepDetails) {
15290             mStepDetailsProvider.requestUpdate();
15291         }
15292     }
15293 
15294     public static boolean isOnBattery(int plugType, int status) {
15295         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
15296     }
15297 
15298     // Inform StatsLog of setBatteryState changes.
15299     private void reportChangesToStatsLog(final int status, final int plugType, final int level) {
15300         if (!mHaveBatteryLevel || mBatteryStatus != status) {
15301             mFrameworkStatsLogger.chargingStateChanged(status);
15302         }
15303         if (!mHaveBatteryLevel || mBatteryPlugType != plugType) {
15304             mFrameworkStatsLogger.pluggedStateChanged(plugType);
15305         }
15306         if (!mHaveBatteryLevel || mBatteryLevel != level) {
15307             mFrameworkStatsLogger.batteryLevelChanged(level);
15308         }
15309     }
15310 
15311     public long getAwakeTimeBattery() {
15312         // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
15313         // for over a decade, but surely that was a mistake.
15314         return getBatteryUptimeLocked(mClock.uptimeMillis());
15315     }
15316 
15317     public long getAwakeTimePlugged() {
15318         return (mClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
15319     }
15320 
15321     @Override
15322     public long computeUptime(long curTimeUs, int which) {
15323         return mUptimeUs + (curTimeUs - mUptimeStartUs);
15324     }
15325 
15326     @Override
15327     public long computeRealtime(long curTimeUs, int which) {
15328         return mRealtimeUs + (curTimeUs - mRealtimeStartUs);
15329     }
15330 
15331     @Override
15332     public long computeBatteryUptime(long curTimeUs, int which) {
15333         return mOnBatteryTimeBase.computeUptime(curTimeUs, which);
15334     }
15335 
15336     @Override
15337     public long computeBatteryRealtime(long curTimeUs, int which) {
15338         return mOnBatteryTimeBase.computeRealtime(curTimeUs, which);
15339     }
15340 
15341     @Override
15342     public long computeBatteryScreenOffUptime(long curTimeUs, int which) {
15343         return mOnBatteryScreenOffTimeBase.computeUptime(curTimeUs, which);
15344     }
15345 
15346     @Override
15347     public long computeBatteryScreenOffRealtime(long curTimeUs, int which) {
15348         return mOnBatteryScreenOffTimeBase.computeRealtime(curTimeUs, which);
15349     }
15350 
15351     @Override
15352     public long computeBatteryTimeRemaining(long curTime) {
15353         if (!mOnBattery) {
15354             return -1;
15355         }
15356         /* Simple implementation just looks at the average discharge per level across the
15357            entire sample period.
15358         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
15359         if (discharge < 2) {
15360             return -1;
15361         }
15362         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
15363         if (duration < 1000*1000) {
15364             return -1;
15365         }
15366         long usPerLevel = duration/discharge;
15367         return usPerLevel * mCurrentBatteryLevel;
15368         */
15369         if (mDischargeStepTracker.mNumStepDurations < 1) {
15370             return -1;
15371         }
15372         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
15373         if (msPerLevel <= 0) {
15374             return -1;
15375         }
15376         return (msPerLevel * mBatteryLevel) * 1000;
15377     }
15378 
15379     @Override
15380     public LevelStepTracker getDischargeLevelStepTracker() {
15381         return mDischargeStepTracker;
15382     }
15383 
15384     @Override
15385     public LevelStepTracker getDailyDischargeLevelStepTracker() {
15386         return mDailyDischargeStepTracker;
15387     }
15388 
15389     @Override
15390     public long computeChargeTimeRemaining(long curTime) {
15391         if (mOnBattery) {
15392             // Not yet working.
15393             return -1;
15394         }
15395         if (mBatteryTimeToFullSeconds >= 0) {
15396             return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us
15397         }
15398         // Else use algorithmic approach
15399         if (mChargeStepTracker.mNumStepDurations < 1) {
15400             return -1;
15401         }
15402         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
15403         if (msPerLevel <= 0) {
15404             return -1;
15405         }
15406         return (msPerLevel * (100 - mBatteryLevel)) * 1000;
15407     }
15408 
15409     /*@hide */
15410     public CellularBatteryStats getCellularBatteryStats() {
15411         final int which = STATS_SINCE_CHARGED;
15412         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
15413         final ControllerActivityCounter counter = getModemControllerActivity();
15414         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
15415         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
15416         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
15417         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
15418         final long monitoredRailChargeConsumedMaMs =
15419                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
15420         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
15421         for (int i = 0; i < timeInRatMs.length; i++) {
15422             timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTimeUs, which) / 1000;
15423         }
15424         long[] timeInRxSignalStrengthLevelMs =
15425                 new long[CELL_SIGNAL_STRENGTH_LEVEL_COUNT];
15426         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
15427             timeInRxSignalStrengthLevelMs[i] =
15428                 getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
15429         }
15430         long[] txTimeMs = new long[Math.min(MODEM_TX_POWER_LEVEL_COUNT,
15431             counter.getTxTimeCounters().length)];
15432         long totalTxTimeMs = 0;
15433         for (int i = 0; i < txTimeMs.length; i++) {
15434             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
15435             totalTxTimeMs += txTimeMs[i];
15436         }
15437 
15438         return new CellularBatteryStats(computeBatteryRealtime(rawRealTimeUs, which) / 1000,
15439                 getMobileRadioActiveTime(rawRealTimeUs, which) / 1000,
15440                 getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which),
15441                 getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which),
15442                 getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which),
15443                 getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which),
15444                 sleepTimeMs, idleTimeMs, rxTimeMs, energyConsumedMaMs, timeInRatMs,
15445                 timeInRxSignalStrengthLevelMs, txTimeMs,
15446                 monitoredRailChargeConsumedMaMs);
15447     }
15448 
15449     /*@hide */
15450     public WifiBatteryStats getWifiBatteryStats() {
15451         final int which = STATS_SINCE_CHARGED;
15452         final long rawRealTimeUs = mClock.elapsedRealtime() * 1000;
15453         final ControllerActivityCounter counter = getWifiControllerActivity();
15454         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
15455         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
15456         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
15457         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
15458         final long totalControllerActivityTimeMs =
15459                 computeBatteryRealtime(mClock.elapsedRealtime() * 1000, which) / 1000;
15460         final long sleepTimeMs = Math.max(0,
15461                 totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs));
15462         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
15463         final long monitoredRailChargeConsumedMaMs =
15464                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
15465         long numAppScanRequest = 0;
15466         for (int i = 0; i < mUidStats.size(); i++) {
15467             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
15468         }
15469         long[] timeInStateMs = new long[NUM_WIFI_STATES];
15470         for (int i=0; i<NUM_WIFI_STATES; i++) {
15471             timeInStateMs[i] = getWifiStateTime(i, rawRealTimeUs, which) / 1000;
15472         }
15473         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
15474         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15475             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTimeUs, which) / 1000;
15476         }
15477         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
15478         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15479             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
15480         }
15481         return new WifiBatteryStats(
15482                 computeBatteryRealtime(rawRealTimeUs, which) / 1000,
15483                 getWifiActiveTime(rawRealTimeUs, which) / 1000,
15484                 getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which),
15485                 getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which),
15486                 getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which),
15487                 getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which),
15488                 sleepTimeMs, scanTimeMs, idleTimeMs, rxTimeMs, txTimeMs, energyConsumedMaMs,
15489                 numAppScanRequest, timeInStateMs, timeSignalStrengthTimeMs, timeInSupplStateMs,
15490                 monitoredRailChargeConsumedMaMs);
15491     }
15492 
15493     /*@hide */
15494     public GpsBatteryStats getGpsBatteryStats() {
15495         GpsBatteryStats s = new GpsBatteryStats();
15496         final int which = STATS_SINCE_CHARGED;
15497         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
15498         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000);
15499         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
15500         long[] time = new long[mGpsSignalQualityTimer.length];
15501         for (int i=0; i<time.length; i++) {
15502             time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000;
15503         }
15504         s.setTimeInGpsSignalQualityLevel(time);
15505         return s;
15506     }
15507 
15508     @Override
15509     public LevelStepTracker getChargeLevelStepTracker() {
15510         return mChargeStepTracker;
15511     }
15512 
15513     @Override
15514     public LevelStepTracker getDailyChargeLevelStepTracker() {
15515         return mDailyChargeStepTracker;
15516     }
15517 
15518     @Override
15519     public ArrayList<PackageChange> getDailyPackageChanges() {
15520         return mDailyPackageChanges;
15521     }
15522 
15523     /**
15524      * @return battery uptime in microseconds
15525      */
15526     protected long getBatteryUptimeLocked(long uptimeMs) {
15527         return mOnBatteryTimeBase.getUptime(uptimeMs * 1000);
15528     }
15529 
15530     @Override
15531     public long getBatteryUptime(long curTimeUs) {
15532         return mOnBatteryTimeBase.getUptime(curTimeUs);
15533     }
15534 
15535     @Override
15536     public long getBatteryRealtime(long curTimeUs) {
15537         return mOnBatteryTimeBase.getRealtime(curTimeUs);
15538     }
15539 
15540     @Override
15541     public int getDischargeStartLevel() {
15542         synchronized(this) {
15543             return getDischargeStartLevelLocked();
15544         }
15545     }
15546 
15547     public int getDischargeStartLevelLocked() {
15548             return mDischargeUnplugLevel;
15549     }
15550 
15551     @Override
15552     public int getDischargeCurrentLevel() {
15553         synchronized(this) {
15554             return getDischargeCurrentLevelLocked();
15555         }
15556     }
15557 
15558     public int getDischargeCurrentLevelLocked() {
15559         return mDischargeCurrentLevel;
15560     }
15561 
15562     @Override
15563     public int getLowDischargeAmountSinceCharge() {
15564         synchronized(this) {
15565             int val = mLowDischargeAmountSinceCharge;
15566             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
15567                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
15568             }
15569             return val;
15570         }
15571     }
15572 
15573     @Override
15574     public int getHighDischargeAmountSinceCharge() {
15575         synchronized(this) {
15576             int val = mHighDischargeAmountSinceCharge;
15577             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
15578                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
15579             }
15580             return val;
15581         }
15582     }
15583 
15584     @Override
15585     public int getDischargeAmount(int which) {
15586         int dischargeAmount = which == STATS_SINCE_CHARGED
15587                 ? getHighDischargeAmountSinceCharge()
15588                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
15589         if (dischargeAmount < 0) {
15590             dischargeAmount = 0;
15591         }
15592         return dischargeAmount;
15593     }
15594 
15595     @Override
15596     public int getDischargeAmountScreenOn() {
15597         synchronized(this) {
15598             int val = mDischargeAmountScreenOn;
15599             if (mOnBattery && Display.isOnState(mScreenState)
15600                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
15601                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
15602             }
15603             return val;
15604         }
15605     }
15606 
15607     @Override
15608     public int getDischargeAmountScreenOnSinceCharge() {
15609         synchronized(this) {
15610             int val = mDischargeAmountScreenOnSinceCharge;
15611             if (mOnBattery && Display.isOnState(mScreenState)
15612                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
15613                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
15614             }
15615             return val;
15616         }
15617     }
15618 
15619     @Override
15620     public int getDischargeAmountScreenOff() {
15621         synchronized(this) {
15622             int val = mDischargeAmountScreenOff;
15623             if (mOnBattery && Display.isOffState(mScreenState)
15624                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
15625                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
15626             }
15627             // For backward compatibility, doze discharge is counted into screen off.
15628             return val + getDischargeAmountScreenDoze();
15629         }
15630     }
15631 
15632     @Override
15633     public int getDischargeAmountScreenOffSinceCharge() {
15634         synchronized(this) {
15635             int val = mDischargeAmountScreenOffSinceCharge;
15636             if (mOnBattery && Display.isOffState(mScreenState)
15637                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
15638                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
15639             }
15640             // For backward compatibility, doze discharge is counted into screen off.
15641             return val + getDischargeAmountScreenDozeSinceCharge();
15642         }
15643     }
15644 
15645     @Override
15646     public int getDischargeAmountScreenDoze() {
15647         synchronized(this) {
15648             int val = mDischargeAmountScreenDoze;
15649             if (mOnBattery && Display.isDozeState(mScreenState)
15650                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
15651                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
15652             }
15653             return val;
15654         }
15655     }
15656 
15657     @Override
15658     public int getDischargeAmountScreenDozeSinceCharge() {
15659         synchronized(this) {
15660             int val = mDischargeAmountScreenDozeSinceCharge;
15661             if (mOnBattery && Display.isDozeState(mScreenState)
15662                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
15663                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
15664             }
15665             return val;
15666         }
15667     }
15668 
15669 
15670     /**
15671      * Estimates the time spent by the system server handling incoming binder requests.
15672      */
15673     @Override
15674     public long[] getSystemServiceTimeAtCpuSpeeds() {
15675         if (mBinderThreadCpuTimesUs == null) {
15676             return null;
15677         }
15678 
15679         return mBinderThreadCpuTimesUs.getCountsLocked(BatteryStats.STATS_SINCE_CHARGED);
15680     }
15681 
15682     /**
15683      * Retrieve the statistics object for a particular uid, creating if needed.
15684      */
15685     public Uid getUidStatsLocked(int uid) {
15686         return getUidStatsLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
15687     }
15688 
15689     public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
15690         Uid u = mUidStats.get(uid);
15691         if (u == null) {
15692             if (Process.isSdkSandboxUid(uid)) {
15693                 Log.wtf(TAG, "Tracking an SDK Sandbox UID");
15694             }
15695             u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
15696             mUidStats.put(uid, u);
15697         }
15698         return u;
15699     }
15700 
15701     /**
15702      * Retrieve the statistics object for a particular uid. Returns null if the object is not
15703      * available.
15704      */
15705     public Uid getAvailableUidStatsLocked(int uid) {
15706         Uid u = mUidStats.get(uid);
15707         return u;
15708     }
15709 
15710     @GuardedBy("this")
15711     public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) {
15712         final int firstUidForUser = UserHandle.getUid(userId, 0);
15713         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
15714         mPendingRemovedUids.add(
15715                 new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs));
15716     }
15717 
15718     @GuardedBy("this")
15719     public void onUserRemovedLocked(int userId) {
15720         if (mExternalSync != null) {
15721             // Clear out the removed user's UIDs after a short delay. The delay is needed
15722             // because at the point that this method is called, some activities are still
15723             // being wrapped up by those UIDs
15724             mExternalSync.scheduleCleanupDueToRemovedUser(userId);
15725         }
15726     }
15727 
15728     /**
15729      * Removes battery stats for UIDs corresponding to a removed user.
15730      */
15731     @GuardedBy("this")
15732     public void clearRemovedUserUidsLocked(int userId) {
15733         final int firstUidForUser = UserHandle.getUid(userId, 0);
15734         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
15735         mUidStats.put(firstUidForUser, null);
15736         mUidStats.put(lastUidForUser, null);
15737         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
15738         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
15739         for (int i = firstIndex; i <= lastIndex; i++) {
15740             final Uid uid = mUidStats.valueAt(i);
15741             if (uid != null) {
15742                 uid.detachFromTimeBase();
15743             }
15744         }
15745         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
15746         removeCpuStatsForUidRangeLocked(firstUidForUser, lastUidForUser);
15747     }
15748 
15749     /**
15750      * @see #removeUidStatsLocked(int)
15751      */
15752     @GuardedBy("this")
15753     public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) {
15754         final Uid u = mUidStats.get(uid);
15755         if (u != null) {
15756             u.detachFromTimeBase();
15757         }
15758         mUidStats.remove(uid);
15759         mPendingRemovedUids.add(new UidToRemove(uid, elapsedRealtimeMs));
15760     }
15761 
15762     /**
15763      * Removes the data for the deleted UIDs from the underlying kernel eBPF tables.
15764      */
15765     @GuardedBy("this")
15766     private void removeCpuStatsForUidRangeLocked(int startUid, int endUid) {
15767         if (startUid == endUid) {
15768             mCpuUidUserSysTimeReader.removeUid(startUid);
15769             mCpuUidFreqTimeReader.removeUid(startUid);
15770             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
15771                 mCpuUidActiveTimeReader.removeUid(startUid);
15772                 mCpuUidClusterTimeReader.removeUid(startUid);
15773             }
15774             if (mKernelSingleUidTimeReader != null) {
15775                 mKernelSingleUidTimeReader.removeUid(startUid);
15776             }
15777             mNumUidsRemoved++;
15778         } else if (startUid < endUid) {
15779             mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
15780             mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
15781             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
15782                 mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
15783                 mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
15784             }
15785             if (mKernelSingleUidTimeReader != null) {
15786                 mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
15787             }
15788             mPowerStatsUidResolver.releaseUidsInRange(startUid, endUid);
15789             // Treat as one. We don't know how many uids there are in between.
15790             mNumUidsRemoved++;
15791         } else {
15792             Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
15793         }
15794     }
15795 
15796     /**
15797      * Retrieve the statistics object for a particular process, creating
15798      * if needed.
15799      */
15800     public Uid.Proc getProcessStatsLocked(int uid, String name,
15801             long elapsedRealtimeMs, long uptimeMs) {
15802         uid = mapUid(uid);
15803         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15804         return u.getProcessStatsLocked(name);
15805     }
15806 
15807     /**
15808      * Retrieve the statistics object for a particular process, creating
15809      * if needed.
15810      */
15811     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
15812         return getPackageStatsLocked(uid, pkg, mClock.elapsedRealtime(), mClock.uptimeMillis());
15813     }
15814 
15815     /**
15816      * @see getPackageStatsLocked(int, String)
15817      */
15818     public Uid.Pkg getPackageStatsLocked(int uid, String pkg,
15819             long elapsedRealtimeMs, long uptimeMs) {
15820         uid = mapUid(uid);
15821         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15822         return u.getPackageStatsLocked(pkg);
15823     }
15824 
15825     /**
15826      * Retrieve the statistics object for a particular service, creating
15827      * if needed.
15828      */
15829     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name,
15830             long elapsedRealtimeMs, long uptimeMs) {
15831         uid = mapUid(uid);
15832         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15833         return u.getServiceStatsLocked(pkg, name);
15834     }
15835 
15836     @GuardedBy("this")
15837     public void shutdownLocked() {
15838         mHistory.recordShutdownEvent(mClock.elapsedRealtime(), mClock.uptimeMillis(),
15839                 mClock.currentTimeMillis());
15840         writeSyncLocked();
15841         mShuttingDown = true;
15842     }
15843 
15844     @Override
15845     public boolean isProcessStateDataAvailable() {
15846         synchronized (this) {
15847             return trackPerProcStateCpuTimes();
15848         }
15849     }
15850 
15851     @GuardedBy("this")
15852     private boolean trackPerProcStateCpuTimes() {
15853         return mCpuUidFreqTimeReader.isFastCpuTimesReader();
15854     }
15855 
15856     /**
15857      * Enables or disables the PowerStatsCollector mode.
15858      */
15859     public void setPowerStatsCollectorEnabled(@BatteryConsumer.PowerComponent int powerComponent,
15860             boolean enabled) {
15861         synchronized (this) {
15862             mPowerStatsCollectorEnabled.put(powerComponent, enabled);
15863         }
15864     }
15865 
15866     /**
15867      * Controls where the logging of the WakelockStateChanged atom occurs:
15868      *   true = Notifier, false = BatteryStatsImpl.
15869      */
15870     public void setMoveWscLoggingToNotifierEnabled(boolean enabled) {
15871         synchronized (this) {
15872             mMoveWscLoggingToNotifierEnabled = enabled;
15873         }
15874     }
15875     @GuardedBy("this")
15876     public void systemServicesReady(Context context) {
15877         mConstants.startObserving(context.getContentResolver());
15878         registerUsbStateReceiver(context);
15879 
15880         synchronized (this) {
15881             mAlarmManager = context.getSystemService(AlarmManager.class);
15882             if (mBatteryPluggedIn) {
15883                 // Already plugged in. Schedule the long plug in alarm.
15884                 scheduleNextResetWhilePluggedInCheck();
15885             }
15886 
15887             if (mPowerManagerFlags.isFrameworkWakelockInfoEnabled()) {
15888                 mFrameworkEvents.initialize(context);
15889             }
15890         }
15891     }
15892 
15893     /**
15894      * Initialize the EnergyConsumer stats data structures.
15895      *
15896      * @param supportedStandardBuckets boolean array indicating which {@link StandardPowerBucket}s
15897      *                                 are currently supported. If null, none are supported
15898      *                                 (regardless of customBucketNames).
15899      * @param customBucketNames        names of custom (OTHER) EnergyConsumers on this device
15900      */
15901     @GuardedBy("this")
15902     public void initEnergyConsumerStatsLocked(@Nullable boolean[] supportedStandardBuckets,
15903             String[] customBucketNames) {
15904         final int numDisplays = mPerDisplayBatteryStats.length;
15905         for (int i = 0; i < numDisplays; i++) {
15906             final int screenState = mPerDisplayBatteryStats[i].screenState;
15907             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
15908         }
15909 
15910         if (supportedStandardBuckets != null) {
15911             final EnergyConsumerStats.Config config = new EnergyConsumerStats.Config(
15912                     supportedStandardBuckets, customBucketNames,
15913                     SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS,
15914                     getBatteryConsumerProcessStateNames());
15915 
15916             if (mEnergyConsumerStatsConfig != null
15917                     &&  !mEnergyConsumerStatsConfig.isCompatible(config)) {
15918                 // Supported power buckets changed since last boot.
15919                 // Save accumulated battery usage stats before resetting
15920                 saveBatteryUsageStatsOnReset();
15921                 // Existing data is no longer reliable.
15922                 resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
15923                         RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE);
15924             }
15925 
15926             mEnergyConsumerStatsConfig = config;
15927             mGlobalEnergyConsumerStats = new EnergyConsumerStats(config);
15928 
15929             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_BLUETOOTH]) {
15930                 mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
15931             }
15932             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO]) {
15933                 mMobileRadioPowerCalculator = new MobileRadioPowerCalculator(mPowerProfile);
15934             }
15935             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_WIFI]) {
15936                 mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
15937             }
15938         } else {
15939             if (mEnergyConsumerStatsConfig != null) {
15940                 // EnergyConsumer no longer supported
15941                 // Save accumulated battery usage stats before resetting
15942                 saveBatteryUsageStatsOnReset();
15943                 // Wipe out the current battery session data.
15944                 resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
15945                         RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE);
15946             }
15947             mEnergyConsumerStatsConfig = null;
15948             mGlobalEnergyConsumerStats = null;
15949         }
15950     }
15951 
15952     @GuardedBy("this")
15953     private boolean isMobileRadioEnergyConsumerSupportedLocked() {
15954         if (mGlobalEnergyConsumerStats == null) return false;
15955         return mGlobalEnergyConsumerStats.isStandardBucketSupported(
15956                 EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
15957     }
15958 
15959     @NonNull
15960     private static String[] getBatteryConsumerProcessStateNames() {
15961         String[] procStateNames = new String[BatteryConsumer.PROCESS_STATE_COUNT];
15962         for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
15963             procStateNames[procState] = BatteryConsumer.processStateToString(procState);
15964         }
15965         return procStateNames;
15966     }
15967 
15968     /** Get the last known Battery voltage (in millivolts), returns -1 if unknown */
15969     @GuardedBy("this")
15970     public int getBatteryVoltageMvLocked() {
15971         return mBatteryVoltageMv;
15972     }
15973 
15974     @VisibleForTesting
15975     public final class Constants extends ContentObserver {
15976         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
15977                 = "track_cpu_active_cluster_time";
15978         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
15979                 = "kernel_uid_readers_throttle_time";
15980         public static final String KEY_UID_REMOVE_DELAY_MS
15981                 = "uid_remove_delay_ms";
15982         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
15983                 = "external_stats_collection_rate_limit_ms";
15984         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
15985                 = "battery_level_collection_delay_ms";
15986         public static final String KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS =
15987                 "procstate_change_collection_delay_ms";
15988         public static final String KEY_MAX_HISTORY_SIZE = "max_history_size";
15989         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
15990         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
15991                 "battery_charged_delay_ms";
15992         public static final String KEY_BATTERY_CHARGING_ENFORCE_LEVEL =
15993                 "battery_charging_enforce_level";
15994         public static final String KEY_PER_UID_MODEM_POWER_MODEL =
15995                 "per_uid_modem_power_model";
15996         public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
15997                 "phone_on_external_stats_collection";
15998         public static final String KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS =
15999                 "reset_while_plugged_in_minimum_duration_hours";
16000 
16001         public static final String PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME =
16002                 "mobile_radio_active_time";
16003         public static final String PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME =
16004                 "modem_activity_info_rx_tx";
16005 
16006         /** Convert {@link PerUidModemPowerModel} to string */
16007         public String getPerUidModemModelName(@PerUidModemPowerModel int model) {
16008             switch(model) {
16009                 case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME:
16010                     return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME;
16011                 case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX:
16012                     return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME;
16013                 default:
16014                     Slog.w(TAG, "Unexpected per uid modem model (" + model + ")");
16015                     return "unknown_" + model;
16016             }
16017         }
16018 
16019         /** Convert string to {@link PerUidModemPowerModel} */
16020         @PerUidModemPowerModel
16021         public int getPerUidModemModel(String name) {
16022             switch(name) {
16023                 case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME:
16024                     return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME;
16025                 case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME:
16026                     return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
16027                 default:
16028                     Slog.w(TAG, "Unexpected per uid modem model name (" + name + ")");
16029                     return DEFAULT_PER_UID_MODEM_MODEL;
16030             }
16031         }
16032 
16033         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
16034         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
16035         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
16036         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
16037         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
16038         private static final long DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS = 60_000;
16039         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
16040         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
16041         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
16042         private static final int DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL = 90;
16043         @PerUidModemPowerModel
16044         private static final int DEFAULT_PER_UID_MODEM_MODEL =
16045                 PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
16046         private static final boolean DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION = true;
16047         // Little less than 2 days
16048         private static final int DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = 47;
16049 
16050         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
16051         /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
16052          * update when startObserving. */
16053         public long KERNEL_UID_READERS_THROTTLE_TIME;
16054         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
16055         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
16056                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
16057         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
16058                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
16059         public long PROC_STATE_CHANGE_COLLECTION_DELAY_MS =
16060                 DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS;
16061         public int MAX_HISTORY_SIZE;
16062         public int MAX_HISTORY_BUFFER; /*Bytes*/
16063         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
16064         public int BATTERY_CHARGING_ENFORCE_LEVEL = DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL;
16065         public int PER_UID_MODEM_MODEL = DEFAULT_PER_UID_MODEM_MODEL;
16066         public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
16067                 DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
16068         public int RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS =
16069                 DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS;
16070 
16071         private ContentResolver mResolver;
16072         private final KeyValueListParser mParser = new KeyValueListParser(',');
16073 
16074         public Constants(Handler handler) {
16075             super(handler);
16076             if (isLowRamDevice()) {
16077                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
16078             } else {
16079                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
16080             }
16081             MAX_HISTORY_SIZE = mBatteryStatsConfig.getMaxHistorySizeBytes();
16082         }
16083 
16084         public void startObserving(ContentResolver resolver) {
16085             mResolver = resolver;
16086             mResolver.registerContentObserver(
16087                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
16088                     false /* notifyForDescendants */, this);
16089             mResolver.registerContentObserver(
16090                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
16091                     false /* notifyForDescendants */, this);
16092             mResolver.registerContentObserver(Settings.Global.getUriFor(
16093                             Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL),
16094                     false /* notifyForDescendants */, this);
16095             updateConstants();
16096         }
16097 
16098         @Override
16099         public void onChange(boolean selfChange, Uri uri) {
16100             if (uri.equals(
16101                     Settings.Global.getUriFor(
16102                             Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY))) {
16103                 synchronized (BatteryStatsImpl.this) {
16104                     updateBatteryChargedDelayMsLocked();
16105                 }
16106                 return;
16107             } else if (uri.equals(Settings.Global.getUriFor(
16108                     Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL))) {
16109                 synchronized (BatteryStatsImpl.this) {
16110                     updateBatteryChargingEnforceLevelLocked();
16111                 }
16112                 return;
16113             }
16114             updateConstants();
16115         }
16116 
16117         private void updateConstants() {
16118             synchronized (BatteryStatsImpl.this) {
16119                 try {
16120                     mParser.setString(Settings.Global.getString(mResolver,
16121                             Settings.Global.BATTERY_STATS_CONSTANTS));
16122                 } catch (IllegalArgumentException e) {
16123                     // Failed to parse the settings string, log this and move on
16124                     // with defaults.
16125                     Slog.e(TAG, "Bad batterystats settings", e);
16126                 }
16127 
16128                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
16129                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
16130                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
16131                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
16132                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
16133                 updateUidRemoveDelay(
16134                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
16135                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
16136                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
16137                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
16138                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
16139                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
16140                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
16141                 PROC_STATE_CHANGE_COLLECTION_DELAY_MS = mParser.getLong(
16142                         KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS,
16143                         DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
16144                 MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
16145                         isLowRamDevice() ? DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
16146                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
16147                         * 1024;
16148                 int maxHistorySize = mParser.getInt(KEY_MAX_HISTORY_SIZE, -1);
16149                 if (maxHistorySize == -1) {
16150                     // Process the deprecated max_history_files parameter for compatibility
16151                     int maxHistoryFiles = mParser.getInt("max_history_files", -1);
16152                     if (maxHistoryFiles != -1) {
16153                         maxHistorySize = maxHistoryFiles * MAX_HISTORY_BUFFER;
16154                     }
16155                 }
16156                 if (maxHistorySize == -1) {
16157                     maxHistorySize = mBatteryStatsConfig.getMaxHistorySizeBytes();
16158                 }
16159                 MAX_HISTORY_SIZE = maxHistorySize;
16160 
16161                 final String perUidModemModel = mParser.getString(KEY_PER_UID_MODEM_POWER_MODEL,
16162                         "");
16163                 PER_UID_MODEM_MODEL = getPerUidModemModel(perUidModemModel);
16164 
16165                 PHONE_ON_EXTERNAL_STATS_COLLECTION = mParser.getBoolean(
16166                         KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION,
16167                         DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION);
16168 
16169                 RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = mParser.getInt(
16170                         KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS,
16171                         DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
16172 
16173                 updateBatteryChargedDelayMsLocked();
16174                 updateBatteryChargingEnforceLevelLocked();
16175 
16176                 onChange();
16177             }
16178         }
16179 
16180         /**
16181          * Propagates changes in constant values.
16182          */
16183         @VisibleForTesting
16184         public void onChange() {
16185             if (mBatteryHistoryDirectory != null) {
16186                 mBatteryHistoryDirectory.setMaxHistorySize(MAX_HISTORY_SIZE);
16187             }
16188             mHistory.setMaxHistoryBufferSize(MAX_HISTORY_BUFFER);
16189         }
16190 
16191         private void updateBatteryChargedDelayMsLocked() {
16192             // a negative value indicates that we should ignore this override
16193             final int delay = Settings.Global.getInt(mResolver,
16194                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
16195                     -1);
16196 
16197             BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
16198                     KEY_BATTERY_CHARGED_DELAY_MS,
16199                     DEFAULT_BATTERY_CHARGED_DELAY_MS);
16200 
16201             if (mHandler.hasCallbacks(mDeferSetCharging)) {
16202                 mHandler.removeCallbacks(mDeferSetCharging);
16203                 mHandler.postDelayed(mDeferSetCharging, BATTERY_CHARGED_DELAY_MS);
16204             }
16205         }
16206 
16207         private void updateBatteryChargingEnforceLevelLocked() {
16208             int lastChargingEnforceLevel = BATTERY_CHARGING_ENFORCE_LEVEL;
16209             final int level = Settings.Global.getInt(mResolver,
16210                     Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL,
16211                     -1);
16212 
16213             BATTERY_CHARGING_ENFORCE_LEVEL = level >= 0 ? level : mParser.getInt(
16214                     KEY_BATTERY_CHARGING_ENFORCE_LEVEL, DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL);
16215 
16216             if (BATTERY_CHARGING_ENFORCE_LEVEL <= mLastChargeStepLevel
16217                     && mLastChargeStepLevel < lastChargingEnforceLevel) {
16218                 setChargingLocked(true);
16219             }
16220         }
16221 
16222         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
16223             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
16224             if (oldTimeMs != newTimeMs) {
16225                 mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16226                 mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16227                 mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16228                 mCpuUidClusterTimeReader
16229                         .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16230             }
16231         }
16232 
16233         @GuardedBy("BatteryStatsImpl.this")
16234         private void updateUidRemoveDelay(long newTimeMs) {
16235             UID_REMOVE_DELAY_MS = newTimeMs;
16236             clearPendingRemovedUidsLocked();
16237         }
16238 
16239         public void dumpLocked(PrintWriter pw) {
16240             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
16241             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
16242             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
16243             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
16244             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
16245             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
16246             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
16247             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
16248             pw.print(KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS); pw.print("=");
16249             pw.println(PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
16250             pw.print(KEY_MAX_HISTORY_SIZE); pw.print("=");
16251             pw.println(MAX_HISTORY_SIZE);
16252             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
16253             pw.println(MAX_HISTORY_BUFFER/1024);
16254             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
16255             pw.println(BATTERY_CHARGED_DELAY_MS);
16256             pw.print(KEY_BATTERY_CHARGING_ENFORCE_LEVEL); pw.print("=");
16257             pw.println(BATTERY_CHARGING_ENFORCE_LEVEL);
16258             pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("=");
16259             pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL));
16260             pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");
16261             pw.println(PHONE_ON_EXTERNAL_STATS_COLLECTION);
16262             pw.print(KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS); pw.print("=");
16263             pw.println(RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
16264         }
16265     }
16266 
16267     public long getExternalStatsCollectionRateLimitMs() {
16268         synchronized (this) {
16269             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
16270         }
16271     }
16272 
16273     @GuardedBy("this")
16274     public void dumpConstantsLocked(PrintWriter pw) {
16275         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16276         iPw.println("BatteryStats constants:");
16277         iPw.increaseIndent();
16278         mConstants.dumpLocked(iPw);
16279         iPw.decreaseIndent();
16280     }
16281 
16282     @GuardedBy("this")
16283     public void dumpCpuStatsLocked(PrintWriter pw) {
16284         int size = mUidStats.size();
16285         pw.println("Per UID CPU user & system time in ms:");
16286         for (int i = 0; i < size; i++) {
16287             int u = mUidStats.keyAt(i);
16288             Uid uid = mUidStats.get(u);
16289             pw.print("  "); pw.print(u); pw.print(": ");
16290             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
16291             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
16292         }
16293 
16294         pw.println("Per UID CPU active time in ms:");
16295         for (int i = 0; i < size; i++) {
16296             int u = mUidStats.keyAt(i);
16297             Uid uid = mUidStats.get(u);
16298             if (uid.getCpuActiveTime() > 0) {
16299                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
16300             }
16301         }
16302         pw.println("Per UID CPU cluster time in ms:");
16303         for (int i = 0; i < size; i++) {
16304             int u = mUidStats.keyAt(i);
16305             long[] times = mUidStats.get(u).getCpuClusterTimes();
16306             if (times != null) {
16307                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
16308             }
16309         }
16310         pw.println("Per UID CPU frequency time in ms:");
16311         for (int i = 0; i < size; i++) {
16312             int u = mUidStats.keyAt(i);
16313             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
16314             if (times != null) {
16315                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
16316             }
16317         }
16318 
16319         if (!Flags.disableSystemServicePowerAttr()) {
16320             updateSystemServiceCallStats();
16321             if (mBinderThreadCpuTimesUs != null) {
16322                 pw.println("Per UID System server binder time in ms:");
16323                 long[] systemServiceTimeAtCpuSpeeds = getSystemServiceTimeAtCpuSpeeds();
16324                 for (int i = 0; i < size; i++) {
16325                     int u = mUidStats.keyAt(i);
16326                     Uid uid = mUidStats.get(u);
16327                     double proportionalSystemServiceUsage = uid.getProportionalSystemServiceUsage();
16328                     long timeUs = 0;
16329                     for (int j = systemServiceTimeAtCpuSpeeds.length - 1; j >= 0; j--) {
16330                         timeUs += systemServiceTimeAtCpuSpeeds[j] * proportionalSystemServiceUsage;
16331                     }
16332 
16333                     pw.print("  ");
16334                     pw.print(u);
16335                     pw.print(": ");
16336                     pw.println(timeUs / 1000);
16337                 }
16338             }
16339         }
16340     }
16341 
16342     /**
16343      * Dump EnergyConsumer stats
16344      */
16345     @GuardedBy("this")
16346     public void dumpEnergyConsumerStatsLocked(PrintWriter pw) {
16347         pw.printf("On-battery energy consumer stats (microcoulombs) \n");
16348         if (mGlobalEnergyConsumerStats == null) {
16349             pw.printf("    Not supported on this device.\n");
16350             return;
16351         }
16352 
16353         dumpEnergyConsumerStatsLocked(pw, "global usage", mGlobalEnergyConsumerStats);
16354 
16355         int size = mUidStats.size();
16356         for (int i = 0; i < size; i++) {
16357             final int u = mUidStats.keyAt(i);
16358             final Uid uid = mUidStats.get(u);
16359             final String name = "uid " + uid.mUid;
16360             dumpEnergyConsumerStatsLocked(pw, name, uid.mUidEnergyConsumerStats);
16361         }
16362     }
16363 
16364     /** Dump EnergyConsumer stats for the given uid */
16365     @GuardedBy("this")
16366     private void dumpEnergyConsumerStatsLocked(PrintWriter pw, String name,
16367             EnergyConsumerStats stats) {
16368         if (stats == null) return;
16369         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16370         iPw.increaseIndent();
16371         iPw.printf("%s:\n", name);
16372         iPw.increaseIndent();
16373         stats.dump(iPw);
16374         iPw.decreaseIndent();
16375     }
16376 
16377     /**
16378      * Dump Power Profile
16379      */
16380     @GuardedBy("this")
16381     public void dumpPowerProfileLocked(PrintWriter pw) {
16382         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16383         iPw.printf("Power Profile: \n");
16384         iPw.increaseIndent();
16385         mPowerProfile.dump(iPw);
16386         iPw.decreaseIndent();
16387     }
16388 
16389     /**
16390      * Schedules an immediate (but asynchronous) collection of PowerStats samples.
16391      * Callers will need to wait for the collection to complete on the handler thread.
16392      */
16393     public void schedulePowerStatsSampleCollection() {
16394         if (!mSystemReady) {
16395             return;
16396         }
16397 
16398         mCpuPowerStatsCollector.forceSchedule();
16399         mWakelockPowerStatsCollector.forceSchedule();
16400         mScreenPowerStatsCollector.forceSchedule();
16401         mMobileRadioPowerStatsCollector.forceSchedule();
16402         mWifiPowerStatsCollector.forceSchedule();
16403         mBluetoothPowerStatsCollector.forceSchedule();
16404         mCameraPowerStatsCollector.forceSchedule();
16405         mGnssPowerStatsCollector.forceSchedule();
16406         mCustomEnergyConsumerPowerStatsCollector.forceSchedule();
16407     }
16408 
16409     /**
16410      * Schedules an immediate collection of PowerStats samples and awaits the result.
16411      */
16412     public void collectPowerStatsSamples() {
16413         schedulePowerStatsSampleCollection();
16414         ConditionVariable done = new ConditionVariable();
16415         mHandler.post(done::open);
16416         done.block();
16417     }
16418 
16419     /**
16420      * Grabs one sample of PowerStats and prints it.
16421      */
16422     public void dumpStatsSample(PrintWriter pw) {
16423         mCpuPowerStatsCollector.collectAndDump(pw);
16424         mWakelockPowerStatsCollector.collectAndDump(pw);
16425         mScreenPowerStatsCollector.collectAndDump(pw);
16426         mMobileRadioPowerStatsCollector.collectAndDump(pw);
16427         mWifiPowerStatsCollector.collectAndDump(pw);
16428         mBluetoothPowerStatsCollector.collectAndDump(pw);
16429         mCameraPowerStatsCollector.collectAndDump(pw);
16430         mGnssPowerStatsCollector.collectAndDump(pw);
16431         mCustomEnergyConsumerPowerStatsCollector.collectAndDump(pw);
16432     }
16433 
16434     private final Runnable mWriteAsyncRunnable = () -> {
16435         synchronized (BatteryStatsImpl.this) {
16436             writeSyncLocked();
16437         }
16438     };
16439 
16440     @GuardedBy("this")
16441     public void writeAsyncLocked() {
16442         BackgroundThread.getHandler().removeCallbacks(mWriteAsyncRunnable);
16443         BackgroundThread.getHandler().post(mWriteAsyncRunnable);
16444     }
16445 
16446     @GuardedBy("this")
16447     public void writeSyncLocked() {
16448         BackgroundThread.getHandler().removeCallbacks(mWriteAsyncRunnable);
16449         writeStatsLocked();
16450         writeHistoryLocked();
16451     }
16452 
16453     @GuardedBy("this")
16454     private void writeStatsLocked() {
16455         if (mStatsFile == null) {
16456             Slog.w(TAG,
16457                     "writeStatsLocked: no file associated with this instance");
16458             return;
16459         }
16460 
16461         if (mShuttingDown) {
16462             return;
16463         }
16464 
16465         final Parcel p = Parcel.obtain();
16466         try {
16467             final long start = SystemClock.uptimeMillis();
16468             writeSummaryToParcel(p, false/*history is in separate file*/);
16469             if (DEBUG) {
16470                 Slog.d(TAG, "writeSummaryToParcel duration ms:"
16471                         + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
16472             }
16473             mLastWriteTimeMs = mClock.elapsedRealtime();
16474             writeParcelToFileLocked(p, mStatsFile);
16475         } finally {
16476             p.recycle();
16477         }
16478     }
16479 
16480     private void writeHistoryLocked() {
16481         if (mShuttingDown) {
16482             return;
16483         }
16484 
16485         mHistory.writeHistory();
16486     }
16487 
16488     private final ReentrantLock mWriteLock = new ReentrantLock();
16489     private void writeParcelToFileLocked(Parcel p, AtomicFile file) {
16490         mWriteLock.lock();
16491         FileOutputStream fos = null;
16492         try {
16493             final long startTimeMs = SystemClock.uptimeMillis();
16494             fos = file.startWrite();
16495             fos.write(p.marshall());
16496             fos.flush();
16497             file.finishWrite(fos);
16498             if (DEBUG) {
16499                 Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
16500                         + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
16501                         + " bytes:" + p.dataSize());
16502             }
16503             mFrameworkStatsLogger.writeCommitSysConfigFile(
16504                     "batterystats", SystemClock.uptimeMillis() - startTimeMs);
16505         } catch (IOException e) {
16506             Slog.w(TAG, "Error writing battery statistics", e);
16507             file.failWrite(fos);
16508         } finally {
16509             mWriteLock.unlock();
16510         }
16511     }
16512 
16513     @GuardedBy("this")
16514     public void readLocked() {
16515         if (mDailyFile != null) {
16516             readDailyStatsLocked();
16517         }
16518 
16519         if (mStatsFile == null) {
16520             Slog.w(TAG, "readLocked: no file associated with this instance");
16521             return;
16522         }
16523 
16524         mUidStats.clear();
16525 
16526         Parcel stats = Parcel.obtain();
16527         try {
16528             final long start = SystemClock.uptimeMillis();
16529             if (mStatsFile.exists()) {
16530                 byte[] raw = mStatsFile.readFully();
16531                 stats.unmarshall(raw, 0, raw.length);
16532                 stats.setDataPosition(0);
16533                 readSummaryFromParcel(stats);
16534                 if (DEBUG) {
16535                     Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
16536                             + " bytes:" + raw.length + " took ms:" + (SystemClock.uptimeMillis()
16537                             - start));
16538                 }
16539             }
16540         } catch (Exception e) {
16541             Slog.e(TAG, "Error reading battery statistics", e);
16542             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
16543                     RESET_REASON_CORRUPT_FILE);
16544         } finally {
16545             stats.recycle();
16546         }
16547 
16548         if (!mHistory.readSummary()) {
16549             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
16550                     RESET_REASON_CORRUPT_FILE);
16551         }
16552 
16553         mEndPlatformVersion = Build.ID;
16554 
16555         mMonotonicEndTime = MonotonicClock.UNDEFINED;
16556         mHistory.continueRecordingHistory();
16557 
16558         recordDailyStatsIfNeededLocked(false, mClock.currentTimeMillis());
16559     }
16560 
16561     @GuardedBy("this")
16562     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
16563         final int version = in.readInt();
16564 
16565         if (version != VERSION) {
16566             Slog.w("BatteryStats", "readFromParcel: version got " + version
16567                 + ", expected " + VERSION + "; erasing old stats");
16568             return;
16569         }
16570 
16571         mHistory.readSummaryFromParcel(in);
16572 
16573         mStartCount = in.readInt();
16574         mUptimeUs = in.readLong();
16575         mRealtimeUs = in.readLong();
16576         mStartClockTimeMs = in.readLong();
16577         mMonotonicStartTime = in.readLong();
16578         mMonotonicEndTime = in.readLong();
16579         mStartPlatformVersion = in.readString();
16580         mEndPlatformVersion = in.readString();
16581         mOnBatteryTimeBase.readSummaryFromParcel(in);
16582         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
16583         mDischargeUnplugLevel = in.readInt();
16584         mDischargePlugLevel = in.readInt();
16585         mDischargeCurrentLevel = in.readInt();
16586         mBatteryLevel = in.readInt();
16587         mEstimatedBatteryCapacityMah = in.readInt();
16588         mLastLearnedBatteryCapacityUah = in.readInt();
16589         mMinLearnedBatteryCapacityUah = in.readInt();
16590         mMaxLearnedBatteryCapacityUah = in.readInt();
16591         mLowDischargeAmountSinceCharge = in.readInt();
16592         mHighDischargeAmountSinceCharge = in.readInt();
16593         mDischargeAmountScreenOnSinceCharge = in.readInt();
16594         mDischargeAmountScreenOffSinceCharge = in.readInt();
16595         mDischargeAmountScreenDozeSinceCharge = in.readInt();
16596         mDischargeStepTracker.readFromParcel(in);
16597         mChargeStepTracker.readFromParcel(in);
16598         mDailyDischargeStepTracker.readFromParcel(in);
16599         mDailyChargeStepTracker.readFromParcel(in);
16600         mDischargeCounter.readSummaryFromParcelLocked(in);
16601         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
16602         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
16603         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
16604         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
16605         int NPKG = in.readInt();
16606         if (NPKG > 0) {
16607             mDailyPackageChanges = new ArrayList<>(NPKG);
16608             while (NPKG > 0) {
16609                 NPKG--;
16610                 PackageChange pc = new PackageChange();
16611                 pc.mPackageName = in.readString();
16612                 pc.mUpdate = in.readInt() != 0;
16613                 pc.mVersionCode = in.readLong();
16614                 mDailyPackageChanges.add(pc);
16615             }
16616         } else {
16617             mDailyPackageChanges = null;
16618         }
16619         mDailyStartTimeMs = in.readLong();
16620         mNextMinDailyDeadlineMs = in.readLong();
16621         mNextMaxDailyDeadlineMs = in.readLong();
16622         mBatteryTimeToFullSeconds = in.readLong();
16623 
16624         final EnergyConsumerStats.Config config = EnergyConsumerStats.Config.createFromParcel(in);
16625         final EnergyConsumerStats energyConsumerStats =
16626                 EnergyConsumerStats.createAndReadSummaryFromParcel(mEnergyConsumerStatsConfig, in);
16627         if (config != null && Arrays.equals(config.getStateNames(),
16628                 getBatteryConsumerProcessStateNames())) {
16629             /**
16630              * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
16631              *          later when {@link #initEnergyConsumerStatsLocked} is called.
16632              */
16633             mEnergyConsumerStatsConfig = config;
16634             mGlobalEnergyConsumerStats = energyConsumerStats;
16635         }
16636 
16637         mStartCount++;
16638 
16639         mScreenState = Display.STATE_UNKNOWN;
16640         mScreenOnTimer.readSummaryFromParcelLocked(in);
16641         mScreenDozeTimer.readSummaryFromParcelLocked(in);
16642         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16643             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
16644         }
16645         final int numDisplays = in.readInt();
16646         for (int i = 0; i < numDisplays; i++) {
16647             mPerDisplayBatteryStats[i].readSummaryFromParcel(in);
16648         }
16649         mInteractive = false;
16650         mInteractiveTimer.readSummaryFromParcelLocked(in);
16651         mPhoneOn = false;
16652         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
16653         mLongestLightIdleTimeMs = in.readLong();
16654         mLongestFullIdleTimeMs = in.readLong();
16655         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
16656         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
16657         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
16658         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
16659         mPhoneOnTimer.readSummaryFromParcelLocked(in);
16660         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
16661             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
16662         }
16663         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
16664         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
16665             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
16666         }
16667         mNrNsaTimer.readSummaryFromParcelLocked(in);
16668         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16669             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
16670             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
16671         }
16672 
16673         final int numRat = in.readInt();
16674         for (int i = 0; i < numRat; i++) {
16675             if (in.readInt() == 0) continue;
16676             getRatBatteryStatsLocked(i).readSummaryFromParcel(in);
16677         }
16678 
16679         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
16680         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
16681         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
16682         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
16683         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
16684         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
16685         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
16686         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
16687         mWifiOn = false;
16688         mWifiOnTimer.readSummaryFromParcelLocked(in);
16689         mGlobalWifiRunning = false;
16690         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
16691         for (int i=0; i<NUM_WIFI_STATES; i++) {
16692             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
16693         }
16694         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
16695             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
16696         }
16697         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16698             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
16699         }
16700         mWifiActiveTimer.readSummaryFromParcelLocked(in);
16701         mWifiActivity.readSummaryFromParcel(in);
16702         for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
16703             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
16704         }
16705         mBluetoothActivity.readSummaryFromParcel(in);
16706         mModemActivity.readSummaryFromParcel(in);
16707         mHasWifiReporting = in.readInt() != 0;
16708         mHasBluetoothReporting = in.readInt() != 0;
16709         mHasModemReporting = in.readInt() != 0;
16710 
16711         mNumConnectivityChange = in.readInt();
16712         mFlashlightOnNesting = 0;
16713         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
16714         mCameraOnNesting = 0;
16715         mCameraOnTimer.readSummaryFromParcelLocked(in);
16716         mBluetoothScanNesting = 0;
16717         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
16718 
16719         int NRPMS = in.readInt();
16720         if (NRPMS > 10000) {
16721             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
16722         }
16723         for (int irpm = 0; irpm < NRPMS; irpm++) {
16724             if (in.readInt() != 0) {
16725                 String rpmName = in.readString();
16726                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
16727             }
16728         }
16729         int NSORPMS = in.readInt();
16730         if (NSORPMS > 10000) {
16731             throw new ParcelFormatException(
16732                     "File corrupt: too many screen-off rpm stats " + NSORPMS);
16733         }
16734         for (int irpm = 0; irpm < NSORPMS; irpm++) {
16735             if (in.readInt() != 0) {
16736                 String rpmName = in.readString();
16737                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
16738             }
16739         }
16740         int NKW = in.readInt();
16741         if (NKW > 10000) {
16742             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
16743         }
16744         for (int ikw = 0; ikw < NKW; ikw++) {
16745             if (in.readInt() != 0) {
16746                 String kwltName = in.readString();
16747                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
16748             }
16749         }
16750 
16751         int NWR = in.readInt();
16752         if (NWR > 10000) {
16753             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
16754         }
16755         for (int iwr = 0; iwr < NWR; iwr++) {
16756             if (in.readInt() != 0) {
16757                 String reasonName = in.readString();
16758                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
16759             }
16760         }
16761 
16762         int NMS = in.readInt();
16763         for (int ims = 0; ims < NMS; ims++) {
16764             if (in.readInt() != 0) {
16765                 long kmstName = in.readLong();
16766                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
16767             }
16768         }
16769 
16770         final int NU = in.readInt();
16771         if (NU > 10000) {
16772             throw new ParcelFormatException("File corrupt: too many uids " + NU);
16773         }
16774         final long elapsedRealtimeMs = mClock.elapsedRealtime();
16775         final long uptimeMs = mClock.uptimeMillis();
16776         for (int iu = 0; iu < NU; iu++) {
16777             int uid = in.readInt();
16778             Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
16779             mUidStats.put(uid, u);
16780 
16781             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
16782             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
16783 
16784             u.mWifiRunning = false;
16785             if (in.readInt() != 0) {
16786                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
16787             }
16788             u.mFullWifiLockOut = false;
16789             if (in.readInt() != 0) {
16790                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
16791             }
16792             u.mWifiScanStarted = false;
16793             if (in.readInt() != 0) {
16794                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
16795             }
16796             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
16797             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
16798                 if (in.readInt() != 0) {
16799                     u.makeWifiBatchedScanBin(i, null);
16800                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
16801                 }
16802             }
16803             u.mWifiMulticastWakelockCount = 0;
16804             if (in.readInt() != 0) {
16805                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
16806             }
16807             if (in.readInt() != 0) {
16808                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16809             }
16810             if (in.readInt() != 0) {
16811                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16812             }
16813             if (in.readInt() != 0) {
16814                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16815             }
16816             if (in.readInt() != 0) {
16817                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16818             }
16819             if (in.readInt() != 0) {
16820                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
16821             }
16822             if (in.readInt() != 0) {
16823                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
16824             }
16825             if (in.readInt() != 0) {
16826                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
16827             }
16828             if (in.readInt() != 0) {
16829                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
16830             }
16831             if (in.readInt() != 0) {
16832                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
16833             }
16834             if (in.readInt() != 0) {
16835                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
16836             }
16837             if (in.readInt() != 0) {
16838                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
16839             }
16840             u.mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
16841             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
16842                 if (in.readInt() != 0) {
16843                     u.makeProcessState(i, null);
16844                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
16845                 }
16846             }
16847             if (in.readInt() != 0) {
16848                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
16849             }
16850 
16851             if (in.readInt() != 0) {
16852                 if (u.mUserActivityCounters == null) {
16853                     u.initUserActivityLocked();
16854                 }
16855                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
16856                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
16857                 }
16858             }
16859 
16860             if (in.readInt() != 0) {
16861                 u.ensureNetworkActivityLocked();
16862                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16863                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
16864                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
16865                 }
16866                 if (in.readBoolean()) {
16867                     u.mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in,
16868                             mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
16869                             elapsedRealtimeMs);
16870                 }
16871                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
16872             }
16873 
16874             u.mUserCpuTime.readSummaryFromParcelLocked(in);
16875             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
16876 
16877             if (in.readInt() != 0) {
16878                 final int numClusters = in.readInt();
16879                 int[] policies =
16880                         mCpuScalingPolicies != null ? mCpuScalingPolicies.getPolicies() : null;
16881                 if (policies != null && policies.length != numClusters) {
16882                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
16883                 }
16884                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
16885                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
16886                 for (int cluster = 0; cluster < numClusters; cluster++) {
16887                     if (in.readInt() != 0) {
16888                         final int NSB = in.readInt();
16889                         if (policies != null
16890                                 && mCpuScalingPolicies.getFrequencies(policies[cluster]).length
16891                                 != NSB) {
16892                             throw new ParcelFormatException("File corrupt: too many speed bins " +
16893                                     NSB);
16894                         }
16895 
16896                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
16897                         for (int speed = 0; speed < NSB; speed++) {
16898                             if (in.readInt() != 0) {
16899                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
16900                                         mOnBatteryTimeBase);
16901                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
16902                             }
16903                         }
16904                     } else {
16905                         u.mCpuClusterSpeedTimesUs[cluster] = null;
16906                     }
16907                 }
16908             } else {
16909                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
16910                 u.mCpuClusterSpeedTimesUs = null;
16911             }
16912 
16913             detachIfNotNull(u.mCpuFreqTimeMs);
16914             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
16915                     in, mOnBatteryTimeBase);
16916             detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
16917             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
16918                     in, mOnBatteryScreenOffTimeBase);
16919 
16920             int stateCount = in.readInt();
16921             if (stateCount != 0) {
16922                 u.mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in,
16923                         mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
16924                         mClock.elapsedRealtime());
16925             }
16926             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
16927 
16928             detachIfNotNull(u.mProcStateTimeMs);
16929             u.mProcStateTimeMs = null;
16930 
16931             stateCount = in.readInt();
16932             if (stateCount != 0) {
16933                 detachIfNotNull(u.mProcStateTimeMs);
16934                 u.mProcStateTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
16935                         mOnBatteryTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
16936                         mCpuScalingPolicies.getScalingStepCount(), mClock.elapsedRealtime());
16937             }
16938 
16939             detachIfNotNull(u.mProcStateScreenOffTimeMs);
16940             u.mProcStateScreenOffTimeMs = null;
16941 
16942             stateCount = in.readInt();
16943             if (stateCount != 0) {
16944                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
16945                 u.mProcStateScreenOffTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
16946                         mOnBatteryScreenOffTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
16947                         mCpuScalingPolicies.getScalingStepCount(), mClock.elapsedRealtime());
16948             }
16949 
16950             if (in.readInt() != 0) {
16951                 detachIfNotNull(u.mMobileRadioApWakeupCount);
16952                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
16953                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
16954             } else {
16955                 detachIfNotNull(u.mMobileRadioApWakeupCount);
16956                 u.mMobileRadioApWakeupCount = null;
16957             }
16958 
16959             if (in.readInt() != 0) {
16960                 detachIfNotNull(u.mWifiRadioApWakeupCount);
16961                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
16962                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
16963             } else {
16964                 detachIfNotNull(u.mWifiRadioApWakeupCount);
16965                 u.mWifiRadioApWakeupCount = null;
16966             }
16967 
16968             u.mUidEnergyConsumerStats = EnergyConsumerStats.createAndReadSummaryFromParcel(
16969                     mEnergyConsumerStatsConfig, in);
16970 
16971             int NW = in.readInt();
16972             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
16973                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
16974             }
16975             for (int iw = 0; iw < NW; iw++) {
16976                 String wlName = in.readString();
16977                 u.readWakeSummaryFromParcelLocked(wlName, in);
16978             }
16979 
16980             int NS = in.readInt();
16981             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
16982                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
16983             }
16984             for (int is = 0; is < NS; is++) {
16985                 String name = in.readString();
16986                 u.readSyncSummaryFromParcelLocked(name, in);
16987             }
16988 
16989             int NJ = in.readInt();
16990             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
16991                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
16992             }
16993             for (int ij = 0; ij < NJ; ij++) {
16994                 String name = in.readString();
16995                 u.readJobSummaryFromParcelLocked(name, in);
16996             }
16997 
16998             u.readJobCompletionsFromParcelLocked(in);
16999 
17000             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
17001             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
17002             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
17003             detachIfNotNull(u.mJobsFreshnessBuckets);
17004             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
17005                 if (in.readInt() != 0) {
17006                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
17007                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
17008                 }
17009             }
17010 
17011             int NP = in.readInt();
17012             if (NP > 1000) {
17013                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
17014             }
17015             for (int is = 0; is < NP; is++) {
17016                 int seNumber = in.readInt();
17017                 if (in.readInt() != 0) {
17018                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
17019                 }
17020             }
17021 
17022             NP = in.readInt();
17023             if (NP > 10000) {
17024                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
17025             }
17026             for (int ip = 0; ip < NP; ip++) {
17027                 String procName = in.readString();
17028                 Uid.Proc p = u.getProcessStatsLocked(procName);
17029                 p.mUserTimeMs = in.readLong();
17030                 p.mSystemTimeMs = in.readLong();
17031                 p.mForegroundTimeMs = in.readLong();
17032                 p.mStarts = in.readInt();
17033                 p.mNumCrashes = in.readInt();
17034                 p.mNumAnrs = in.readInt();
17035                 p.readExcessivePowerFromParcelLocked(in);
17036             }
17037 
17038             NP = in.readInt();
17039             if (NP > 10000) {
17040                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
17041             }
17042             for (int ip = 0; ip < NP; ip++) {
17043                 String pkgName = in.readString();
17044                 detachIfNotNull(u.mPackageStats.get(pkgName));
17045                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
17046                 final int NWA = in.readInt();
17047                 if (NWA > 10000) {
17048                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
17049                 }
17050                 p.mWakeupAlarms.clear();
17051                 for (int iwa = 0; iwa < NWA; iwa++) {
17052                     String tag = in.readString();
17053                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
17054                     c.readSummaryFromParcelLocked(in);
17055                     p.mWakeupAlarms.put(tag, c);
17056                 }
17057                 NS = in.readInt();
17058                 if (NS > 10000) {
17059                     throw new ParcelFormatException("File corrupt: too many services " + NS);
17060                 }
17061                 for (int is = 0; is < NS; is++) {
17062                     String servName = in.readString();
17063                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
17064                     s.mStartTimeMs = in.readLong();
17065                     s.mStarts = in.readInt();
17066                     s.mLaunches = in.readInt();
17067                 }
17068             }
17069         }
17070 
17071         if (!Flags.disableSystemServicePowerAttr()) {
17072             mBinderThreadCpuTimesUs =
17073                     LongSamplingCounterArray.readSummaryFromParcelLocked(in, mOnBatteryTimeBase);
17074         }
17075     }
17076 
17077     /**
17078      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
17079      * disk.  This format does not allow a lossless round-trip.
17080      *
17081      * @param out the Parcel to be written to.
17082      */
17083     @GuardedBy("this")
17084     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
17085         pullPendingStateUpdatesLocked();
17086 
17087         // Pull the clock time.  This may update the time and make a new history entry
17088         // if we had originally pulled a time before the RTC was set.
17089         getStartClockTime();
17090 
17091         final long nowUptime = mClock.uptimeMillis() * 1000;
17092         final long nowRealtime = mClock.elapsedRealtime() * 1000;
17093 
17094         out.writeInt(VERSION);
17095 
17096         mHistory.writeSummaryToParcel(out, inclHistory);
17097 
17098         out.writeInt(mStartCount);
17099         out.writeLong(computeUptime(nowUptime, STATS_SINCE_CHARGED));
17100         out.writeLong(computeRealtime(nowRealtime, STATS_SINCE_CHARGED));
17101         out.writeLong(mStartClockTimeMs);
17102         out.writeLong(mMonotonicStartTime);
17103         out.writeLong(mMonotonicClock.monotonicTime());
17104         out.writeString(mStartPlatformVersion);
17105         out.writeString(mEndPlatformVersion);
17106         mOnBatteryTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
17107         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
17108         out.writeInt(mDischargeUnplugLevel);
17109         out.writeInt(mDischargePlugLevel);
17110         out.writeInt(mDischargeCurrentLevel);
17111         out.writeInt(mBatteryLevel);
17112         out.writeInt(mEstimatedBatteryCapacityMah);
17113         out.writeInt(mLastLearnedBatteryCapacityUah);
17114         out.writeInt(mMinLearnedBatteryCapacityUah);
17115         out.writeInt(mMaxLearnedBatteryCapacityUah);
17116         out.writeInt(getLowDischargeAmountSinceCharge());
17117         out.writeInt(getHighDischargeAmountSinceCharge());
17118         out.writeInt(getDischargeAmountScreenOnSinceCharge());
17119         out.writeInt(getDischargeAmountScreenOffSinceCharge());
17120         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
17121         mDischargeStepTracker.writeToParcel(out);
17122         mChargeStepTracker.writeToParcel(out);
17123         mDailyDischargeStepTracker.writeToParcel(out);
17124         mDailyChargeStepTracker.writeToParcel(out);
17125         mDischargeCounter.writeSummaryFromParcelLocked(out);
17126         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
17127         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
17128         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
17129         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
17130         if (mDailyPackageChanges != null) {
17131             final int NPKG = mDailyPackageChanges.size();
17132             out.writeInt(NPKG);
17133             for (int i=0; i<NPKG; i++) {
17134                 PackageChange pc = mDailyPackageChanges.get(i);
17135                 out.writeString(pc.mPackageName);
17136                 out.writeInt(pc.mUpdate ? 1 : 0);
17137                 out.writeLong(pc.mVersionCode);
17138             }
17139         } else {
17140             out.writeInt(0);
17141         }
17142         out.writeLong(mDailyStartTimeMs);
17143         out.writeLong(mNextMinDailyDeadlineMs);
17144         out.writeLong(mNextMaxDailyDeadlineMs);
17145         out.writeLong(mBatteryTimeToFullSeconds);
17146 
17147         EnergyConsumerStats.Config.writeToParcel(mEnergyConsumerStatsConfig, out);
17148         EnergyConsumerStats.writeSummaryToParcel(mGlobalEnergyConsumerStats, out);
17149 
17150         mScreenOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17151         mScreenDozeTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17152         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
17153             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17154         }
17155         final int numDisplays = mPerDisplayBatteryStats.length;
17156         out.writeInt(numDisplays);
17157         for (int i = 0; i < numDisplays; i++) {
17158             mPerDisplayBatteryStats[i].writeSummaryToParcel(out, nowRealtime);
17159         }
17160         mInteractiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17161         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17162         out.writeLong(mLongestLightIdleTimeMs);
17163         out.writeLong(mLongestFullIdleTimeMs);
17164         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17165         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17166         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17167         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17168         mPhoneOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17169         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
17170             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17171         }
17172         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17173         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
17174             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17175         }
17176         mNrNsaTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17177         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
17178             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
17179             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
17180         }
17181         final int numRat = mPerRatBatteryStats.length;
17182         out.writeInt(numRat);
17183         for (int i = 0; i < numRat; i++) {
17184             final RadioAccessTechnologyBatteryStats ratStat = mPerRatBatteryStats[i];
17185             if (ratStat == null) {
17186                 out.writeInt(0);
17187                 continue;
17188             }
17189             out.writeInt(1);
17190             ratStat.writeSummaryToParcel(out, nowRealtime);
17191         }
17192         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17193         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17194         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
17195         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
17196         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
17197         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17198         mWifiOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17199         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17200         for (int i=0; i<NUM_WIFI_STATES; i++) {
17201             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17202         }
17203         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
17204             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17205         }
17206         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
17207             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17208         }
17209         mWifiActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17210         mWifiActivity.writeSummaryToParcel(out);
17211         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
17212             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17213         }
17214         mBluetoothActivity.writeSummaryToParcel(out);
17215         mModemActivity.writeSummaryToParcel(out);
17216         out.writeInt(mHasWifiReporting ? 1 : 0);
17217         out.writeInt(mHasBluetoothReporting ? 1 : 0);
17218         out.writeInt(mHasModemReporting ? 1 : 0);
17219 
17220         out.writeInt(mNumConnectivityChange);
17221         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17222         mCameraOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17223         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17224 
17225         out.writeInt(mRpmStats.size());
17226         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
17227             Timer rpmt = ent.getValue();
17228             if (rpmt != null) {
17229                 out.writeInt(1);
17230                 out.writeString(ent.getKey());
17231                 rpmt.writeSummaryFromParcelLocked(out, nowRealtime);
17232             } else {
17233                 out.writeInt(0);
17234             }
17235         }
17236         out.writeInt(mScreenOffRpmStats.size());
17237         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
17238             Timer rpmt = ent.getValue();
17239             if (rpmt != null) {
17240                 out.writeInt(1);
17241                 out.writeString(ent.getKey());
17242                 rpmt.writeSummaryFromParcelLocked(out, nowRealtime);
17243             } else {
17244                 out.writeInt(0);
17245             }
17246         }
17247 
17248         out.writeInt(mKernelWakelockStats.size());
17249         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
17250             Timer kwlt = ent.getValue();
17251             if (kwlt != null) {
17252                 out.writeInt(1);
17253                 out.writeString(ent.getKey());
17254                 kwlt.writeSummaryFromParcelLocked(out, nowRealtime);
17255             } else {
17256                 out.writeInt(0);
17257             }
17258         }
17259 
17260         out.writeInt(mWakeupReasonStats.size());
17261         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
17262             SamplingTimer timer = ent.getValue();
17263             if (timer != null) {
17264                 out.writeInt(1);
17265                 out.writeString(ent.getKey());
17266                 timer.writeSummaryFromParcelLocked(out, nowRealtime);
17267             } else {
17268                 out.writeInt(0);
17269             }
17270         }
17271 
17272         out.writeInt(mKernelMemoryStats.size());
17273         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
17274             Timer kmt = mKernelMemoryStats.valueAt(i);
17275             if (kmt != null) {
17276                 out.writeInt(1);
17277                 out.writeLong(mKernelMemoryStats.keyAt(i));
17278                 kmt.writeSummaryFromParcelLocked(out, nowRealtime);
17279             } else {
17280                 out.writeInt(0);
17281             }
17282         }
17283 
17284         final int NU = mUidStats.size();
17285         out.writeInt(NU);
17286         for (int iu = 0; iu < NU; iu++) {
17287             out.writeInt(mUidStats.keyAt(iu));
17288             Uid u = mUidStats.valueAt(iu);
17289 
17290             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
17291             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, nowUptime,
17292                     nowRealtime);
17293 
17294             if (u.mWifiRunningTimer != null) {
17295                 out.writeInt(1);
17296                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17297             } else {
17298                 out.writeInt(0);
17299             }
17300             if (u.mFullWifiLockTimer != null) {
17301                 out.writeInt(1);
17302                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17303             } else {
17304                 out.writeInt(0);
17305             }
17306             if (u.mWifiScanTimer != null) {
17307                 out.writeInt(1);
17308                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17309             } else {
17310                 out.writeInt(0);
17311             }
17312             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
17313                 if (u.mWifiBatchedScanTimer[i] != null) {
17314                     out.writeInt(1);
17315                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17316                 } else {
17317                     out.writeInt(0);
17318                 }
17319             }
17320             if (u.mWifiMulticastTimer != null) {
17321                 out.writeInt(1);
17322                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17323             } else {
17324                 out.writeInt(0);
17325             }
17326             if (u.mAudioTurnedOnTimer != null) {
17327                 out.writeInt(1);
17328                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17329             } else {
17330                 out.writeInt(0);
17331             }
17332             if (u.mVideoTurnedOnTimer != null) {
17333                 out.writeInt(1);
17334                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17335             } else {
17336                 out.writeInt(0);
17337             }
17338             if (u.mFlashlightTurnedOnTimer != null) {
17339                 out.writeInt(1);
17340                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17341             } else {
17342                 out.writeInt(0);
17343             }
17344             if (u.mCameraTurnedOnTimer != null) {
17345                 out.writeInt(1);
17346                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17347             } else {
17348                 out.writeInt(0);
17349             }
17350             if (u.mForegroundActivityTimer != null) {
17351                 out.writeInt(1);
17352                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17353             } else {
17354                 out.writeInt(0);
17355             }
17356             if (u.mForegroundServiceTimer != null) {
17357                 out.writeInt(1);
17358                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17359             } else {
17360                 out.writeInt(0);
17361             }
17362             if (u.mAggregatedPartialWakelockTimer != null) {
17363                 out.writeInt(1);
17364                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17365             } else {
17366                 out.writeInt(0);
17367             }
17368             if (u.mBluetoothScanTimer != null) {
17369                 out.writeInt(1);
17370                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17371             } else {
17372                 out.writeInt(0);
17373             }
17374             if (u.mBluetoothUnoptimizedScanTimer != null) {
17375                 out.writeInt(1);
17376                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17377             } else {
17378                 out.writeInt(0);
17379             }
17380             if (u.mBluetoothScanResultCounter != null) {
17381                 out.writeInt(1);
17382                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
17383             } else {
17384                 out.writeInt(0);
17385             }
17386             if (u.mBluetoothScanResultBgCounter != null) {
17387                 out.writeInt(1);
17388                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
17389             } else {
17390                 out.writeInt(0);
17391             }
17392             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
17393                 if (u.mProcessStateTimer[i] != null) {
17394                     out.writeInt(1);
17395                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17396                 } else {
17397                     out.writeInt(0);
17398                 }
17399             }
17400             if (u.mVibratorOnTimer != null) {
17401                 out.writeInt(1);
17402                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17403             } else {
17404                 out.writeInt(0);
17405             }
17406 
17407             if (u.mUserActivityCounters == null) {
17408                 out.writeInt(0);
17409             } else {
17410                 out.writeInt(1);
17411                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
17412                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
17413                 }
17414             }
17415 
17416             if (u.mNetworkByteActivityCounters == null) {
17417                 out.writeInt(0);
17418             } else {
17419                 out.writeInt(1);
17420                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
17421                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
17422                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
17423                 }
17424                 if (u.mMobileRadioActiveTime != null) {
17425                     out.writeBoolean(true);
17426                     u.mMobileRadioActiveTime.writeToParcel(out);
17427                 } else {
17428                     out.writeBoolean(false);
17429                 }
17430                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
17431             }
17432 
17433             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
17434             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
17435 
17436             if (u.mCpuClusterSpeedTimesUs != null) {
17437                 out.writeInt(1);
17438                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
17439                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
17440                     if (cpuSpeeds != null) {
17441                         out.writeInt(1);
17442                         out.writeInt(cpuSpeeds.length);
17443                         for (LongSamplingCounter c : cpuSpeeds) {
17444                             if (c != null) {
17445                                 out.writeInt(1);
17446                                 c.writeSummaryFromParcelLocked(out);
17447                             } else {
17448                                 out.writeInt(0);
17449                             }
17450                         }
17451                     } else {
17452                         out.writeInt(0);
17453                     }
17454                 }
17455             } else {
17456                 out.writeInt(0);
17457             }
17458 
17459             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
17460             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
17461 
17462             if (u.mCpuActiveTimeMs != null) {
17463                 out.writeInt(u.mCpuActiveTimeMs.getStateCount());
17464                 u.mCpuActiveTimeMs.writeToParcel(out);
17465             } else {
17466                 out.writeInt(0);
17467             }
17468 
17469             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
17470 
17471             if (u.mProcStateTimeMs != null) {
17472                 out.writeInt(u.mProcStateTimeMs.getStateCount());
17473                 u.mProcStateTimeMs.writeToParcel(out);
17474             } else {
17475                 out.writeInt(0);
17476             }
17477 
17478             if (u.mProcStateScreenOffTimeMs != null) {
17479                 out.writeInt(u.mProcStateScreenOffTimeMs.getStateCount());
17480                 u.mProcStateScreenOffTimeMs.writeToParcel(out);
17481             } else {
17482                 out.writeInt(0);
17483             }
17484 
17485             if (u.mMobileRadioApWakeupCount != null) {
17486                 out.writeInt(1);
17487                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
17488             } else {
17489                 out.writeInt(0);
17490             }
17491 
17492             if (u.mWifiRadioApWakeupCount != null) {
17493                 out.writeInt(1);
17494                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
17495             } else {
17496                 out.writeInt(0);
17497             }
17498 
17499             EnergyConsumerStats.writeSummaryToParcel(u.mUidEnergyConsumerStats, out);
17500 
17501             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
17502             int NW = wakeStats.size();
17503             out.writeInt(NW);
17504             for (int iw=0; iw<NW; iw++) {
17505                 out.writeString(wakeStats.keyAt(iw));
17506                 Uid.Wakelock wl = wakeStats.valueAt(iw);
17507                 if (wl.mTimerFull != null) {
17508                     out.writeInt(1);
17509                     wl.mTimerFull.writeSummaryFromParcelLocked(out, nowRealtime);
17510                 } else {
17511                     out.writeInt(0);
17512                 }
17513                 if (wl.mTimerPartial != null) {
17514                     out.writeInt(1);
17515                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, nowRealtime);
17516                 } else {
17517                     out.writeInt(0);
17518                 }
17519                 if (wl.mTimerWindow != null) {
17520                     out.writeInt(1);
17521                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, nowRealtime);
17522                 } else {
17523                     out.writeInt(0);
17524                 }
17525                 if (wl.mTimerDraw != null) {
17526                     out.writeInt(1);
17527                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, nowRealtime);
17528                 } else {
17529                     out.writeInt(0);
17530                 }
17531             }
17532 
17533             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
17534             int NS = syncStats.size();
17535             out.writeInt(NS);
17536             for (int is=0; is<NS; is++) {
17537                 out.writeString(syncStats.keyAt(is));
17538                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, nowRealtime);
17539             }
17540 
17541             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
17542             int NJ = jobStats.size();
17543             out.writeInt(NJ);
17544             for (int ij=0; ij<NJ; ij++) {
17545                 out.writeString(jobStats.keyAt(ij));
17546                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, nowRealtime);
17547             }
17548 
17549             u.writeJobCompletionsToParcelLocked(out);
17550 
17551             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
17552             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
17553             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
17554             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
17555                 if (u.mJobsFreshnessBuckets[i] != null) {
17556                     out.writeInt(1);
17557                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
17558                 } else {
17559                     out.writeInt(0);
17560                 }
17561             }
17562 
17563             int NSE = u.mSensorStats.size();
17564             out.writeInt(NSE);
17565             for (int ise=0; ise<NSE; ise++) {
17566                 out.writeInt(u.mSensorStats.keyAt(ise));
17567                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
17568                 if (se.mTimer != null) {
17569                     out.writeInt(1);
17570                     se.mTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17571                 } else {
17572                     out.writeInt(0);
17573                 }
17574             }
17575 
17576             int NP = u.mProcessStats.size();
17577             out.writeInt(NP);
17578             for (int ip=0; ip<NP; ip++) {
17579                 out.writeString(u.mProcessStats.keyAt(ip));
17580                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
17581                 out.writeLong(ps.mUserTimeMs);
17582                 out.writeLong(ps.mSystemTimeMs);
17583                 out.writeLong(ps.mForegroundTimeMs);
17584                 out.writeInt(ps.mStarts);
17585                 out.writeInt(ps.mNumCrashes);
17586                 out.writeInt(ps.mNumAnrs);
17587                 ps.writeExcessivePowerToParcelLocked(out);
17588             }
17589 
17590             NP = u.mPackageStats.size();
17591             out.writeInt(NP);
17592             if (NP > 0) {
17593                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
17594                     : u.mPackageStats.entrySet()) {
17595                     out.writeString(ent.getKey());
17596                     Uid.Pkg ps = ent.getValue();
17597                     final int NWA = ps.mWakeupAlarms.size();
17598                     out.writeInt(NWA);
17599                     for (int iwa=0; iwa<NWA; iwa++) {
17600                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
17601                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
17602                     }
17603                     NS = ps.mServiceStats.size();
17604                     out.writeInt(NS);
17605                     for (int is=0; is<NS; is++) {
17606                         out.writeString(ps.mServiceStats.keyAt(is));
17607                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
17608                         long time = ss.getStartTimeToNowLocked(
17609                                 mOnBatteryTimeBase.getUptime(nowUptime) / 1000);
17610                         out.writeLong(time);
17611                         out.writeInt(ss.mStarts);
17612                         out.writeInt(ss.mLaunches);
17613                     }
17614                 }
17615             }
17616         }
17617 
17618         if (!Flags.disableSystemServicePowerAttr()) {
17619             LongSamplingCounterArray.writeSummaryToParcelLocked(out, mBinderThreadCpuTimesUs);
17620         }
17621     }
17622 
17623     /**
17624      * Persists the monotonic clock associated with battery stats.
17625      */
17626     public void commitMonotonicClock() {
17627         mMonotonicClock.write();
17628     }
17629 
17630     @GuardedBy("this")
17631     public void prepareForDumpLocked() {
17632         // Need to retrieve current kernel wake lock stats before printing.
17633         pullPendingStateUpdatesLocked();
17634 
17635         // Pull the clock time.  This may update the time and make a new history entry
17636         // if we had originally pulled a time before the RTC was set.
17637         getStartClockTime();
17638 
17639         if (!Flags.disableSystemServicePowerAttr()) {
17640             updateSystemServiceCallStats();
17641         }
17642     }
17643 
17644     @GuardedBy("this")
17645     public void dump(Context context, PrintWriter pw, int flags, int reqUid, long histStart,
17646             BatteryStatsDumpHelper dumpHelper) {
17647         if (DEBUG) {
17648             pw.println("mOnBatteryTimeBase:");
17649             mOnBatteryTimeBase.dump(pw, "  ");
17650             pw.println("mOnBatteryScreenOffTimeBase:");
17651             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
17652             Printer pr = new PrintWriterPrinter(pw);
17653             pr.println("*** Screen on timer:");
17654             mScreenOnTimer.logState(pr, "  ");
17655             pr.println("*** Screen doze timer:");
17656             mScreenDozeTimer.logState(pr, "  ");
17657             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
17658                 pr.println("*** Screen brightness #" + i + ":");
17659                 mScreenBrightnessTimer[i].logState(pr, "  ");
17660             }
17661             pr.println("*** Interactive timer:");
17662             mInteractiveTimer.logState(pr, "  ");
17663             pr.println("*** Power save mode timer:");
17664             mPowerSaveModeEnabledTimer.logState(pr, "  ");
17665             pr.println("*** Device idle mode light timer:");
17666             mDeviceIdleModeLightTimer.logState(pr, "  ");
17667             pr.println("*** Device idle mode full timer:");
17668             mDeviceIdleModeFullTimer.logState(pr, "  ");
17669             pr.println("*** Device light idling timer:");
17670             mDeviceLightIdlingTimer.logState(pr, "  ");
17671             pr.println("*** Device idling timer:");
17672             mDeviceIdlingTimer.logState(pr, "  ");
17673             pr.println("*** Phone timer:");
17674             mPhoneOnTimer.logState(pr, "  ");
17675             for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
17676                 pr.println("*** Phone signal strength #" + i + ":");
17677                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
17678             }
17679             pr.println("*** Signal scanning :");
17680             mPhoneSignalScanningTimer.logState(pr, "  ");
17681             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
17682                 pr.println("*** Data connection type #" + i + ":");
17683                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
17684             }
17685             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
17686             pr.println("*** Mobile network active timer:");
17687             mMobileRadioActiveTimer.logState(pr, "  ");
17688             pr.println("*** Mobile network active adjusted timer:");
17689             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
17690             pr.println("*** Wifi Multicast WakeLock Timer:");
17691             mWifiMulticastWakelockTimer.logState(pr, "  ");
17692             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
17693             pr.println("*** Wifi timer:");
17694             mWifiOnTimer.logState(pr, "  ");
17695             pr.println("*** WifiRunning timer:");
17696             mGlobalWifiRunningTimer.logState(pr, "  ");
17697             for (int i=0; i<NUM_WIFI_STATES; i++) {
17698                 pr.println("*** Wifi state #" + i + ":");
17699                 mWifiStateTimer[i].logState(pr, "  ");
17700             }
17701             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
17702                 pr.println("*** Wifi suppl state #" + i + ":");
17703                 mWifiSupplStateTimer[i].logState(pr, "  ");
17704             }
17705             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
17706                 pr.println("*** Wifi signal strength #" + i + ":");
17707                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
17708             }
17709             for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
17710                 pr.println("*** GPS signal quality #" + i + ":");
17711                 mGpsSignalQualityTimer[i].logState(pr, "  ");
17712             }
17713             pr.println("*** Flashlight timer:");
17714             mFlashlightOnTimer.logState(pr, "  ");
17715             pr.println("*** Camera timer:");
17716             mCameraOnTimer.logState(pr, "  ");
17717         }
17718         super.dump(context, pw, flags, reqUid, histStart, dumpHelper);
17719 
17720         synchronized (this) {
17721             pw.print("Per process state tracking available: ");
17722             pw.println(trackPerProcStateCpuTimes());
17723             pw.print("Total cpu time reads: ");
17724             pw.println(mNumSingleUidCpuTimeReads);
17725             pw.print("Batching Duration (min): ");
17726             pw.println((mClock.uptimeMillis() - mCpuTimeReadsTrackingStartTimeMs) / (60 * 1000));
17727             pw.print("All UID cpu time reads since the later of device start or stats reset: ");
17728             pw.println(mNumAllUidCpuTimeReads);
17729             pw.print("UIDs removed since the later of device start or stats reset: ");
17730             pw.println(mNumUidsRemoved);
17731 
17732             mPowerStatsUidResolver.dump(pw);
17733 
17734             pw.println();
17735             dumpConstantsLocked(pw);
17736 
17737             pw.println();
17738             mCpuPowerStatsCollector.dumpCpuPowerBracketsLocked(pw);
17739 
17740             pw.println();
17741             dumpEnergyConsumerStatsLocked(pw);
17742         }
17743     }
17744 }
17745